关于自定义无限轮播图_Android

首先看一下效果图

下载地址Demo

废话不多说上代码了

首先看我们自定义的可以设置是否可以滑动的viewpager

package cn.yuan.banner;

import android.content.Context;
import android.support.v4.view.ViewPager;
import android.util.AttributeSet;
import android.view.MotionEvent;

/**
 * Created by yukuo on 2016/5/10.
 * 一个可以自己设置是否可以滚动的viewpager
 */
public class SetingScrollBanner extends ViewPager {
    public SetingScrollBanner(Context context) {
        super(context);
    }

    public SetingScrollBanner(Context context, AttributeSet attrs) {
        super(context, attrs);
    }
    private boolean scrollable = true;

    /**
     * 设置viewpager是否可以滚动
     *
     * @param enable
     */
    public void setScrollable(boolean enable) {
        scrollable = enable;
    }

    @Override
    public boolean onInterceptTouchEvent(MotionEvent event) {
        if (scrollable) {
            return super.onInterceptTouchEvent(event);
        } else {
            return false;
        }
    }
}

然后看我们的主要的自定义的控件

package cn.yuan.banner;

import android.content.Context;
import android.os.Handler;
import android.os.Message;
import android.support.v4.view.PagerAdapter;
import android.support.v4.view.ViewPager;
import android.util.AttributeSet;
import android.view.View;
import android.view.ViewGroup;
import android.widget.FrameLayout;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.RelativeLayout;

import java.util.ArrayList;
import java.util.List;

/**
 * Created by yukuo on 2016/5/10.
 * 这是一个横向滚动的viewpager
 */
public class BannerViewPager extends LinearLayout implements ViewPager.OnPageChangeListener {
    private OnItemClickListener onItemClickListener;
    private FrameLayout fl_banner_viewpager;
    private LinearLayout ll_scroll_banner_indicator;
    private SetingScrollBanner vp_banner;
    private List<String> list = new ArrayList<>();//数据源集合
    private List<ImageView> imageViews = new ArrayList<ImageView>();//图片集合
    private int scrolltime = 3000; // 默认滚动时间
    private long releaseTime = 0; // 手指松开、页面不滚动时间,防止手机松开后短时间进行切换
    private int LOOP = 200; // 转动
    private int LOOP_WAIT = 201; // 等待
    //是否循环 默认循环
    private boolean isLoop = true;
    private boolean isWheel = true; // 是否轮播
    private boolean isScrolling = false;//是否在滚动
    private ImageView[] indicators;
    private ViewPagerAdapter viewPagerAdapter;
    private int currentPosition;
    private Handler handler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            if (msg.what == LOOP && imageViews.size() != 0) {
                if (!isScrolling) {
                    int max = imageViews.size() + 1;
                    int position = (currentPosition + 1) % imageViews.size();
                    vp_banner.setCurrentItem(position, true);
                    if (position == max) { // 最后一页时回到第一页
                        vp_banner.setCurrentItem(1, false);
                    }
                }

                releaseTime = System.currentTimeMillis();
                handler.removeCallbacks(runnable);
                handler.postDelayed(runnable, scrolltime);
                return;
            }
            if (msg.what == LOOP_WAIT && imageViews.size() != 0) {
                handler.removeCallbacks(runnable);
                handler.postDelayed(runnable, scrolltime);
            }

        }
    };

    public BannerViewPager(Context context) {
        super(context);
        init(context);
    }

    public BannerViewPager(Context context, AttributeSet attrs) {
        super(context, attrs);
        init(context);
    }

    private void init(Context context) {
        //设置宽高
        setLayoutParams(new ViewGroup.LayoutParams(
                ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT));
        View view = View.inflate(context, R.layout.view_scrollbanner, null);
        fl_banner_viewpager = (FrameLayout) view.findViewById(R.id.fl_banner_viewpager);
        vp_banner = (SetingScrollBanner) view.findViewById(R.id.vp_banner);
        ll_scroll_banner_indicator = (LinearLayout) view.findViewById(R.id.ll_scroll_banner_indicator);
        addView(view);
    }

    /**
     * 设置数据源
     *
     * @param views    viee集合
     * @param list     数据源集合
     * @param listener 回调监听
     */
    public void setData(List<ImageView> views, List<String> list, OnItemClickListener listener) {
        setData(views, list, listener, 0);
    }

    /**
     * 设置是否轮播,默认不轮播,轮播一定是循环的
     *
     * @param isWheel
     */
    public void setWheel(boolean isWheel) {
        this.isWheel = isWheel;
        isLoop = true;
        if (isWheel) {
            handler.postDelayed(runnable, scrolltime);
        }
    }

    /**
     * 是否处于轮播状态
     *
     * @return
     */
    public boolean isWheel() {
        return isWheel;
    }

    /**
     * 设置数据源
     *
     * @param views        view集合
     * @param list         数据源集合
     * @param listener     回调监听
     * @param showPosition 默认选中的位置
     */
    public void setData(List<ImageView> views, List<String> list, OnItemClickListener listener, int showPosition) {
        this.onItemClickListener = listener;
        this.list = list;
        imageViews.clear();
        /**
         * 如果没有数据的话就隐藏展示
         */
        if (list.size() == 0) {
            fl_banner_viewpager.setVisibility(View.GONE);
            return;
        }
        /**
         * 如果只有一个图片就不显示下边的指针了
         */
        if (list.size() == 1) {
            setScrollable(false);
            ll_scroll_banner_indicator.setVisibility(View.GONE);

        }
        //添加数据
        for (ImageView item : views) {
            this.imageViews.add(item);
        }
        //设置指示器
        int ivSize = views.size();
        indicators = new ImageView[ivSize];
        //如果是需呀循环的话就重新设置指示器
        if (isLoop)
            indicators = new ImageView[ivSize - 2];
        ll_scroll_banner_indicator.removeAllViews();
        for (int i = 0; i < indicators.length; i++) {
            View view = View.inflate(getContext(), R.layout.view_banner_viewpager_indicator, null);
            indicators[i] = (ImageView) view.findViewById(R.id.iv_baner_indicator);
            ll_scroll_banner_indicator.addView(view);
        }
        viewPagerAdapter = new ViewPagerAdapter();
        // 默认指向第一项,下方viewPager.setCurrentItem将触发重新计算指示器指向
        setIndicator(0);
        vp_banner.setOffscreenPageLimit(3);//默认缓存所有的界面
        vp_banner.setOnPageChangeListener(this);
        vp_banner.setAdapter(viewPagerAdapter);
        if (showPosition < 0 || showPosition > views.size()) {
            showPosition = 0;
        }
        if (isLoop) {
            showPosition = showPosition + 1;
        }
        vp_banner.setCurrentItem(showPosition);
    }

    /**
     * 设置指示器
     *
     * @param selectedPosition 默认指示器位置
     */
    private void setIndicator(int selectedPosition) {
        for (int i = 0; i < indicators.length; i++) {
            indicators[i]
                    .setBackgroundResource(R.drawable.icon_point);
        }
        if (indicators.length > selectedPosition)
            indicators[selectedPosition]
                    .setBackgroundResource(R.drawable.icon_point_pre);
    }

    /**
     * 是否循环,默认不开启,开启前,请将views的最前面与最后面各加入一个视图,用于循环
     * 如果需要设置请在添加数据之前的时候进行使用
     *
     * @param isLoop 是否循环
     */
    public void setLoop(boolean isLoop) {
        this.isLoop = isLoop;
    }

    /**
     * 是否处于循环状态
     *
     * @return
     */
    public boolean isLoop() {
        return isLoop;
    }

    final Runnable runnable = new Runnable() {

        @Override
        public void run() {
            if (getContext() != null
                    && isWheel) {
                long now = System.currentTimeMillis();
                // 检测上一次滑动时间与本次之间是否有触击(手滑动)操作,有的话等待下次轮播
                if (now - releaseTime > scrolltime - 500) {
                    handler.sendEmptyMessage(LOOP);
                } else {
                    handler.sendEmptyMessage(LOOP_WAIT);
                }
            }
        }
    };

    /**
     * 设置viewpager是否可以滚动
     *
     * @param enable 是否
     */
    public void setScrollable(boolean enable) {
        vp_banner.setScrollable(enable);
    }

    /**
     * 设置轮播暂停时间,即没多少秒切换到下一张视图.默认3000ms
     *
     * @param time 毫秒为单位
     */
    public void setScrollTime(int time) {
        this.scrolltime = time;
    }

    /**
     * 设置指示器居中,默认指示器在右方
     */
    public void setIndicatorCenter() {
        RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(
                RelativeLayout.LayoutParams.WRAP_CONTENT,
                RelativeLayout.LayoutParams.WRAP_CONTENT);
        params.addRule(RelativeLayout.ALIGN_PARENT_BOTTOM);
        params.addRule(RelativeLayout.CENTER_HORIZONTAL);
        ll_scroll_banner_indicator.setLayoutParams(params);
    }

    /**
     * 刷新数据,当外部视图更新后,通知刷新数据
     */
    public void refreshData() {
        if (viewPagerAdapter != null)
            viewPagerAdapter.notifyDataSetChanged();
    }

    /**
     * banner点击的监听器
     */
    public interface OnItemClickListener {
        /**
         * 条目点击回调的方法
         *
         * @param postion 位置
         */
        void onItemClick(int postion);
    }

    /**
     * 页面适配器 返回对应的view
     *
     * @author Yuedong Li
     */
    private class ViewPagerAdapter extends PagerAdapter {

        @Override
        public int getCount() {
            return imageViews.size();
        }

        @Override
        public boolean isViewFromObject(View arg0, Object arg1) {
            return arg0 == arg1;
        }

        @Override
        public void destroyItem(ViewGroup container, int position, Object object) {
            container.removeView((View) object);
        }

        @Override
        public View instantiateItem(ViewGroup container, final int position) {
            ImageView v = imageViews.get(position);
            if (onItemClickListener != null) {
                v.setOnClickListener(new View.OnClickListener() {
                    @Override
                    public void onClick(View v) {
                        if (list.size() == 1) {
                            onItemClickListener.onItemClick(0);
                        } else {
                            onItemClickListener.onItemClick(position - 1);
                        }
                    }
                });
            }
            container.addView(v);
            return v;
        }

        @Override
        public int getItemPosition(Object object) {
            return POSITION_NONE;
        }
    }

    /**
     * 隐藏Banner
     */
    public void hideBanner() {
        fl_banner_viewpager.setVisibility(View.GONE);
    }

    /**
     * 隐藏指示器
     */
    public void hideIndicator() {
        ll_scroll_banner_indicator.setVisibility(View.GONE);
    }

    @Override
    public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {

    }

    @Override
    public void onPageSelected(int position) {
        int max = imageViews.size() - 1;
        int positi = position;
        currentPosition = position;
        if (isLoop) {
            if (position == 0) {
                currentPosition = max - 1;
            } else if (position == max) {
                currentPosition = 1;
            }
            positi = currentPosition - 1;
        }
        setIndicator(positi);
    }

    @Override
    public void onPageScrollStateChanged(int state) {
        if (state == 1) { // viewPager在滚动
            isScrolling = true;
            return;
        } else if (state == 0) { // viewPager滚动结束
            if (vp_banner != null)
                vp_banner.setScrollable(true);

            releaseTime = System.currentTimeMillis();

            vp_banner.setCurrentItem(currentPosition, false);

        }
        isScrolling = false;
    }
}

用到的工具类

package cn.yuan.banner;

import android.content.Context;
import android.view.LayoutInflater;
import android.widget.ImageView;

import com.bumptech.glide.Glide;

/**
 * ImageView创建工厂
 */
public class ViewFactory {

    /**
     * 获取ImageView视图的同时加载显示url
     *
     * @param url
     * @return
     */
    public static ImageView getImageView(Context context, String url) {
        ImageView imageView = (ImageView)LayoutInflater.from(context).inflate(
                R.layout.item_view_banner, null);
        Glide.with(context).load(url).into(imageView);
        return imageView;
    }
}

至于如何使用.简单到没朋友,直接在xml文件当成一个控件应用就可以了

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <cn.yuan.banner.BannerViewPager
        android:id="@+id/fl_banner"
        android:layout_width="match_parent"
        android:layout_height="280dp"/>
</RelativeLayout>

好了.欢迎Fork和Star

Demo下载

时间: 2024-11-05 14:57:41

关于自定义无限轮播图_Android的相关文章

无限轮播图的制作

url:http://zjingwen.github.io/SetTimeOutGoBlog/webdemo/huanyouji/index.html (如果打开过慢,或者打不开,原因你懂得.) 一.思路 1.所有滑动效果的demo都是通过控制css里的left值,来控制滑动效果的. 2.需要两个块,一个div块,一个ui.div块的position是relative,ui块的position是absolute.这样ui块的left就可以根据外层的div来控制.div的overflow是hidd

无限轮播图

思路:在ScrollView的contentSiz设置成ScrollView宽的度的三倍.创建三个循环的View.当滑动的时候,正常滑动活动结束.滑动结束设置contentOffset将视图滑动到中间去.将后面的数据赋值到中间...简单说就是视图只显示中间一张视,交换数据实现不同数据的显示.. #import <UIKit/UIKit.h> @protocol YQImageLoopDelegate <NSObject> - (void)YQImageLoopConfigDataA

iOS 无限轮播图的两种实现

首先说一下实现的思想: 用UIScrollView实现,在scrollView上添加3个UIImageView,分别用来显示上一张图片,当前显示的图片,下一张图片.scrollView在不滑动的时候永远显示当前图片(第二张图片)即contentOffset = CGPointMake(scrollViewW,0),在滑动的时候可以预览部分上一张图片或下一张图片.现在以向左滑动为例,因为已经设置好三张图片,我们向左滑动可以看到下一张图片的一部分(此时屏幕显示着部分当前图片和部分下一张图片).如果完

无限轮播图特效

<!doctype html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Document</title> <style> *{ padding: 0; margin: 0; list-style: none; } img{ border: 0; } .box{ width: 200px; height: 300px;

Android 超简单自动无限轮播图LoopView

只需要你传入数据就可以了 效果图 demo地址 https://github.com/wanghao200906/Android-LoopView 效果实现 1.添加依赖库 2.添加到xml < com.kevin.loopview.AdLoopView android:id="@+id/main_act_adloopview" android:layout_width="match_parent" android:layout_height="54

自定义完美的ViewPager 真正无限循环的轮播图

网上80%的思路关于Android轮播图无限循环都是不正确的,不是真正意义上的无限循环, 其思路大多是将ViewPager的getCount方法返回值设置为Integer.MAX_VALUE, 然后呢将ViewPager的当前展示页设置为第1000页或者是10000页,这样用户一般情况下是滑不到边界的 例如有5张图片的轮播图,item的编号为(0,1,2,3,4)当前页的页号如果是5, 这时候就将编号设置为0,即 actPosition %= datas.size();这个公式就是这么来的 这种

Android开发之ViewPager实现轮播图(轮播广告)效果的自定义View

最近开发中需要做一个类似京东首页那样的广告轮播效果,于是采用ViewPager自己自定义了一个轮播图效果的View. 主要原理就是利用定时任务器定时切换ViewPager的页面. 效果图如下: 主页面布局实现如下: <?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android&

Objective-C UI之自定义轮播图控件

下面我们自定义一个轮播图类ImageLoop继承于UIView,类ImageLoop中包含一个UIScrollView和UIPageControl,其中定义三个属性: pageControll,position,currentPage可以自定义pageControl样式,也可以使用position控制播放方向,或者设置从下标为currentPage的图片开始播放 下面是ImageLoop的接口文件: #import <UIKit/UIKit.h> typedef enum{Left,Right

自定义View实现广告位轮播图barner组件

闲谈 最近公司事情不算太多,闲来无事,看到项目中用到的广告轮播图,之前都是使用第三方的,趁事情不算多,所以自己实现一个广告位轮播图barner组件,这样的话,在以后的开发中就可以使用自己的了. 知识点 好了,切入正题!我们要想实现barner组件,首先要求我们需要哪些知识点呢? 1.自定义View的流程(测量.布局.绘制) 2.广告位轮播图滑动的时候,我们需要弹性滑动Scroller 3.自定义View的事件传递机制 4.在我们自定义View事件传递给我们自定义的View的时候,我们在OnTou