Android Studio - 第四十六期 不会ANR的轮播写法

简介:

   最近在学习撸撸的代码,发现他的轮播写法很独特,但是有bug,就重新修改了一下,现在支持左右点击和圆点自定义。

    BannerAdapter:(注意适配器自己看ImageView和onclick的自己项目的写法~)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
package  com.example.p029_banner_lunbo.adapter;
 
import  android.app.Activity;
import  android.view.View;
import  android.view.ViewGroup;
import  android.widget.ImageView;
 
import  com.example.p029_banner_lunbo.bannerutils.BannerView;
import  com.example.p029_banner_lunbo.domain.Biaoge_listBean;
 
import  java.util.List;
 
 
public  class  BannerAdapter  extends  BannerView.Adapter {
 
     private  List<Biaoge_listBean> mAdList;
     private  Object mReceiver;
 
     public  BannerAdapter(Object receiver, List<Biaoge_listBean> items) {
         mReceiver = receiver;
         mAdList = items;
     }
 
     @Override
     public  int  getRealCount() {
         return  mAdList.size();
     }
 
     @Override
     public  Object instantiateItem( final  ViewGroup container,  int  position) {
         int  size = mAdList.size();
         if  (size ==  0 ) {
             return  null ;
         }
 
         final  int  pos = position % size;
 
         final  Biaoge_listBean item = mAdList.get(pos);
 
         ViewGroup.LayoutParams p =  new  ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
                 ViewGroup.LayoutParams.MATCH_PARENT);
         ImageView iv =  new  ImageView(container.getContext());
         iv.setScaleType(ImageView.ScaleType.FIT_XY);
         iv.setAdjustViewBounds( true );
         container.addView(iv, p);
 
         iv.setBackgroundResource(item.getImg_url());
 
//        GlideUtil.display(container.getContext(), iv, item.getPic_url(),
//                GlideOptionsFactory.get(GlideOptionsFactory.Type.RADIUS));
 
         iv.setOnClickListener( new  View.OnClickListener() {
             @Override
             public  void  onClick(View v) {
//                MobEventHelper.onEvent(container.getContext(), "UI2_ec_index_banner");
//                    MobEventHelper.onEvent(container.getContext(), "UI2_ec_index_banner_" + String.valueOf(pos + 1));
                 if  (container.getContext()  instanceof  Activity) {
                     Activity act = (Activity) container.getContext();
                     //跳转bufen
//                    HiosHelper.resolveAd(act, mReceiver, item.getUrl());
                 }
             }
         });
 
         return  iv;
     }
 
     @Override
     public  void  destroyItem(ViewGroup container,  int  position, Object object) {
         container.removeView((View) object);
     }
}

    DotIndicatorView:(圆点的方法大部分都public了,大家可以DotIndicatorView.自定义~)    

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
package  com.example.p029_banner_lunbo.bannerutils;
 
import  android.content.Context;
import  android.graphics.Canvas;
import  android.graphics.Color;
import  android.graphics.Paint;
import  android.util.AttributeSet;
import  android.util.DisplayMetrics;
import  android.util.TypedValue;
import  android.view.View;
 
/**
  * 圆点导航
  * @author geek
  *
  */
public  class  DotIndicatorView  extends  View {
    private  Paint mPaint;
 
    private  int  mPadding;
    private  int  mCircleRadius;
    
    private  int  mCurrentColor;
    private  int  mNormalColor;
    
    private  int  mCount =  3 ;
    
    private  int  mCurrent;
    
    public  DotIndicatorView(Context context) {
       super (context);
       initView();
    }
    
    public  DotIndicatorView(Context context, AttributeSet attrs) {
       this (context, attrs,  0 );
    }
 
    public  DotIndicatorView(Context context, AttributeSet attrs,  int  defStyle) {
       super (context, attrs, defStyle);
       initView();
    }
 
    private  void  initView() {
       DisplayMetrics dm = getResources().getDisplayMetrics();
       mPadding = ( int ) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,  10 , dm);
       mCircleRadius = ( int ) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,  4 , dm);
       mCurrentColor = Color.WHITE;
       mNormalColor = Color.argb( 88 91 91 91 );
       
       mPaint =  new  Paint(Paint.ANTI_ALIAS_FLAG);
    }
    
    @Override
    protected  void  onMeasure( int  widthMeasureSpec,  int  heightMeasureSpec) {
       int  width = mCircleRadius *  2  * mCount + mPadding * (mCount - 1 );
       int  height = mCircleRadius *  2 ;
       
       setMeasuredDimension(width, height);
    }
    
    @Override
    protected  void  onDraw(Canvas canvas) {
       for  ( int  i =  0 ; i < mCount; i++) {
          canvas.save();
          canvas.translate((mCircleRadius *  2  + mPadding) * i,  0 );
          
          if (i == mCurrent) mPaint.setColor(mCurrentColor);
          else  mPaint.setColor(mNormalColor);
          
          canvas.drawCircle(mCircleRadius , mCircleRadius, mCircleRadius, mPaint);
          canvas.restore();
       }
    }
    
    /**
     * 创建导航
     * @param count 个数
     */
    public  void  create( int  count) {
       mCount = count;
       requestLayout();
       invalidate();
    }
    
    /** 
     * 选中当前
     * @param position 选中位置
     */
    public  void  current( int  position) {
       mCurrent = position;
       invalidate();
    }
    
    /**
     * 获取当前选中的位置
     * @return
     */
    public  int  current() {
       return  mCurrent;
    }
}

    BannerView:(自定义的View~)

    

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
package  com.example.p029_banner_lunbo.bannerutils;
 
import  android.content.Context;
import  android.content.res.TypedArray;
import  android.os.Bundle;
import  android.os.Handler;
import  android.os.Message;
import  android.os.Parcelable;
import  android.support.v4.view.PagerAdapter;
import  android.support.v4.view.ViewPager;
import  android.support.v4.view.ViewPager.OnPageChangeListener;
import  android.util.AttributeSet;
import  android.view.Gravity;
import  android.view.MotionEvent;
import  android.view.View;
import  android.widget.FrameLayout;
 
import  com.example.p029_banner_lunbo.R;
 
import  java.lang.ref.WeakReference;
 
 
public  class  BannerView  extends  FrameLayout {
     private  static  final  int  MSG_RUN =  1 ;
 
     private  ViewPager mViewPager;
     /**
      * 导航的小点
      */
     private  DotIndicatorView mIndicator;
 
     private  Adapter mAdapter;
 
     /**
      * 是否处于滑动的状态
      */
     private  boolean  isScrolling;
 
     private  int  mIndicatorPosition;  // center_hori  left
     /**
      * 是否显示indicator
      */
     private  boolean  isShowIndicator =  true ;
 
     private  boolean  isTouch;
 
     private  Handler mHandler;
 
     private  BannerViewHelper mHelper;
 
     private  int  mScrollTime;
 
     public  BannerView(Context context, AttributeSet attrs) {
         this (context, attrs,  0 );
     }
 
     public  BannerView(Context context, AttributeSet attrs,  int  defStyle) {
         super (context, attrs, defStyle);
         TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.BannerView,
                 defStyle,  0 );
         mIndicatorPosition = ta.getInt(R.styleable.BannerView_indicator_position,  0 );
         isShowIndicator = ta.getBoolean(R.styleable.BannerView_indicator_visible,  true );
         mScrollTime = ta.getInteger(R.styleable.BannerView_scroll_time,  3000 );
         isScrolling = ta.getBoolean(R.styleable.BannerView_auto_start,  false );
         ta.recycle();
         initView(context);
     }
 
     private  void  initView(Context context) {
         mViewPager =  new  ViewPager(context);
         mViewPager.addOnPageChangeListener(mOnPageChangeListener);
         addView(mViewPager); //, viewPagerParams);
 
         mHandler =  new  H(mViewPager);
         mIndicator =  new  DotIndicatorView(context);
         LayoutParams indicatorParams =
                 new  LayoutParams(LayoutParams.WRAP_CONTENT,
                         LayoutParams.WRAP_CONTENT);
         if  (mIndicatorPosition ==  0 ) {
             indicatorParams.gravity = Gravity.BOTTOM | Gravity.LEFT;
         else  if  (mIndicatorPosition ==  1 ) {
             indicatorParams.gravity = Gravity.BOTTOM | Gravity.CENTER_HORIZONTAL;
         else  if  (mIndicatorPosition ==  2 ) {
             indicatorParams.gravity = Gravity.BOTTOM | Gravity.RIGHT;
         }
         indicatorParams.bottomMargin =  20 ;
 
         if  (!isShowIndicator) {
             return ;
         }
         addView(mIndicator, indicatorParams);
 
     }
 
     @Override
     protected  void  onAttachedToWindow() {
         if  (isScrolling) {
             startScroll();
         }
         super .onAttachedToWindow();
         mHelper =  new  BannerViewHelper( this );
     }
 
     @Override
     public  boolean  dispatchTouchEvent(MotionEvent ev) {
         if  (mHelper !=  null ) {
             mHelper.resolveTouchConflict(ev);
         }
         return  super .dispatchTouchEvent(ev);
     }
 
     @Override
     protected  LayoutParams generateDefaultLayoutParams() {
         return  new  LayoutParams(LayoutParams.MATCH_PARENT,
                 LayoutParams.WRAP_CONTENT);
     }
 
     @Override
     public  LayoutParams generateLayoutParams(AttributeSet attrs) {
         return  new  LayoutParams(getContext(), attrs);
     }
 
     @Override
     protected  android.view.ViewGroup.LayoutParams generateLayoutParams(
             android.view.ViewGroup.LayoutParams p) {
         return  new  LayoutParams(p);
     }
 
     @Override
     protected  boolean  checkLayoutParams(android.view.ViewGroup.LayoutParams p) {
         return  instanceof  LayoutParams;
     }
 
     private  OnPageChangeListener mOnPageChangeListener =  new  OnPageChangeListener() {
 
         @Override
         public  void  onPageSelected( int  position) {
             int  relCount = mAdapter.getRealCount();
             if  (relCount <=  0 ) {
                 mIndicator.current( 0 );
             else  {
                 mIndicator.current(position % relCount);
             }
         }
 
         @Override
         public  void  onPageScrolled( int  arg0,  float  arg1,  int  arg2) {
 
         }
 
         @Override
         public  void  onPageScrollStateChanged( int  arg0) {
             isTouch = arg0 == ViewPager.SCROLL_STATE_DRAGGING;
             if  (arg0 == ViewPager.SCROLL_STATE_IDLE && isScrolling) {
                 mHandler.removeMessages(MSG_RUN);
                 Message msg = mHandler.obtainMessage(MSG_RUN, isScrolling ?  1  0 , isTouch ?  1  0 );
                 mHandler.sendMessageDelayed(msg, mScrollTime);
             }
         }
     };
 
     /**
      * 开始自动滚动
      */
     public  void  startScroll() {
         mHandler.removeMessages(MSG_RUN);
         isScrolling =  true ;
         Message msg = mHandler.obtainMessage(MSG_RUN,  1 , isTouch ?  1  0 );
         mHandler.sendMessageDelayed(msg, mScrollTime);
     }
 
     /**
      * 停止自动滚动
      */
     public  void  stopScroll() {
         isScrolling =  false ;
         if  (mHandler !=  null ) {
             mHandler.removeMessages(MSG_RUN);
         }
     }
 
     @Override
     protected  Parcelable onSaveInstanceState() {
         Bundle bundle =  new  Bundle();
         bundle.putBoolean( "scroll" , isScrolling);
         bundle.putParcelable( "state" super .onSaveInstanceState());
         return  bundle;
     }
 
     @Override
     protected  void  onRestoreInstanceState(Parcelable state) {
         Bundle bundle = (Bundle) state;
         isScrolling = bundle.getBoolean( "scroll" );
         state = bundle.getParcelable( "state" );
         if  (state !=  null ) {
             super .onRestoreInstanceState(state);
         }
     }
 
// @Override
// protected void onAttachedToWindow() {
//    super.onAttachedToWindow();
//    if(isScrolling) mHandler.sendEmptyMessage(MSG_RUN);
// }
 
     @Override
     protected  void  onDetachedFromWindow() {
         mHandler.removeMessages(MSG_RUN);
         super .onDetachedFromWindow();
     }
 
     /**
      * 设置banner的数据集合
      */
     public  void  setAdapter(Adapter adapter) {
         mAdapter = adapter;
         mViewPager.setAdapter(adapter);
         mIndicator.create(adapter.getRealCount());
     }
 
     /**
      * 获取adapter
      */
     public  Adapter getAdapter() {
         return  mAdapter;
     }
 
     public  int  getCurrent() {
         return  mViewPager.getCurrentItem() +  1 ;
     }
 
     public  void  setCurrent( int  current) {
         mViewPager.setCurrentItem(current);
     }
 
     private  static  class  extends  Handler {
         private  WeakReference<ViewPager> mViewPager;
 
         public  H(ViewPager pager) {
             mViewPager =  new  WeakReference<>(pager);
         }
 
         public  void  handleMessage(Message msg) {
             if  (mViewPager.get() ==  null return ;
 
             boolean  isScrolling = msg.arg1 ==  1 ;
             boolean  isTouch = msg.arg2 ==  1 ;
 
             if  (msg.what == MSG_RUN && isScrolling) {
                 if  (!isTouch) {
                     int  pos = mViewPager.get().getCurrentItem() +  1 ;
                     mViewPager.get().setCurrentItem(pos);
//             sendEmptyMessageDelayed(MSG_RUN, 3000);
                 else  {
                     removeMessages(MSG_RUN);
                 }
             }
         }
     }
 
     public  static  abstract  class  Adapter  extends  PagerAdapter {
         @Override
         public  final  int  getCount() {
             return  Integer.MAX_VALUE;
         }
 
         /**
          * 获取真实的数据统计
          *
          * @return
          */
         public  abstract  int  getRealCount();
 
         @Override
         public  final  boolean  isViewFromObject(View arg0, Object arg1) {
             return  arg0 == arg1;
         }
 
         public  Object getItem( int  position) {
             return  position;
         }
     }
}

    BannerViewHelper:(用于解决BannerView和SwipeRefreshLayout的冲突)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
package  com.example.p029_banner_lunbo.bannerutils;
 
import  android.support.v4.widget.SwipeRefreshLayout;
import  android.view.MotionEvent;
import  android.view.VelocityTracker;
import  android.view.ViewGroup;
 
 
/**
  * 用于解决BannerView和SwipeRefreshLayout的冲突
  * @author geek
  *
  */
public  class  BannerViewHelper {
    private  BannerView mBannerView;
    private  SwipeRefreshLayout mSwipeRefreshLayout;
    
    private  VelocityTracker mVelocityTracker;
    
    private  float  mAccuracy =  1 .f;
    
    public  BannerViewHelper(BannerView bannerView) {
       mBannerView = bannerView;
       mSwipeRefreshLayout = findSwipeRefreshLayout();
    }
    
    public  BannerViewHelper(BannerView bannerView,  float  accuracy) {
       this (bannerView);
       mAccuracy = accuracy;
    }
    
    public  void  resolveTouchConflict(MotionEvent event) {
       if (mSwipeRefreshLayout ==  null return ;
       
       setupVelocityTracker(event);
       switch  (event.getAction()) {
       case  MotionEvent.ACTION_MOVE:
          if (!mSwipeRefreshLayout.isEnabled())  return ;
          mVelocityTracker.computeCurrentVelocity( 1000 );
          if (Math.abs(mVelocityTracker.getXVelocity()) > 
             Math.abs(mVelocityTracker.getYVelocity()) * mAccuracy) {
             mSwipeRefreshLayout.setEnabled( false );
          }
          break ;
       case  MotionEvent.ACTION_UP:
       case  MotionEvent.ACTION_CANCEL:
          mSwipeRefreshLayout.setEnabled( true );
          recycleVelocityTracker();
       default :
          break ;
       }
    }
    
    private  void  setupVelocityTracker(MotionEvent event) {
       if (mVelocityTracker ==  null ) mVelocityTracker = VelocityTracker.obtain();
       mVelocityTracker.addMovement(event);
    }
    
    private  void  recycleVelocityTracker() {
       if (mVelocityTracker !=  null ) {
          mVelocityTracker.clear();
          mVelocityTracker.recycle();
          mVelocityTracker =  null ;
       }
    }
    
    private  SwipeRefreshLayout findSwipeRefreshLayout() {
       ViewGroup parent = (ViewGroup) mBannerView.getParent();
       while (parent !=  null  && parent.getId() != android.R.id.content) {
          if (parent  instanceof  SwipeRefreshLayout)  return  (SwipeRefreshLayout) parent;
          parent = (ViewGroup) parent.getParent();
       }
       return  null ;
    }
}

    xml布局:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
<?xml version= "1.0"  encoding= "utf-8" ?>
<RelativeLayout xmlns:android= "http://schemas.android.com/apk/res/android"
     xmlns:app= "http://schemas.android.com/apk/res-auto"
     android:layout_width= "match_parent"
     android:layout_height= "match_parent"
     android:orientation= "vertical" >
 
     <LinearLayout
         android:layout_width= "match_parent"
         android:layout_height= "wrap_content"
         android:background= "#ccc"
         android:orientation= "vertical" >
 
         <com.example.p029_banner_lunbo.bannerutils.BannerView
             android:id= "@+id/banner"
             android:layout_width= "match_parent"
             android:layout_height= "400dp"
             app:indicator_position= "center"
             app:indicator_visible= "false"
             app:scroll_time= "8000"  />
 
     </LinearLayout>
 
     <TextView
         android:id= "@+id/tv_left"
         android:layout_width= "wrap_content"
         android:layout_height= "wrap_content"
         android:background= "@drawable/icon_left"  />
 
     <TextView
         android:id= "@+id/tv_right"
         android:layout_width= "wrap_content"
         android:layout_height= "wrap_content"
         android:layout_alignParentRight= "true"
         android:background= "@drawable/icon_right"  />
</RelativeLayout>

    调用方法:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
tv_left = (TextView) findViewById(R.id.tv_left);
tv_left.setOnClickListener( new  View.OnClickListener() {
     @Override
     public  void  onClick(View v) {
         //左←
         ToastUtil.showToastShort(MainActivity. this "左" );
 
         mBannerView.setCurrent(mBannerView.getCurrent() -  2 );
     }
});
tv_right = (TextView) findViewById(R.id.tv_right);
tv_right.setOnClickListener( new  View.OnClickListener() {
     @Override
     public  void  onClick(View v) {
         //右→
         ToastUtil.showToastShort(MainActivity. this "右" );
 
         mBannerView.setCurrent(mBannerView.getCurrent());
     }
});
mBannerView = (BannerView) findViewById(R.id.banner);
 
Data1();
mBannerView.setAdapter( new  BannerAdapter( this , mList1));
 
mBannerView.stopScroll();
mBannerView.startScroll();

    代码已经整理好,效果如下图:

    图1:

    wKiom1mBm2Hwn4ZAAA4a2t1gsho820.png

    图2:

    wKioL1mBpD6DSGdmABpqlbmWKEo502.gif

    图2:

    QQ截图20171222151741.png

    地址:https://github.com/geeklx/MyApplication/tree/master/p029_banner_lunbo

    附:

    wKioL1mBohPj4IwCAAsTVcRnQWk237.png









本文转自 吴雨声 51CTO博客,原文链接:http://blog.51cto.com/liangxiao/1953066,如需转载请自行联系原作者

目录
相关文章
|
4月前
|
人工智能 IDE 开发工具
Studio Bot - 让 AI 帮我写 Android 代码
Studio Bot - 让 AI 帮我写 Android 代码
166 1
|
8天前
|
传感器 Java 开发工具
[NDK/JNI系列03] Android Studio集成NDK开发环境
[NDK/JNI系列03] Android Studio集成NDK开发环境
14 0
|
15天前
|
Android开发
【Android Studio】缺少输入自动补充(已解决)
【Android Studio】缺少输入自动补充(已解决)
|
5月前
|
Java 开发工具 Android开发
OpenCV(一):Android studio jni配置OpenCV(亲测有效,保姆级)
OpenCV(一):Android studio jni配置OpenCV(亲测有效,保姆级)
164 0
|
29天前
|
Java 测试技术 Linux
Android Studio安装超详细步骤
安装Android Studio涉及多个步骤,包括**安装JDK 1.8**,配置`JAVA_HOME`和`PATH`环境变量。然后从**官方地址**下载并安装Android Studio。启动时初始化环境,通过SDK Manager安装必要的SDK Tools。配置**ANDROID_HOME**环境变量,并在`PATH`中添加SDK相关目录。确保**adb**和**emulator**命令可执行,并可能需要将build-tools降级至兼容JDK 1.8的版本(如29)。这些步骤对于设置App自动化测试环境至关重要。
40 3
|
2月前
|
Java Android开发
Android Studio的使用导入第三方Jar包
Android Studio的使用导入第三方Jar包
12 1
|
2月前
|
Android开发
android studio 重新将module中的代码加入到自己项目中,报错找不到SO文件。
android studio 重新将module中的代码加入到自己项目中,报错找不到SO文件。
9 1
|
2月前
|
API Android开发
List.size() 问题 Android studio: Verbose,Debug,Info,Warn,Error
List.size() 问题 Android studio: Verbose,Debug,Info,Warn,Error
16 0
|
2月前
|
Java 开发工具 Android开发
Android Studio Gradle文件解释其作用
Android Studio Gradle文件解释其作用
26 2
|
3月前
|
数据库 Android开发 数据库管理
【Android】使用android studio查看内置数据库信息
【Android】使用android studio查看内置数据库信息
77 0