侧边栏壁纸
博主头像
落叶人生博主等级

走进秋风,寻找秋天的落叶

  • 累计撰写 130562 篇文章
  • 累计创建 28 个标签
  • 累计收到 9 条评论
标签搜索

目 录CONTENT

文章目录

Android 使用RecyclerView实现轮播图

2023-12-16 星期六 / 0 评论 / 0 点赞 / 47 阅读 / 13806 字

一、需求 之前一篇博客使用ViewPager实现轮播图《Android ViewPager实现循环轮播图》,但是ViewPager有个天生的缺陷是View无法重用,此外ViewPager的滑动过程会频

一、需求

之前一篇博客使用ViewPager实现轮播图《Android ViewPager实现循环轮播图》,但是ViewPager有个天生的缺陷是View无法重用,此外ViewPager的滑动过程会频繁requestLayout,尽管可以通过addViewInLayout和removeViewInLayout配合PagerAdapter 的startUpdate和finishUpdate可以减少重绘,但在ListView和RecyclerView中仍然达不到最好的效果。因此,使用一种新的方式十分必要。

二、代码实现

RecyclerPagerView 

public class RecyclerPagerView extends RecyclerView implements Handler.Callback {    private static final long TASK_TIMEOUT = 3000;    public OnPageChangeListener onPageChangeListener;    private final Handler mRecyclerHandler;    private final int MSG_PLAY_NEXT  = 112233;    private volatile boolean isPlaying = false;    private boolean lastIsPlayState = false;    private int realPosition = -1;    public RecyclerPagerView(Context context) {        this(context,null);    }    public RecyclerPagerView(Context context, @Nullable AttributeSet attrs) {        this(context, attrs,0);    }    public RecyclerPagerView(Context context, @Nullable AttributeSet attrs, int defStyle) {        super(context, attrs, defStyle);        mRecyclerHandler = new Handler(Looper.getMainLooper(),this);    }    public void setOnPageChangeListener(OnPageChangeListener onPageChangeListener) {        this.onPageChangeListener = onPageChangeListener;        if(this.onPageChangeListener!=null){            addOnScrollListener(this.onPageChangeListener);            int currentItem = getCurrentItem();            this.onPageChangeListener.onPageSelection(currentItem);        }    }    public int getCurrentItem(){        LinearLayoutManager linearLayoutManager = (LinearLayoutManager) getLayoutManager();        return linearLayoutManager.findFirstVisibleItemPosition();    }    public void setCurrentItem(int position,boolean isAnimate){        Adapter adapter = getAdapter();        if(adapter==null || adapter.getItemCount()<=position){            return;        }        if(!isAnimate)        {            scrollToPosition(position);        }else {            smoothScrollToPosition(position);        }    }    public void setCurrentItem(int position ){       setCurrentItem(position,true);    }    @Override    public boolean onTouchEvent(MotionEvent e) {        int action = e.getAction();        if(action==MotionEvent.ACTION_DOWN){            lastIsPlayState = isPlaying;            if(lastIsPlayState){                stopPlay();            }        }else if(action==MotionEvent.ACTION_UP || action==MotionEvent.ACTION_CANCEL){            if(lastIsPlayState){                startPlay();            }        }        return super.onTouchEvent(e);    }    @Override    public boolean fling(int velocityX, int velocityY) {        LinearLayoutManager linearLayoutManager = (LinearLayoutManager) getLayoutManager();        int screenWidth = getWidth();        // views on the screen        int lastVisibleItemPosition = linearLayoutManager.findLastVisibleItemPosition();        View lastView = linearLayoutManager.findViewByPosition(lastVisibleItemPosition);        int firstVisibleItemPosition = linearLayoutManager.findFirstVisibleItemPosition();        View firstView = linearLayoutManager.findViewByPosition(firstVisibleItemPosition);        // distance we need to scroll        int leftMargin = (screenWidth - lastView.getWidth()) / 2;        int rightMargin = (screenWidth - firstView.getWidth()) / 2 + firstView.getWidth();        int leftEdge = lastView.getLeft();        int rightEdge = firstView.getRight();        int scrollDistanceLeft = leftEdge - leftMargin;        int scrollDistanceRight = rightMargin - rightEdge;        int targetPosition;        if (Math.abs(velocityX) < 1500) {            // The fling is slow -> stay at the current page if we are less than half through,            // or go to the next page if more than half through            if (leftEdge > screenWidth / 2) {                // go to next page                smoothScrollBy(-scrollDistanceRight, 0);                targetPosition = firstVisibleItemPosition;            } else if (rightEdge < screenWidth / 2) {                // go to next page                smoothScrollBy(scrollDistanceLeft, 0);                targetPosition = firstVisibleItemPosition+1;            } else {                // stay at current page                if (velocityX > 0) {                    smoothScrollBy(-scrollDistanceRight, 0);                } else {                    smoothScrollBy(scrollDistanceLeft, 0);                }                targetPosition = firstVisibleItemPosition;            }        } else {            // The fling is fast -> go to next page            if (velocityX > 0) {                smoothScrollBy(scrollDistanceLeft, 0);                targetPosition = firstVisibleItemPosition+1;            } else {                smoothScrollBy(-scrollDistanceRight, 0);                targetPosition = firstVisibleItemPosition;            }        }        Log.e("RecyclerPagerView","nextPage="+targetPosition);        if(this.onPageChangeListener!=null){            realPosition = targetPosition;            this.onPageChangeListener.onPageSelection(targetPosition);        }        return true;    }    @Override    public void onScrollStateChanged(final  int state) {        super.onScrollStateChanged(state);        if (state == SCROLL_STATE_IDLE) {            LinearLayoutManager linearLayoutManager = (LinearLayoutManager) getLayoutManager();            int screenWidth = getWidth();            int lastVisibleItemPosition = linearLayoutManager.findLastVisibleItemPosition();            View lastView = linearLayoutManager.findViewByPosition(lastVisibleItemPosition);            int firstVisibleItemPosition = linearLayoutManager.findFirstVisibleItemPosition();            View firstView = linearLayoutManager.findViewByPosition(firstVisibleItemPosition);            // distance we need to scroll            int leftMargin = (screenWidth - lastView.getWidth()) / 2;            int rightMargin = (screenWidth - firstView.getWidth()) / 2 + firstView.getWidth();            int leftEdge = lastView.getLeft();            int rightEdge = firstView.getRight();            int scrollDistanceLeft = leftEdge - leftMargin;            int scrollDistanceRight = rightMargin - rightEdge;            int  targetPosition = -1;            if (leftEdge > screenWidth / 2) {                smoothScrollBy(-scrollDistanceRight, 0);                targetPosition = firstVisibleItemPosition+1;            } else if (rightEdge < screenWidth / 2) {                smoothScrollBy(scrollDistanceLeft, 0);                targetPosition = lastVisibleItemPosition;            }else{                targetPosition = firstVisibleItemPosition;            }            if(this.onPageChangeListener!=null){                realPosition = targetPosition;                this.onPageChangeListener.onPageSelection(targetPosition);            }        }    }    @Override    public boolean handleMessage(Message msg) {        int what = msg.what;        switch (what){            case MSG_PLAY_NEXT:                showNextPage();                break;        }        return false;    }    private void showNextPage() {        if(!isPlaying){            return;        }        if(!canRecyclePlaying()){            isPlaying = false;            return;        }        Adapter adapter = getAdapter();        int currentItem = getCurrentItem();        if(adapter!=null && adapter.getItemCount()>0) {            if (currentItem == NO_POSITION  ) {                setCurrentItem(0);            }else {                setCurrentItem(currentItem+1);            }        }        mRecyclerHandler.sendEmptyMessageDelayed(MSG_PLAY_NEXT,TASK_TIMEOUT);    }    public void startPlay(){        if(isPlaying){            stopPlay();        }        if (!canRecyclePlaying()){            isPlaying = false;            return;        }        isPlaying = true;        mRecyclerHandler.sendEmptyMessageDelayed(MSG_PLAY_NEXT,TASK_TIMEOUT);    }    @Override    public void setAdapter(Adapter adapter) {        super.setAdapter(adapter);        if(canRecyclePlaying()){            if(realPosition==-1){                realPosition = 1000;                if(adapter.getItemCount()==3000){                    realPosition = realPosition - 1;                }            }            setCurrentItem(realPosition,false);        }    }    private boolean canRecyclePlaying() {        Adapter adapter = getAdapter();        if(adapter==null || adapter.getItemCount()<1) return false;        return true;    }    private void stopPlay() {        isPlaying = false;        mRecyclerHandler.removeMessages(MSG_PLAY_NEXT);    }    @Override    protected void onAttachedToWindow() {        super.onAttachedToWindow();        if(lastIsPlayState){            startPlay();        }    }    @Override    protected void onDetachedFromWindow() {        super.onDetachedFromWindow();        lastIsPlayState = isPlaying;        stopPlay();    }    public static    abstract class OnPageChangeListener extends RecyclerView.OnScrollListener{            public abstract  void onPageSelection(int position);    }}

 

Adapter+Holder 适配器

该类的作用主要用于约束和快速接入

public class QuickViewHolder extends RecyclerView.ViewHolder{    private SparseArray<View> mViews;    private View mConvertView;    private QuickViewHolder(View v){        super(v);        mConvertView = v;        mViews = new SparseArray<>();    }    public static QuickViewHolder get(ViewGroup parent, int layoutId){        View convertView = LayoutInflater.from(parent.getContext()).inflate(layoutId, parent, false);        return new QuickViewHolder(convertView);    }    public <T extends View> T getView(int id){        View v = mViews.get(id);        if(v == null){            v = mConvertView.findViewById(id);            mViews.put(id, v);        }        return (T)v;    }}

 

BannerAdapter实现,该类继承QuickAdapter

 public static abstract class BaseQuickAdapter<VH extends  QuickViewHolder,DM extends Serializable> extends RecyclerPagerView.Adapter{        private List<DM> dataset;        public BaseQuickAdapter(List<DM> dataset){            this.dataset = dataset;        }        @Override        public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {            return QuickViewHolder.get(parent,getLayoutId(viewType));        }        @Override        public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {            convert((VH)holder,getItem(position),position);        }        public  abstract  void convert(VH holder, DM dataModel, int position);        public abstract int getLayoutId(int viewType);        public DM getItem(int position) {            if(dataset==null) return null;            if(position<0 || position>=getItemCount()) {                return null;            }            return dataset.get(position%dataset.size());        }        @Override        public int getItemCount() {            if(dataset==null || dataset.isEmpty()) return 0;            return dataset.size()*1000;        }    }    public static class BannerAdapter extends BaseQuickAdapter {        public BannerAdapter(List<Item> dataset) {            super(dataset);        }        @Override        public void convert(QuickViewHolder holder, Serializable dataModel, int position) {            if(!(dataModel instanceof Item)) return;            TextView textView = holder.getView(R.id.text);            textView.setText(((Item) dataModel).getTitle());            ImageView imageView = holder.getView(R.id.image);            imageView.setImageDrawable(((Item) dataModel).getImageResource());        }        @Override        public int getLayoutId(int viewType) {            return R.layout.item_banner;        }    }

 

三、使用

监听器

    public static class  PagerChangeListener extends RecyclerPagerView.OnPageChangeListener {        private TextView tipTextView;        private int size;        public PagerChangeListener(TextView tipTextView,int size) {            this.tipTextView = tipTextView;            this.size = size;        }        @Override        public void onPageSelection(int position) {            tipTextView.setText((position%size+1)+"/"+size);        }    }

数据集

public static class Item implements Serializable {         Drawable drawable;         String title;        public Item(int color, String s) {            this.drawable = new ColorDrawable(color);            this.title = s;        }        public Drawable getImageResource() {            return drawable;        }        public String getTitle() {            return title;        }        public static List<Item>  getSampleData(){            int[] colors = {                    	0xffDC143C,                        0xff00BFFF,                        0xffA52A2A            };            List<Item> lst = new ArrayList<>();            for (int i=0;i<colors.length;i++) {                Item item =  new Item(colors[i%colors.length],"第"+(i%colors.length+1)+"张图");                lst.add(item);            }            return lst;        }    }

 

广告 广告

评论区