网站/小程序/APP个性化定制开发,二开,改版等服务,加扣:8582-36016

    一、需求

    之前一篇博客使用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
     
    fling
    (
    int
     velocityX, 
    int
     velocityY)
     
    {
    
    
            LinearLayoutManager linearLayoutManager = (LinearLayoutManager) getLayoutManager();
    
    
            
    int
     screenWidth = Resources.getSystem().getDisplayMetrics().widthPixels;
    
    
            
    // 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 = Resources.getSystem().getDisplayMetrics().widthPixels;
    
    
                
    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
    ;
    
                }
    
                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 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 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 class BannerAdapter extends QuickAdapter {    public BannerAdapter(List datas) {        super(datas);
        }    @Override
        public int getLayoutId(int viewType) {        return R.layout.item_banner_image;
        }    @Override
        public void convert(QuickViewHolder holder, String url, int position) {        final Resources resources = holder.itemView.getResources();        final int drawableId = resources.getIdentifier(url, "drawable", holder.itemView.getContext().getPackageName());        if(drawableId!=0) {
                ImageView bannerImage = holder.getView(R.id.banner_image_item);
                bannerImage.setImageResource(drawableId);
            }
    
        }
    }

     

    三、使用

            final RecyclerPagerView rpv  = findViewById(R.id.recycler_pager);
            tipTextView                  = findViewById(R.id.tip_text);
            LinearLayoutManager lm = new LinearLayoutManager(this,LinearLayoutManager.HORIZONTAL,false);
            rpv.setLayoutManager(lm);
    
            List imagelist = new ArrayList<>();
            imagelist.add("banner_t1");
            imagelist.add("banner_t2");
            imagelist.add("banner_t3");
            imagelist.add("banner_t4");
    
            rpv.setAdapter(new BannerAdapter(imagelist));
            rpv.setOnPageChangeListener(new PagerChangeListener(tipTextView,imagelist.size()));
            rpv.startPlay();

    监听器

        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);
            }
        }

     


     

    评论 0

    暂无评论
    0
    0
    0
    立即
    投稿
    发表
    评论
    返回
    顶部