自动无限轮播广告栏

自动滑动广告栏是比较常用的功能之一,方法一是使用的是一个第三方工具AutoScrollViewPager,方法二使用的是自定义控件实现需要的要求.

1.AutoScrollViewPager

第三方库,github地址:
https://github.com/Trinea/android-auto-scroll-view-pager

直接使用在线导包:

  compile('cn.trinea.android.view.autoscrollviewpager:android-auto-scroll-view-pager:1.1.2') {
        exclude module: 'support-v4'
    }

开始使用:

①在布局中使用控件

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/activity_main"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="com.simon.autobanner.MainActivity">

    <cn.trinea.android.view.autoscrollviewpager.AutoScrollViewPager
        android:id="@+id/main_autoscrollviewpager"
        android:layout_width="match_parent"
        android:layout_height="175dp"/>
</RelativeLayout>

②创建Adapter,继承PagerAdapter

因为这个控件是ViewPager,要用到Adapter(适配器)来展现数据
Activity代码

public class MainActivity extends AppCompatActivity {

    private AutoScrollViewPager mAutoscrollViewPager;
    private MyViewPagerAdapter mMyViewPagerAdapter;
    private ArrayList<ImageView> mImageViews;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        initData();
        initView();

    }

    private void initData() {
        //模拟广告图片,一般是从网络后台获取
        mImageViews = new ArrayList<>();

        ImageView img1 = new ImageView(this);
        img1.setScaleType(ImageView.ScaleType.FIT_XY);
        img1.setImageResource(R.mipmap.mao1);
        mImageViews.add(img1);

        ImageView img2= new ImageView(this);
        img2.setScaleType(ImageView.ScaleType.FIT_XY);
        img2.setImageResource(R.mipmap.mao2);
        mImageViews.add(img2);

        ImageView img3 = new ImageView(this);
        img3.setScaleType(ImageView.ScaleType.FIT_XY);
        img3.setImageResource(R.mipmap.mao3);
        mImageViews.add(img3);

        ImageView img4 = new ImageView(this);
        img4.setScaleType(ImageView.ScaleType.FIT_XY);
        img4.setImageResource(R.mipmap.mao4);
        mImageViews.add(img4);

    }

    private void initView() {
        //找到控件id
        mAutoscrollViewPager = (AutoScrollViewPager) findViewById(R.id.main_autoscrollviewpager);
        //new出Adapter
        mMyViewPagerAdapter = new MyViewPagerAdapter(this);
        //传入数据
        mMyViewPagerAdapter.setDatas(mImageViews);
        //绑定ViewPager和adapter
        mAutoscrollViewPager.setAdapter(mMyViewPagerAdapter);
        //启动自动滑动
        mAutoscrollViewPager.startAutoScroll();

    }
}

adapter代码

public class MyViewPagerAdapter extends PagerAdapter {
    private final Context context;
    private ArrayList<ImageView> mDatas;

    public MyViewPagerAdapter(Context context) {
        this.context = context;
    }

    public void setDatas(ArrayList<ImageView> imageViews){
       mDatas=imageViews;
    }

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

    @Override
    public boolean isViewFromObject(View view, Object object) {
        return view == object;
    }

    //还需要重写两个方法instantiateItem和destroyItem
    //将某一项视图添加ViewPager中
    @Override
    public Object instantiateItem(ViewGroup container, int position) {
        ImageView imageView = mDatas.get(position);
        container.addView(imageView);
        //返回图片视图
        return imageView;
    }

    //将某一项视图从ViewPager中销毁
    @Override
    public void destroyItem(ViewGroup container, int position, Object object) {
        ImageView imageView = mDatas.get(position);
        container.removeView(imageView);
    }
}

③添加指示器

 /***
     * 初始化指示器
     */
    private void initAdBannerIndicator(int size) {
        //1.做一个for循环
        //2.创建图片控件 要设置宽高  绑定shapDrawable  添加到容器中
        //3.默认让第一个选中
        for (int i = 0; i < size; i++) {
            ImageView iv = new ImageView(this);
            LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(15, 15);//px
            params.setMargins(20, 0, 0, 0);
            iv.setLayoutParams(params);
            iv.setBackgroundResource(R.drawable.ad_indicator_bg);
            mAdIndicator.addView(iv);
        }
        //启动时默认为第一个
        changeAdIndicator(0);
    }

    /**
     * 修改广告栏的指示器
     */
    private void changeAdIndicator(int position) {
        int childCount = mAdIndicator.getChildCount();
        for (int i = 0; i < childCount; i++) {
            //getChildAt 获取某个容器内部的位置为i的子控件
            mAdIndicator.getChildAt(i).setSelected(i == position);
        }
    }

要让指示器随着广告的变化而变化,要给ViewPager设置监听器,获取ViewPager当前位置,然后修改指示器,从而达到效果

//找到指示器的容器id
        mAdIndicator = (LinearLayout) findViewById(R.id.ad_indicator);
        initAdBannerIndicator(mImageViews.size());
        //设置监听器
        mAutoscrollViewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
            @Override
            public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {

            }

            @Override
            public void onPageSelected(int position) {
                changeAdIndicator(position);
            }

            @Override
            public void onPageScrollStateChanged(int state) {

            }
        });

但是这里还有一点小问题,就是从最后一页返回第一页时,效果不太好,可以通过重写某个方法达到想要的效果,原理与下面的方法相同,所以这里就不重复了.

④其他属性设置

setInterval(long) 设置自动滚动的间隔时间,单位为毫秒
setDirection(int) 设置自动滚动的方向,默认向右
setCycle(boolean) 是否自动循环轮播,默认为true
setScrollDurationFactor(double) 设置ViewPager滑动动画间隔时间的倍率,达到减慢动画或改变动画速度的效果
setStopScrollWhenTouch(boolean) 当手指碰到ViewPager时是否停止自动滚动,默认为true
setSlideBorderMode(int) 滑动到第一个或最后一个Item的处理方式,支持没有任何操作、轮播以及传递到父View三种模式
setBorderAnimation(boolean) 设置循环滚动时滑动到从边缘滚动到下一个是否需要动画,默认为true

2.自定义广告轮播控件

采用自定义控件的方法,做出一个能达到想要的效果的广告轮播控件

①创建一个新的类BannerScrollView,继承RelativeLayout

实现构造方法,并模拟了数据

    public BannerScrollView(Context context) {
        super(context);
    }

    public BannerScrollView(Context context, AttributeSet attrs) {
        super(context, attrs);
        initData();
        initView();

    }

    private void initView() {
        //因为是继承了系统的控件,所以在加载布局的时候需要与父布局绑定
        View view = View.inflate(getContext(), R.layout.view_banner, this);

        mBannerVp = (ViewPager) view.findViewById(R.id.banner_vp);
        mBannerRl = (RelativeLayout) view.findViewById(R.id.banner_rl);
        mBannerTvTitle = (TextView) view.findViewById(R.id.banner_tv_title);
        mBannerLlIndicator = (LinearLayout) view.findViewById(R.id.banner_ll_indicator);

        //创建adapter
        mBannerScrollAdapter = new BannerScrollAdapter();
        mBannerScrollAdapter.setDatas(mImageViews);
        //绑定ViewPager和adapter
        mBannerVp.setAdapter(mBannerScrollAdapter);
    }

    private void initData() {
        mImageViews = new ArrayList<>();

        //根据业务需求,把传进来的数据进行网络请求,再转为图片格式放入imageView
        //现在只能模拟数据,直接放入图片
        ImageView img1 = new ImageView(getContext());
        img1.setScaleType(ImageView.ScaleType.FIT_XY);
        img1.setImageResource(R.mipmap.mao1);
        mImageViews.add(img1);

        ImageView img2 = new ImageView(getContext());
        img2.setScaleType(ImageView.ScaleType.FIT_XY);
        img2.setImageResource(R.mipmap.mao2);
        mImageViews.add(img2);

        ImageView img3 = new ImageView(getContext());
        img3.setScaleType(ImageView.ScaleType.FIT_XY);
        img3.setImageResource(R.mipmap.mao3);
        mImageViews.add(img3);

        ImageView img4 = new ImageView(getContext());
        img4.setScaleType(ImageView.ScaleType.FIT_XY);
        img4.setImageResource(R.mipmap.mao4);
        mImageViews.add(img4);


    }

②创建适配器adapter

public class BannerScrollAdapter extends PagerAdapter {

    private ArrayList<ImageView> mBannerImg;

    public void setDatas(ArrayList<ImageView> bannerImg) {
        mBannerImg = bannerImg;
    }

    @Override
    public int getCount() {
        //把数量写成integer的最大值,这就能实现无限播放了
        return Integer.MAX_VALUE;
        //        return mBannerImg.size();
    }

    @Override
    public boolean isViewFromObject(View view, Object object) {
        return view == object;
    }

    @Override
    public Object instantiateItem(ViewGroup container, int position) {
        //防止数引越界
        position = position % mBannerImg.size();
        ImageView imageView = mBannerImg.get(position);
        container.addView(imageView);
        return imageView;
    }


    @Override
    public void destroyItem(ViewGroup container, int position, Object object) {
        position = position%mBannerImg.size();
        ImageView imageView = mBannerImg.get(position);
        container.removeView(imageView);
    }
}

现在已经实现了ViewPager的效果,而且能够无限滑动

③让广告自动轮播

让广告自动轮播的方法不只一种,我这里用的是Handler发送延迟消息,来进行轮播

Handler mHandler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
           //① int position = msg.what;int position=mBannerVp.getCurrentItem();
            position++;
            mBannerVp.setCurrentItem(position);
            sendEmptyMessageDelayed(position, 2000);
        }
    };

这里有一个bug,①中position值是从handler发送过来的mBannerVp.getCurrentItem(),但是如果使用这个值的话,当广告栏往回滑的时候就会报错,而使用②中再次获取mBannerVp.getCurrentItem()值后就可以正常运行.
经过打印log得知,①中的数据不是期望的值,具体的原因可能需要查看源代码才能知道.

④添加ViewPager的触摸事件

现在已经实现了广告的轮播效果,但是现在的代码还有很多的问题
1.当你想手动滑动广告的时候,广告还是会自动轮播.
2.当你往回滑时,程序会报错,而且错误不只是一个.

给ViewPager添加触摸事件可以暂时解决这两个问题,让程序能进行下去,但是有时还是会报错,暂时还没找到原因.

mBannerVp.setOnTouchListener(new OnTouchListener() {
            @Override
            public boolean onTouch(View v, MotionEvent event) {
                int action = event.getAction();
                switch (action) {
                    //当按下时,停止给handler发送消息
                    case MotionEvent.ACTION_DOWN:
                        mHandler.removeCallbacksAndMessages(null);
                        break;
                    //当松开或者手指已经离开ViewPager范围后,会重新发送消息,继续轮播
                    case MotionEvent.ACTION_CANCEL:
                    case MotionEvent.ACTION_UP:
                        mHandler.sendEmptyMessageDelayed(mBannerVp.getCurrentItem(), 1000);
                        break;
                }
                return false;
            }
        });

效果:
这里写图片描述

⑤最后加上指示器

//初始化指示器
    private void initDot() {
        LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
        layoutParams.setMargins(0, 0, 8, 0);

        for (int i = 0; i < mImageViews.size(); i++) {
            ImageView imageView = new ImageView(getContext());
            imageView.setImageResource(R.drawable.bg_dot_selected);
            mBannerLlIndicator.addView(imageView, layoutParams);
        }
        //从第一个开始
        selectDot(0);
    }

    //改变指示器的显示,显示当前位置
    private void selectDot(int position) {
        int size = mImageViews.size();
        position = position % size;
        for (int i = 0; i < size; i++) {
            ImageView childAt = (ImageView) mBannerLlIndicator.getChildAt(i);
            if (position == i) {
                childAt.setImageResource(R.drawable.bg_dot);
            } else {
                childAt.setImageResource(R.drawable.bg_dot_selected);
            }
        }
    }


    //设置ViewPager的监听器,监听当前pager的位置,并修改指示器位置
        mBannerVp.setOnPageChangeListener(new ViewPager.OnPageChangeListener() {
            @Override
            public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {

            }

            @Override
            public void onPageSelected(int position) {
                selectDot(position);
            }

            @Override
            public void onPageScrollStateChanged(int state) {

            }
        });

完成,最终效果如图:
![enter description here][4]

猜你喜欢

转载自blog.csdn.net/fong_simon/article/details/73718833