多多色-多人伦交性欧美在线观看-多人伦精品一区二区三区视频-多色视频-免费黄色视屏网站-免费黄色在线

國內最全IT社區平臺 聯系我們 | 收藏本站
阿里云優惠2
您當前位置:首頁 > php開源 > 綜合技術 > ViewDragHelper讓你處理View拖動時,代碼減半!

ViewDragHelper讓你處理View拖動時,代碼減半!

來源:程序員人生   發布時間:2015-04-27 08:27:19 閱讀次數:3729次

出處:ViewDragHelper是V4包下的1個文件。

我們在自定義ViewGroup的時候,有時候覺得很頭疼,其中很大1部份緣由就是由于事件處理太麻煩,需要記錄大量的成員變量,還有各種判斷等等。
Google也感覺到了這個麻煩,所以ViewDragHelper就出現了,ViewDragHelper功能究竟是甚么呢?從字面意思上看是View拖拽的幫助類,簡而言之就是,在簡化View拖拽的時候的代碼量。我們先來看1看到底這個類的幫助有多大?
先來看1個測拉菜單效果
這里寫圖片描述
先來分析1下,如果我們不借助這個幫助類實現情況:
1、重寫1個RelativeLayout;
2、重寫其中的onInterceptTouchEvent(做相應的事件攔截操作)
2、重寫其中的onTouchEvent方法(這里面做大量的代碼)
3、定義1個Scroller變量,用來控制手指松開以后的操作
這里我就不去寫代碼了,代碼量肯定很大!
再來看看借助ViewDragHelper類實現的代碼

/** * Created by gyzhong on 15/4/8. */ public class VdhLayout01 extends RelativeLayout { private ViewDragHelper mViewDragHelper; private View mCaptureView; private float mInitialMotionX; private float mInitialMotionY; private boolean mIsUnableToDrag; private int mSlideRange; private float mSlideOffset; public VdhLayout01(Context context) { this(context, null); } public VdhLayout01(Context context, AttributeSet attrs) { this(context, attrs, 0); } public VdhLayout01(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); initView(context); } private void initView(Context context) { mViewDragHelper = ViewDragHelper.create(this, 1.0f, new DragHelperCall()); } @Override protected void onFinishInflate() { super.onFinishInflate(); mCaptureView = findViewById(R.id.id_capture_view); TextView textView = (TextView) findViewById(R.id.id_text); textView.setText(Shakespeare.DIALOGUE[0]); } @Override protected void onAttachedToWindow() { super.onAttachedToWindow(); mCaptureView.getViewTreeObserver().addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() { @Override public boolean onPreDraw() { mCaptureView.getViewTreeObserver().removeOnPreDrawListener(this); mSlideRange = mCaptureView.getMeasuredWidth(); return false; } }); } private class DragHelperCall extends ViewDragHelper.Callback { @Override public boolean tryCaptureView(View child, int pointerId) { return child == mCaptureView; } @Override public void onViewPositionChanged(View changedView, int left, int top, int dx, int dy) { super.onViewPositionChanged(changedView, left, top, dx, dy); mSlideOffset = left * 1.0f / mSlideRange*2; } @Override public int clampViewPositionHorizontal(View child, int left, int dx) { return clamp(left, 0, mSlideRange / 2); } @Override public int getViewHorizontalDragRange(View child) { return mSlideRange/2; } @Override public void onViewReleased(View releasedChild, float xvel, float yvel) { int finalLeft; if (xvel > 0 || xvel == 0 && mSlideOffset > .5f) { finalLeft = mSlideRange/2 ; }else { finalLeft = 0 ; } mViewDragHelper.settleCapturedViewAt( finalLeft, mCaptureView.getTop()); invalidate(); } } @Override public void computeScroll() { if (mViewDragHelper.continueSettling(true)){ ViewCompat.postInvalidateOnAnimation(this); } } private int clamp(int value, int min, int max) { return Math.min(max, Math.max(min, value)); } @Override public boolean onInterceptTouchEvent(MotionEvent ev) { final int action = MotionEventCompat.getActionMasked(ev); if (action == MotionEvent.ACTION_CANCEL || action == MotionEvent.ACTION_UP) { mViewDragHelper.cancel(); return false; } if (!isEnabled() || (mIsUnableToDrag && action != MotionEvent.ACTION_DOWN)) { mViewDragHelper.cancel(); return super.onInterceptTouchEvent(ev); } int index = MotionEventCompat.getActionIndex(ev) ; switch (action) { case MotionEvent.ACTION_DOWN: { final float x = ev.getX(); final float y = ev.getY(); mInitialMotionX = x; mInitialMotionY = y; mIsUnableToDrag = false; break; } case MotionEvent.ACTION_MOVE: { final float x = ev.getX(); final float y = ev.getY(); final float adx = Math.abs(x - mInitialMotionX); final float ady = Math.abs(y - mInitialMotionY); int slop = mViewDragHelper.getTouchSlop(); if (adx > slop && adx < ady) { mIsUnableToDrag = true; mViewDragHelper.cancel(); return false; } break; } } return mViewDragHelper.shouldInterceptTouchEvent(ev); } @Override public boolean onTouchEvent(MotionEvent event) { mViewDragHelper.processTouchEvent(event); return true; } }

可以看到這里我們只是處理了事件攔截的操作,由于這里觸及到了ScrollView,如果沒有觸及到事件攔截的話,代碼量更簡單!而最最復雜的onTouchEvent方法,我們甚么都沒做,只是讓他交給ViewDragHelper類去處理。
如果看了DrawerLayout和SlidingPaneLayout源碼的朋友應當知道,這兩個控件就使用了這個幫助類。
看了ViewDragHelper的使用效果,我們再來看看它的用法,

/** * ViewDragHelper is a utility class for writing custom ViewGroups. It offers a number * of useful operations and state tracking for allowing a user to drag and reposition * views within their parent ViewGroup. */

上面那段話是ViewDragHelper類的1個說明。大致意思實說ViewDragHelper是自定義ViewGroup的1個工具類,在我們對子View拖拽或復位的時候它提供了1系列有用的操作。
從這段話中我們可以知道1個信息,這個類大部份用于自定義ViewGroup中,固然像上面的例子,重寫RelativeLayout其實也相當于自定義ViewGroup。
實例化ViewDragHelper,ViewDragHelper的構造方法私有化了,所以我們不能直接new,需要通過

public static ViewDragHelper create(ViewGroup forParent, float sensitivity, Callback cb) { //... return helper; }

public static ViewDragHelper create(ViewGroup forParent, Callback cb) { return new ViewDragHelper(forParent.getContext(), forParent, cb); }

來實例化,這列有3個參數,分別代表甚么意思呢?
ViewGroup forParent 就是我們自定義的ViewGroup
float sensitivity 是1個拖拽的靈敏度
Callback cb 是ViewDragHelper中定義的1個抽象類,需要我們在自定義的ViewGroup中重寫它,而核心的操作也就在在各類中,了解了這個類中的方法,就基本掌握這個Helper的應用。

public static abstract class Callback { //但拖拽狀態改變的時候會觸發這個方法,比如:從1開始不能拖拽,到拖拽 public void onViewDragStateChanged(int state) {} //關鍵方法:顧名思義,這里就是記錄了1些值得變化,可用于我們處理其他的操作,比如,改變背景色彩 public void onViewPositionChanged(View changedView, int left, int top, int dx, int dy) {} //這個方法很少用到,意義不大,可疏忽 public void onViewCaptured(View capturedChild, int activePointerId) {} //關鍵方法,手指松開會觸發這個方法,做復位操作就在此方法中實現 public void onViewReleased(View releasedChild, float xvel, float yvel) {} //當邊沿被觸摸的時候調用 public void onEdgeTouched(int edgeFlags, int pointerId) {} //邊沿設置不可用, public boolean onEdgeLock(int edgeFlags) { return false; } //這個方法也很少用到 public void onEdgeDragStarted(int edgeFlags, int pointerId) {} //給自定義的ViewGroup中的字View 重新排序 public int getOrderedChildIndex(int index) { return index; } //關鍵方法:設置水平拖動的距離 public int getViewHorizontalDragRange(View child) { return 0; } //關鍵方法:設置垂直拖動的距離 0 表示不可拖動 public int getViewVerticalDragRange(View child) { return 0; } //關鍵方法:返回true表示可以拖動 public abstract boolean tryCaptureView(View child, int pointerId); //關鍵方法:重新定位水平移動的位置,返回left表示不受限制 public int clampViewPositionHorizontal(View child, int left, int dx) { return 0; } //關鍵方法:重新定位垂直移動的位置,返回top表示不受限制 public int clampViewPositionVertical(View child, int top, int dy) { return 0; } }

看了以上注釋,再回過頭來看上面的例子是否是覺得很簡單。

總結:

1、ViewDragHelper的作用是1個簡化View拖動的幫助類
2、ViewDragHelper大部份用在自定義ViewGroup中
3、ViewDragHelper的實例化通過

create(ViewGroup forParent, float sensitivity, Callback cb)

方法創建
4、在自定義的ViewGroup中的onInterceptTouchEvent方法中別忘記調用ViewDragHelper中的shouldInterceptTouchEvent(ev),
同理onTouchEvent(MotionEvent event)中需要調用
ViewDragHelper.processTouchEvent(event);

源碼下載

生活不易,碼農辛苦
如果您覺得本網站對您的學習有所幫助,可以手機掃描二維碼進行捐贈
程序員人生
------分隔線----------------------------
分享到:
------分隔線----------------------------
關閉
程序員人生
主站蜘蛛池模板: 在线观看免费精品国自产 | 欧美激情αv一区二区三区 欧美激情第二页 | 国产亚洲精品福利在线 | 午夜啪啪网站 | 欧美bbwxxxx| 国产精品亚洲午夜不卡 | 亚洲色欲色欲综合网站 | 欧美性活生活视频 | 另类zoofilia杂交videos | a天堂在线 | 成年人视频免费网站 | 日韩精品久久不卡中文字幕 | 人人澡人人擦人人免费 | 天天做天天爱天天大综合 | 国产三级在线观看视频 | 精品无码久久久久久国产 | 嫩草影院久久精品 | 国产免费播放一区二区 | 中文字幕在线视频网 | 色综合久久久久久久久久久 | 国产成人精品第一区二区 | 日韩成人国产精品视频 | 亚洲日韩欧美综合 | 亚洲图片小说区 | 亚洲三级黄色片 | 国产成人无精品久久久 | 亚洲一区二区三区高清视频 | 最新亚洲国产有精品 | 国产一区二区三区高清视频 | 欧美系列第一页 | 国产免费久久精品久久久 | 天天拍久久 | 第一国内永久免费福利视频 | 亚洲欧美日本国产 | 欧美性video高清精品 | 亚洲乱码一二三四五六区 | 欧美一级高清免费播放 | 97欧美在线看欧美视频免费 | 国产美女一级做受在线观看 | 最近最新中文字幕免费1 | 欧美成人免费高清二区三区 |