• 扩展ViewFlow避免和ViewPager滑动冲突,同时支持无限循环,并完美和CircleFlowIndicator结合


    首先,为了避免滑动冲突,我们要继承ViewFlow,重写onInterceptTouchEvent

     1 public class MyViewFlow extends ViewFlow {
     2     private ViewPager mPager;
     3 
     4     public MyViewFlow(Context context, AttributeSet attrs) {
     5         super(context, attrs);
     6     }
     7 
     8 
     9     public void setViewPager(ViewPager viewPager) {
    10         mPager = viewPager;
    11     }
    12 
    13     @Override
    14     public boolean onInterceptTouchEvent(MotionEvent ev) {
    15         if (mPager != null)
    16             switch (ev.getAction()) {
    17                 case MotionEvent.ACTION_DOWN:
    18                     mPager.requestDisallowInterceptTouchEvent(true);
    19                     break;
    20                 case MotionEvent.ACTION_UP:
    21                     mPager.requestDisallowInterceptTouchEvent(false);
    22                     break;
    23                 case MotionEvent.ACTION_CANCEL:
    24                     mPager.requestDisallowInterceptTouchEvent(false);
    25                     break;
    26                 case MotionEvent.ACTION_MOVE:
    27                     mPager.requestDisallowInterceptTouchEvent(true);
    28                     break;
    29             }
    30         return super.onInterceptTouchEvent(ev);
    31     }
    32 }

     调用setViewPager指定viewPager后,滑动便不再冲突

    接下来,我们实现无限循环滚动

     1 public class AdapterBanner extends BaseAdapter {
     2 
     3     private LayoutInflater mInflater;
     4     private static final int[] ids = { R.drawable.banner, R.drawable.banner, R.drawable.banner, R.drawable.banner};
     5 
     6     public AdapterBanner(Context context) {
     7         mInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
     8     }
     9 
    10     @Override
    11     public int getCount() {
    12         //return ids.length;
    13         return Integer.MAX_VALUE;//返回很大的值使得getView中的position不断增大来实现循环
    14     }
    15 
    16     @Override
    17     public Object getItem(int position) {
    18         return position;
    19     }
    20 
    21     @Override
    22     public long getItemId(int position) {
    23         return position;
    24     }
    25 
    26     @Override
    27     public View getView(int position, View convertView, ViewGroup parent) {
    28         if (convertView == null) {
    29             convertView = mInflater.inflate(R.layout.item_fr_acmain_nearby_banner, null);
    30         }
    31         convertView.findViewById(R.id.imgView).setBackgroundResource(ids[position%ids.length]);
    32         return convertView;
    33     }
    34 
    35 }

    关键代码在第13行和31行的红色部分。不过这样实现之后,和CircleFlowIndicator结合使用,会发现程序ANR(无响应),原因是CircleFlowIndicator会调用ViewFlow.getViewCount()来绘制圆点,显然这个数是Integer.MAX_VALUE,圆点数太多了导致ANR,我们需要继续扩展MyViewFlow的getViewCount()。如下。

    1     private int mCount;
    2     public void setCount(int count){
    3         mCount=count;
    4     }
    5     @Override
    6     public int getViewsCount() {
    7         return mCount;
    8     }

    需要调用MyViewFlow.setCount(int count)指定真实的数目,这样做了之后,发现程序不会ANR了。CircleFlowIndicator绘制的圆点数目也正常。但是会发现,无论怎么滑动,圆点状态都不变化,分析ViewFlow的源码,发现要重写一下onScrollChanged,我们继续扩展MyViewFlow,代码如下。

     1     private int mLastIndex;
     2     @Override
     3     public void setAdapter(Adapter adapter, int initialPosition){
     4         super.setAdapter(adapter,initialPosition);
     5         mLastIndex = initialPosition;
     6     }
     7 
     8     @Override
     9     protected void onScrollChanged(int h, int v, int oldh, int oldv) {
    10         //super.onScrollChanged(h, v, oldh, oldv);
    11         if (mIndicator != null) {
    12             /*
    13              * The actual horizontal scroll origin does typically not match the
    14              * perceived one. Therefore, we need to calculate the perceived
    15              * horizontal scroll origin here, since we use a view buffer.
    16              */
    17             int hPerceived = h + (mCurrentAdapterIndex%mCount - mCurrentBufferIndex)
    18                     * getChildWidth();
    19 
    20             if(mLastIndex%mCount==mCount-1 && mCurrentAdapterIndex>mLastIndex) {
    21                 oldh=0;
    22                 hPerceived = 0;
    23             }
    24             if(mLastIndex%mCount==0&&mCurrentAdapterIndex<mLastIndex)
    25                 hPerceived=h+(mCount-1-mCurrentBufferIndex)*getChildWidth();
    26 
    27             LogUtil.e(Config.MYTAG,"mCurrentAdapterIndex="+mCurrentAdapterIndex);
    28             LogUtil.e(Config.MYTAG,"mLastIndex="+mLastIndex);
    29             LogUtil.e(Config.MYTAG, "hPerceived=" + hPerceived);
    30 
    31             mIndicator.onScrolled(hPerceived, v, oldh, oldv);
    32 
    33             mLastIndex=mCurrentAdapterIndex;
    34         }
    35

    当然,有几个变量mIndicator,mCurrentAdapterIndex,mCurrentBufferIndex是沿用父类ViewFlow的,如果找不到,需要将父类ViewFlow中这些变量改为public即可(虽然从oop角度,这种做法很脏,但很省事,大半夜码文字很累,我很懒)。

    至此,大功告成!

    整体MyViewFlow代码如下:

    package common.control.viewflow;
    
    import android.content.Context;
    import android.support.v4.view.ViewPager;
    import android.util.AttributeSet;
    import android.view.MotionEvent;
    import android.widget.Adapter;
    
    import com.xxx.android.main.Config;
    
    import common.util.LogUtil;
    
    
    public class MyViewFlow extends ViewFlow {
        private ViewPager mPager;
    
        public MyViewFlow(Context context, AttributeSet attrs) {
            super(context, attrs);
        }
    
    
        public void setViewPager(ViewPager viewPager) {
            mPager = viewPager;
        }
    
        @Override
        public boolean onInterceptTouchEvent(MotionEvent ev) {
            if (mPager != null)
                switch (ev.getAction()) {
                    case MotionEvent.ACTION_DOWN:
                        mPager.requestDisallowInterceptTouchEvent(true);
                        break;
                    case MotionEvent.ACTION_UP:
                        mPager.requestDisallowInterceptTouchEvent(false);
                        break;
                    case MotionEvent.ACTION_CANCEL:
                        mPager.requestDisallowInterceptTouchEvent(false);
                        break;
                    case MotionEvent.ACTION_MOVE:
                        mPager.requestDisallowInterceptTouchEvent(true);
                        break;
                }
            return super.onInterceptTouchEvent(ev);
        }
        private int mCount;
        public void setCount(int count){
            mCount=count;
        }
        @Override
        public int getViewsCount() {
            return mCount;
        }
        private int mLastIndex;
        @Override
        public void setAdapter(Adapter adapter, int initialPosition){
            super.setAdapter(adapter,initialPosition);
            mLastIndex = initialPosition;
        }
    
        @Override
        protected void onScrollChanged(int h, int v, int oldh, int oldv) {
            //super.onScrollChanged(h, v, oldh, oldv);
            if (mIndicator != null) {
                /*
                 * The actual horizontal scroll origin does typically not match the
                 * perceived one. Therefore, we need to calculate the perceived
                 * horizontal scroll origin here, since we use a view buffer.
                 */
                int hPerceived = h + (mCurrentAdapterIndex%mCount - mCurrentBufferIndex)
                        * getChildWidth();
    
                if(mLastIndex%mCount==mCount-1 && mCurrentAdapterIndex>mLastIndex) {
                    oldh=0;
                    hPerceived = 0;
                }
                if(mLastIndex%mCount==0&&mCurrentAdapterIndex<mLastIndex)
                    hPerceived=h+(mCount-1-mCurrentBufferIndex)*getChildWidth();
    
                LogUtil.e(Config.MYTAG,"mCurrentAdapterIndex="+mCurrentAdapterIndex);
                LogUtil.e(Config.MYTAG,"mLastIndex="+mLastIndex);
                LogUtil.e(Config.MYTAG, "hPerceived=" + hPerceived);
    
                mIndicator.onScrolled(hPerceived, v, oldh, oldv);
    
                mLastIndex=mCurrentAdapterIndex;
            }
        }
    }

    自动播放就不用讲了,网上很多。同学们如果有收获,记得回赞。

  • 相关阅读:
    java内存管理之内存模型
    HTTP协议
    12 数值的整数次方
    11 二进制中1的个数+二进制补充知识点
    10 矩形覆盖
    9 变态跳台阶
    8 跳台阶
    7斐波那契数列
    6旋转数组的最小数字
    5用两个栈实现队列
  • 原文地址:https://www.cnblogs.com/kaima/p/3999390.html
Copyright © 2020-2023  润新知