自定义控件:Viewpager
生活随笔
收集整理的這篇文章主要介紹了
自定义控件:Viewpager
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
自定義控件:Viewpager
package com.itheima.myviewpager66;import android.content.Context; import android.util.AttributeSet; import android.view.GestureDetector; import android.view.MotionEvent; import android.view.ViewGroup; import android.widget.Scroller;/*** 自定義ViewPager* * 1. 寫一個類繼承ViewGroup* 2. 重寫onLayout方法, 保證孩子正常顯示(一字排開)* 3. 重寫onTouchEvent, 手勢識別器(onScroll),scrollby* 4. 監聽手指抬起事件,根據當前滑動后位置,確定下一個頁面, scrollTo* 5. 防止pos過大* 6. 平滑移動, Scroller, startScroll->computeScroll* 7. 增加RadioButton, 監聽自定義viewpager頁面切換(回調接口),更改raidoButton選中位置* 8. 監聽RadioButton切換事件, 更改頁面* 9. 增加測試頁面(ScrollView)* 11. 重寫onMeasure,測量每個孩子* 12. 重寫onInterceptTouchEvent, 在適當時機(水平滑動),中斷事件傳遞* @author Kevin* @date 2015-8-8*/ public class MyViewPager extends ViewGroup {// 手勢識別器private GestureDetector mDetector;private Scroller mScroller;public MyViewPager(Context context, AttributeSet attrs, int defStyle) {super(context, attrs, defStyle);initView();}public MyViewPager(Context context, AttributeSet attrs) {super(context, attrs);initView();}public MyViewPager(Context context) {super(context);initView();}private void initView() {mDetector = new GestureDetector(getContext(),new GestureDetector.SimpleOnGestureListener() {// 手勢滑動@Overridepublic boolean onScroll(MotionEvent e1, MotionEvent e2,float distanceX, float distanceY) {scrollBy((int) distanceX, 0);// 滑動x,y方向偏移一定距離, 相對位移// scrollTo(x, y);//絕對位移, 移動到確定的x,y坐標位置return super.onScroll(e1, e2, distanceX, distanceY);}});// 初始化滑動器mScroller = new Scroller(getContext());}// 測量布局寬高@Overrideprotected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {super.onMeasure(widthMeasureSpec, heightMeasureSpec);// 手動測量所有孩子的寬高, 解決測試頁面無法展示的bugint childCount = getChildCount();for (int i = 0; i < childCount; i++) {getChildAt(i).measure(widthMeasureSpec, heightMeasureSpec);}System.out.println("widthMeasureSpec:" + widthMeasureSpec);System.out.println("heightMeasureSpec:" + heightMeasureSpec);int size = MeasureSpec.getSize(widthMeasureSpec);System.out.println("width:" + size);int mode = MeasureSpec.getMode(widthMeasureSpec);//MeasureSpec.AT_MOST; //wrap_content//MeasureSpec.EXACTLY; //確定值 , 寬高寫死, 100dp/ match_parent//MeasureSpec.UNSPECIFIED;//沒有指定寬高System.out.println("mode:" + mode);}// 設置布局位置@Overrideprotected void onLayout(boolean changed, int l, int t, int r, int b) {// 手動設置孩子們的位置, 保證一字排開int childCount = getChildCount();for (int i = 0; i < childCount; i++) {getChildAt(i).layout(0 + i * getWidth(), 0, (i + 1) * getWidth(),getHeight());}}@Overridepublic boolean onTouchEvent(MotionEvent event) {mDetector.onTouchEvent(event);// 委托手勢識別器處理switch (event.getAction()) {case MotionEvent.ACTION_UP:// 1.獲取當前滑動的位置// 2.根據當前位置,確定應該跳到第幾個頁面// 3.跳到確定頁面int scrollX = getScrollX();// System.out.println("scrollX:" + scrollX);// 計算應該跳轉到下一個頁面的哪個位置int pos = (scrollX + getWidth() / 2) / getWidth();// //350 / 320 = 1// int pos = scrollX / getWidth();// // 350% 320 = 30// int offset = scrollX % getWidth();// if (offset > getWidth() / 2) {// pos++;// }// System.out.println("pos:" + pos);// 防止pos過大if (pos > getChildCount() - 1) {pos = getChildCount() - 1;}// 移動到確定頁面// scrollTo(pos * getWidth(), 0);setCurrentItem(pos);break;default:break;}return true;}// 當調用startScroll后,系統會不斷回調此方法@Overridepublic void computeScroll() {if (mScroller.computeScrollOffset()) {// 判斷滑動回調有沒有結束int currX = mScroller.getCurrX();// 獲取當前應該移動到的位置System.out.println("currX:" + currX);scrollTo(currX, 0);// 移動到確定位置invalidate();// 刷新界面}}private OnPageChangeListener mListener;public void setOnPageChangeListener(OnPageChangeListener listener) {mListener = listener;}public interface OnPageChangeListener {public void onPageSelected(int position);}/*** 切換到某個具體的頁面* * @param position*/public void setCurrentItem(int pos) {// 平滑的移動到某個位置int distance = pos * getWidth() - getScrollX();// 目標位置減去當前位置,獲得要滑動的距離// 開始滑動, 滑動時間等于距離絕對值,// 保證距離越長,時間越久(此方法不會產生滑動,而是會導致不斷回調computeScroll,需要在這個方法中處理滑動邏輯)mScroller.startScroll(getScrollX(), 0, distance, 0, Math.abs(distance));// 參1:開始x,// 參2:開始y;參3:x偏移,參4:y偏移;參5:滑動時間invalidate();// 刷新界面,保證滑動器正常運行// 頁面切換的回調if (mListener != null) {mListener.onPageSelected(pos);}}int startX;int startY;// 事件中斷 onInterceptTouchEvent->onTouchEvent@Overridepublic boolean onInterceptTouchEvent(MotionEvent ev) {// 如果左右滑動, 就需要攔截, 上下滑動,不需要攔截switch (ev.getAction()) {case MotionEvent.ACTION_DOWN:mDetector.onTouchEvent(ev);// 將ACTION_DOWN傳遞給手勢識別器, 避免事件丟失startX = (int) ev.getX();startY = (int) ev.getY();break;case MotionEvent.ACTION_MOVE:int endX = (int) ev.getX();int endY = (int) ev.getY();int dx = endX - startX;int dy = endY - startY;if (Math.abs(dx) > Math.abs(dy)) {// 左右滑動return true;// 中斷事件傳遞, 不允許孩子響應事件了, 由父控件處理}break;default:break;}return false;// 不攔截事件,優先傳遞給孩子處理}// 事件分發dispatchTouchEvent->onInterceptTouchEvent->onTouchEvent@Overridepublic boolean dispatchTouchEvent(MotionEvent ev) {return super.dispatchTouchEvent(ev);} }
總結
以上是生活随笔為你收集整理的自定义控件:Viewpager的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 自定义控件:QQ气泡效果粘性控件的实现
- 下一篇: 自定义控件:滑动开关