Viewpager实现 轮播广告栏(BannerPager)

版权声明:保留记忆 https://blog.csdn.net/u012811342/article/details/79665307

实现这个功能的目前已经有很多种方式了,譬如说继承ViewGroup仿ViewPager通过adapter循环add、dstory指定的item,使用fragment添加移除view的方式,设置viewpager的索引条目达到上限==。以上几种方式属于Banner的常用选择,其中动效做的非常出色的如代码家的ImageSlider,曾经在项目中也引用过,不过在使用的过程中出现了内存开销过大的问题,1张图片也可以左右轮回切换的问题,不得不说是个硬伤。后来遇到了一种新的方式,于是分享出来给大家。

Banner和viewpgaer的最大区别是Banner可以在itemPosition=0和itemPosition=size-1之间来回无缝切换,因此我们理想状态是作如下处理的:当滑动到itemPosition=0的时候,左侧有对应itemPosition=0到itemPosition=size-1的view;当滑动到itemPosition=size-1的时候,右侧有对应itemPosition=0到itemPosition=size-1的view。这是我们一般直接的做法:设置viewpager的索引条目达到上限。然而开销的问题让我们会想到复用,结合listview的adapter的viewholder形式,可能会采取第i屏的第itemPosition=position的view复用第1屏的itemPosition=position的view。这样的做法看似不错,但是对于拥有着程序员思维的我们觉得这仅仅是一个逻辑不够严密,过程不够完美,存在潜藏的隐患的idea。于是两条道路,优化or另辟蹊径。

其实再做上述过程中的考虑时候,我们想到了复用,想到了设置size=Integer.MAX_VALUE实现itemPosition=0和itemPosition=size-1之间的切换,但是仔细考虑一下,我们也仅仅需要实现itemPosition=0和itemPosition=size-1之间的切换,就可以交给viewpager本身的机制来完成剩下页卡之间的轮播。假设一共需要展示4个view,于是画图如下:

... item=2 -> item=3 -> item=0 -> item=1 -> item=2 -> item=3 -> item=0 -> item=1 ...

也就是说我们发现可以考虑当itemPosition=3的时候下一屏itemPosition=0的view就是当前屏被滑动过去itemPosition=0的View,用来代替无限size=Integer.MAX_VALUE的实现方式,然而这样难点又回到了如和实现两者之间的无动画切换。于是我们想到实现size=Integer.MAX_VALUE的本质其实就是对viewpager不停的addView和destoryView,当滑动到itemPosition=0的时候在左侧添加一个itemPosition=3的view,当滑动到itemPosition=3的时候在右侧添加一个itemPosition=0的view,但是后续的itemPosition=1和itemPosition=2的view就可以不用我们手动add进去,因为viewpager的本质会自动默认itemPosition=3左侧、itemPosition=0右侧存在itemPosition=1、2的view,因此上述图我们可以简化成:

                       |<—————————————|     
itemPosition    3  ->  0  ->  1  ->  2  ->  3  ->  0
                |—————————————>|

于是我们把addView简化成了addView(0,item3View)和addView(5,item0View),而当加载到这两个view的时候我们认为它加载的其实就是itemPosition=3和itemPosition=0的view。认为这个词语在代码中的体现就是set,因此当我们在首尾各添加了一个view之后可以写出如下代码:

if(getCurrentPosition() == 0){
    setCurrentPosition(4);
}
if(getCurrentPosition() == 5){
    setCurrentPosition(1);
}

注:getCurrentPosition() == 0的时候其实相当于把item4的布局加到了item0的前面,此时数据就是item4的数据,所以把页面设置到item4;getCurrentPosition() == 5的时候其实相当于把item0的布局加到了item4的后面,此时数据就是item0的数据,所以把页面设置到item0

完整代码:

package com.systoon.business.home.holder;

import android.app.Activity;
import android.support.v4.view.PagerAdapter;
import android.support.v4.view.ViewPager;
import android.text.TextUtils;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;

import com.systoon.business.home.bean.HomeActivityBean;
import com.systoon.business.home.utils.CommonUtils;
import com.systoon.business.home.view.HomeNewsListActivity;
import com.systoon.toon.R;
import com.systoon.toon.common.utils.DateUtils;
import com.systoon.toon.common.utils.ScreenUtil;

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

public class QlLHomeNewsViewHolder extends BaseMainAppViewHolder {

    private final Activity mActivity;
    private ViewPager mViewpager;
    private LinearLayout mIndicateRoot;

    private LinearLayout mRootEmpty;
    private LinearLayout contentRoot;
    private TextView mTitle;
    private TextView mTime;
    private int currentItem;
    private TextView mMore;
    private List<HomeActivityBean> datas;
    private ArrayList<View> viewList;
    private int count;
    private long delayTime = 3000;
    private ViewPager.OnPageChangeListener mOnPageChangeListener;
    private WeakHandler handler = new WeakHandler();

    public QlLHomeNewsViewHolder(View itemView, ViewGroup parent, List<HomeActivityBean> mList,
                                 Activity activity) {
        super(itemView);
        mViewpager = (ViewPager) itemView.findViewById(R.id.news_banner);
        mIndicateRoot = (LinearLayout) itemView.findViewById(R.id.dot_indicate_root);
        contentRoot = (LinearLayout) itemView.findViewById(R.id.content_root);

        mTitle = (TextView) itemView.findViewById(R.id.news_title);
        mTime = (TextView) itemView.findViewById(R.id.time);
        mMore = (TextView) itemView.findViewById(R.id.btn_more);

        mActivity = activity;
        datas = mList;

    }

    @Override
    public void bindHolder(HomeActivityBean bean, int position) {
        super.bindHolder(bean, position);
        viewList = new ArrayList<>();
        final List<HomeActivityBean.ExtrasData> list = bean.getDataList();

        if (list != null) {

            count = list.size();
            mIndicateRoot.removeAllViews();
            View dot;

            if (count > 1) {// 多于一个轮播
                for (int i = 0; i < count + 2; i++) {
                    viewList.add(LayoutInflater.from(itemView.getContext()).inflate(R.layout
                                    .ql_home_show_type_banner_item_img,
                            null, false));

                    if (i < count) {
                        dot = new View(itemView.getContext());
                        mIndicateRoot.addView(dot, ScreenUtil.dp2px(6), ScreenUtil.dp2px(6));
                        setMargins(dot, ScreenUtil.dp2px(3), 0, ScreenUtil.dp2px(3), 0);
                    }
                }
            } else if (count == 1) {
                viewList.add(LayoutInflater.from(itemView.getContext()).inflate(R.layout
                                .ql_home_show_type_banner_item_img,
                        null, false));
            } else {// TODO 空界面处理

            }


            /**
             * banner
             */
            if (count > 0)
                mViewpager.setAdapter(new PagerAdapter() {


                    @Override
                    public int getCount() {
                        return count > 1 ? count + 2 : count;
                    }

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

                    @Override
                    public Object instantiateItem(final ViewGroup container, int position)
                    {//必须实现,实例化
                        View view = viewList.get(position);
                        final ImageView img = (ImageView) view.findViewById(R.id.img_content);
                        final HomeActivityBean.ExtrasData items;

                        if (count > 1) {
                            if (position == 0) {
                                items = list.get(count - 1);

                            } else if (position == count + 1) {
                                items = list.get(0);
                            } else {
                                items = list.get(position - 1);
                            }
                        } else {
                            items = list.get(position);
                        }

                        showImgRoundCrop("", img, img.getContext());
                        img.setOnClickListener(new View.OnClickListener() {
                            @Override
                            public void onClick(View v) {
                                if (TextUtils.isEmpty(items.getDescription())) {
                                    CommonUtils.goActivityH5(mActivity, items.getActivityId());
                                } else {

                                    CommonUtils.toNewsDetail(mActivity, items.getNewsId());
                                }
                                //  跳转
                            }
                        });


                        container.addView(view);
                        return view;
                    }

                    @Override
                    public void destroyItem(ViewGroup container, int position, Object object)
                    {//必须实现,销毁
                        container.removeView(viewList.get(position));
                    }

                });


            mViewpager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
                @Override
                public void onPageScrolled(int position, float positionOffset, int
                        positionOffsetPixels) {
                    if (mOnPageChangeListener != null) {
                        mOnPageChangeListener.onPageScrolled(toRealPosition(position, count),
                                positionOffset, positionOffsetPixels);
                    }

                }

                @Override
                public void onPageSelected(int position) {


                    currentItem = position;
                    if (mOnPageChangeListener != null) {
                        mOnPageChangeListener.onPageSelected(toRealPosition(position, count));
                    }
                    //   mPageIndex.setText(new StringBuilder().append(toRealPosition(position,
                    // count) + 1).append("/").append(count).toString());


                    if (mIndicateRoot.getChildCount() > 1) {// 多余一个
                        HomeActivityBean.ExtrasData items = list.get(toRealPosition(position,
                                count));
                        for (int i = 0; i < mIndicateRoot.getChildCount(); i++) {
                            if (i == toRealPosition(position, count)) {
                                mIndicateRoot.getChildAt(i).setBackgroundResource(R.drawable
                                        .icon_interact_news_banner_white_dot);

                                mTitle.setText(TextUtils.isEmpty(items.getTitle()) ? "" : items
                                        .getTitle());
                                mTime.setText(TextUtils.isEmpty(items.getUpdateTime()) ? "" :
                                        DateUtils.convertToTime(Long.parseLong(items
                                                        .getUpdateTime())
                                                , "yyyy年MM月dd日"));
                            } else {
                                mIndicateRoot.getChildAt(i).setBackgroundResource(R.drawable
                                        .icon_interact_news_banner_gray_dot);
                            }
                        }
                    }
                }

                @Override
                public void onPageScrollStateChanged(int state) {
                    if (mOnPageChangeListener != null) {
                        mOnPageChangeListener.onPageScrollStateChanged(state);
                    }

                    switch (state) {
                        case 0://No operation
                            if (currentItem == 0) {
                                //  viewPager.setCurrentItem(count+1, false);
                                mViewpager.setCurrentItem(count, false);
                            } else if (currentItem == count + 1) {
                                // viewPager.setCurrentItem(0, false);
                                mViewpager.setCurrentItem(1, false);
                            }
                            break;
                        case 1://start Sliding
                            if (currentItem == count + 1) {
                                // viewPager.setCurrentItem(0, false);
                                mViewpager.setCurrentItem(1, false);
                            } else if (currentItem == 0) {
                                //  viewPager.setCurrentItem(count+1, false);
                                mViewpager.setCurrentItem(count, false);
                            }
                            break;
                        case 2://end Sliding
                            break;
                    }
                }
            });


          /*  if (datas.size() - 1 == position) {
                mLine.setVisibility(View.GONE);
            } else {
                mLine.setVisibility(View.VISIBLE);
            }
*/
            mViewpager.setCurrentItem(1);
            //TODO 设置偏移  mViewpager.setOffscreenPageLimit(count + 2);


            mMore.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View view) {
                    HomeNewsListActivity.launcher(mMore.getContext());
                }
            });

            if (count > 1)
                startAutoPlay();

        }


    }

    public void setOnPageChangeListener(ViewPager.OnPageChangeListener onPageChangeListener) {
        mOnPageChangeListener = onPageChangeListener;
    }

    private int toRealPosition(int position, int count) {
        int realPosition = (position - 1) % count;
        if (realPosition < 0)
            realPosition += count;
        return realPosition;
    }

    public void startAutoPlay() {
        handler.removeCallbacks(task);
        handler.postDelayed(task, delayTime);
    }

    private final Runnable task = new Runnable() {
        @Override
        public void run() {

            if (count > 1) {
                currentItem = currentItem % (count + 1) + 1;
                if (currentItem == 1) {
                    mViewpager.setCurrentItem(currentItem, false);
                    handler.postDelayed(task, delayTime);
                } else {
                    mViewpager.setCurrentItem(currentItem);
                    handler.postDelayed(task, delayTime);
                }
            }
        }
    };

    public void stopAutoPlay() {
        handler.removeCallbacks(task);
    }
}

原文地址:https://blog.csdn.net/byxyrq/article/details/51481773

猜你喜欢

转载自blog.csdn.net/u012811342/article/details/79665307
今日推荐