自动滑动广告栏

自动滑动广告栏是比较常用的功能之一,方法一是使用的是一个第三方工具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的效果,而且能够无限滑动

adimg1.gif

③让广告自动轮播

让广告自动轮播的方法不只一种,我这里用的是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;
            }
        });

效果:

adimg2.gif

⑤最后加上指示器

//初始化指示器
    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) {

            }
        });

完成,最终效果如图:

adimg3.gif
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,590评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 86,808评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,151评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,779评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,773评论 5 367
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,656评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,022评论 3 398
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,678评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 41,038评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,659评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,756评论 1 330
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,411评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,005评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,973评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,203评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,053评论 2 350
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,495评论 2 343

推荐阅读更多精彩内容