ViewDragHelper使用简介
来源:互联网 发布:网络电视遥控怎么开 编辑:程序博客网 时间:2024/05/21 11:31
ViewDragHelper
使用ViewDragHelper可以轻松的实现拖动效果
简单Demo
XML中定义
<?xml version="1.0" encoding="utf-8"?><RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent"> <!--这里考虑了Padding的情况--> <com.jacob.viewdraghelper.tianrui.Practice1View android:layout_width="match_parent" android:layout_height="match_parent" android:padding="10dp"> <TextView android:layout_width="60dp" android:layout_height="60dp" android:background="#00ff00"/> </com.jacob.viewdraghelper.tianrui.Practice1View></RelativeLayout>
ViewDragHelper的编写
在onInterceptTouchEvent()和onTouchEvent()中使用ViewDragHelper接受事件
@Override public boolean onInterceptTouchEvent(MotionEvent event) { switch (event.getAction()) { case MotionEvent.ACTION_UP: case MotionEvent.ACTION_CANCEL: // 取消拖动 mViewDragHelper.cancel(); break; } // 由ViewDragHelper决定是否拦截事件 return mViewDragHelper.shouldInterceptTouchEvent(event); } @Override public boolean onTouchEvent(MotionEvent event) { mViewDragHelper.processTouchEvent(event); return true; }
这些都是模板代码,要使用ViewDragHelper的话必须这么做.
编写CallBack代码
ViewDragHelper将MotionEvent帮我们处理成CallBack,我们只需处理CallBack中的逻辑就可以了,不用编写重复的拖动代码了.
最基本的有三个回调方法,使用这三个回调方法,能够处理大多数拖拽逻辑了
/** * ViewDragHelper必备的回调方法 */ private class ViewDragCallBack extends ViewDragHelper.Callback { /** * 判断当前需要拖动哪个View */ @Override public boolean tryCaptureView(View child, int pointerId) { Log.d(TAG, "tryCaptureView: " + child.getClass().getSimpleName()); return child == mTvTarget; } /** * 在水平方向上,对拖动的位置进行限制 * * @param child 进行拖动的View * @param left 水平方向上的移动距离 * @param dx 水平方向上的移动增量 * @return 实际需要移动的值 */ @Override public int clampViewPositionHorizontal(View child, int left, int dx) { final int leftBound = getLeft() + getPaddingLeft(); if (left < leftBound) { return leftBound; } final int rightBound = getRight() - mTvTarget.getWidth() - getPaddingRight(); if (left > rightBound) { return rightBound; } return left; } /** * 处理竖直方向上的拖动 */ @Override public int clampViewPositionVertical(View child, int top, int dy) { final int topBound = getTop() + getPaddingTop(); if (top < topBound) { return topBound; } final int bottomBound = getBottom() - mTvTarget.getHeight() - getPaddingBottom(); if (top > bottomBound) { return bottomBound; } return top; } }
注意事项:
- 如果第一子View不是TextView而是一个Button,那么就会出现无法拖动的情况,原因就是子View默认属性带有Clickable,会消耗掉这次事件序列,所以必须在OnInterceptTouchEvent()中进行拦截,使用ViewDragHelper中已经带了默认方法帮我们进行处理
/** * 该方法用来描述View需要被拖动的距离,用此来适配子View具有Clickable属性的情况 * * @param child 要拖动的View * @return View在该方向上拖动的距离 */@Overridepublic int getViewHorizontalDragRange(View child) { Log.d(TAG, "getViewHorizontalDragRange: "); // 这里返回整个水平区域 return getMeasuredWidth() - child.getMeasuredWidth();}@Overridepublic int getViewVerticalDragRange(View child) { return getMeasuredHeight() - child.getMeasuredHeight();}
Demo1完整代码
/** * Created by yangtianrui on 17-8-3. * ViewDragHelper的基本使用 */public class Practice1View extends LinearLayout { private static final String TAG = "tianrui"; // 需要拖动的目标View private TextView mTvTarget; private ViewDragHelper mViewDragHelper; public Practice1View(Context context) { this(context, null); } public Practice1View(Context context, @Nullable AttributeSet attrs) { this(context, attrs, 0); } public Practice1View(Context context, @Nullable AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); mViewDragHelper = ViewDragHelper.create(this, 1F, new ViewDragCallBack()); } @Override protected void onFinishInflate() { super.onFinishInflate(); Log.d(TAG, "onFinishInflate: "); mTvTarget = (TextView) getChildAt(0); if (mTvTarget == null) { throw new IllegalStateException("first child must be TextView."); } } @Override public boolean onInterceptTouchEvent(MotionEvent event) { switch (event.getAction()) { case MotionEvent.ACTION_UP: case MotionEvent.ACTION_CANCEL: // 取消拖动 mViewDragHelper.cancel(); break; } // 由ViewDragHelper决定是否拦截事件 return mViewDragHelper.shouldInterceptTouchEvent(event); } @Override public boolean onTouchEvent(MotionEvent event) { mViewDragHelper.processTouchEvent(event); return true; } /** * ViewDragHelper必备的回调方法 */ private class ViewDragCallBack extends ViewDragHelper.Callback { /** * 判断当前需要拖动哪个View */ @Override public boolean tryCaptureView(View child, int pointerId) { Log.d(TAG, "tryCaptureView: " + child.getClass().getSimpleName()); return child == mTvTarget; } /** * 在水平方向上,对拖动的位置进行限制 * * @param child 进行拖动的View * @param left 水平方向上的移动距离 * @param dx 水平方向上的移动增量 * @return 实际需要移动的值 */ @Override public int clampViewPositionHorizontal(View child, int left, int dx) { final int leftBound = getLeft() + getPaddingLeft(); if (left < leftBound) { return leftBound; } final int rightBound = getRight() - mTvTarget.getWidth() - getPaddingRight(); if (left > rightBound) { return rightBound; } return left; } /** * 处理竖直方向上的拖动 */ @Override public int clampViewPositionVertical(View child, int top, int dy) { final int topBound = getTop() + getPaddingTop(); if (top < topBound) { return topBound; } final int bottomBound = getBottom() - mTvTarget.getHeight() - getPaddingBottom(); if (top > bottomBound) { return bottomBound; } return top; } /** * 该方法用来描述View需要被拖动的距离,用此来适配子View具有Clickable属性的情况 * * @param child 要拖动的View * @return View在该方向上拖动的距离 */ @Override public int getViewHorizontalDragRange(View child) { Log.d(TAG, "getViewHorizontalDragRange: "); // 这里返回整个水平区域 return getMeasuredWidth() - child.getMeasuredWidth(); } @Override public int getViewVerticalDragRange(View child) { return getMeasuredHeight() - child.getMeasuredHeight(); } } @Override public void computeScroll() { super.computeScroll(); // 如果需要ViewDragHelper进行惯性滑动的话需要使用 // 下面代码仍然是模板代码 if (mViewDragHelper.continueSettling(true)) { ViewCompat.postInvalidateOnAnimation(this); } }}
Demo2 使用ViewDragHelper实现惯性滑动
ViewDragHelper内部使用Scroller实现滑动,所以需要重写View的ComputeScroll()方法,
该方法的重写方式如下:
@Override public void computeScroll() { super.computeScroll(); if (mViewDragHelper.continueSettling(true)) { ViewCompat.postInvalidateOnAnimation(this); } }
在onViewRelease()中实现惯性滑动逻辑
使用 mViewDragHelper.settleCapturedViewAt( left, top)将一个View进行惯性滑动,同时记得调用invalidate()进行重绘
/** * 手指抬起时回调,一般用于实现惯性滑动 * * @param releasedChild 拖动的View * @param xvel x方向的速度 * @param yvel y方向的速度 */ @Override public void onViewReleased(View releasedChild, float xvel, float yvel) { super.onViewReleased(releasedChild, xvel, yvel); // 定位到top/middle/bottom三个位置 final int top = releasedChild.getTop(); Log.d(TAG, "onViewReleased: " + String.format("mTop=%d, mMiddle=%d, mBottom=%d,yVel=%f, height=%d", mTop, mMiddle, mBottom, yvel, releasedChild.getHeight())); // 向下滑动 if (yvel > 0) { if (top < mMiddle) { mViewDragHelper.settleCapturedViewAt(0, mMiddle); } else if (top < mBottom) { mViewDragHelper.settleCapturedViewAt(0, mBottom); } } else if (yvel < 0) { // 向上滑动 if (top < mMiddle) { mViewDragHelper.settleCapturedViewAt(0, mTop); } else if (top < mBottom) { mViewDragHelper.settleCapturedViewAt(0, mMiddle); } } invalidate(); } }
Demo2完整代码
/** * Created by yangtianrui on 17-8-5. * ViewDragHelper实现惯性滑动 */public class Practice2View extends LinearLayout { private static final String TAG = "tianrui"; private ViewDragHelper mViewDragHelper; private View mTarget; private int mTop; private int mMiddle; private int mBottom; public Practice2View(Context context) { this(context, null); } public Practice2View(Context context, @Nullable AttributeSet attrs) { this(context, attrs, 0); } public Practice2View(Context context, @Nullable AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); mViewDragHelper = ViewDragHelper.create(this, 1F, new ViewDragHelperCallBack()); } @Override protected void onFinishInflate() { super.onFinishInflate(); mTarget = getChildAt(0); } @Override protected void onLayout(boolean changed, int l, int t, int r, int b) { super.onLayout(changed, l, t, r, b); mTop = getTop(); mMiddle = (getBottom() - getTop()) / 2 - mTarget.getMeasuredHeight(); mBottom = getBottom() - mTarget.getMeasuredHeight(); } @Override public boolean onInterceptTouchEvent(MotionEvent ev) { final int action = ev.getAction(); switch (action) { case MotionEvent.ACTION_UP: case MotionEvent.ACTION_CANCEL: mViewDragHelper.cancel(); break; } return mViewDragHelper.shouldInterceptTouchEvent(ev); } @Override public boolean onTouchEvent(MotionEvent event) { mViewDragHelper.processTouchEvent(event); return true; } @Override public void computeScroll() { super.computeScroll(); if (mViewDragHelper.continueSettling(true)) { ViewCompat.postInvalidateOnAnimation(this); } } private class ViewDragHelperCallBack extends ViewDragHelper.Callback { @Override public boolean tryCaptureView(View child, int pointerId) { return child == mTarget; } @Override public int clampViewPositionVertical(View child, int top, int dy) { if (top < getTop()) { return getTop(); } if (top > (getBottom() - child.getHeight())) { return getBottom() - child.getHeight(); } return top; } @Override public int clampViewPositionHorizontal(View child, int left, int dx) { if (left < getLeft()) { return getLeft(); } if (left > (getRight() - child.getWidth())) { return getRight() - child.getWidth(); } return left; } /** * 手指抬起时回调,一般用于实现惯性滑动 * * @param releasedChild 拖动的View * @param xvel x方向的速度 * @param yvel y方向的速度 */ @Override public void onViewReleased(View releasedChild, float xvel, float yvel) { super.onViewReleased(releasedChild, xvel, yvel); // 定位到top/middle/bottom三个位置 final int top = releasedChild.getTop(); Log.d(TAG, "onViewReleased: " + String.format("mTop=%d, mMiddle=%d, mBottom=%d,yVel=%f, height=%d", mTop, mMiddle, mBottom, yvel, releasedChild.getHeight())); // 向下滑动 if (yvel > 0) { if (top < mMiddle) { mViewDragHelper.settleCapturedViewAt(0, mMiddle); } else if (top < mBottom) { mViewDragHelper.settleCapturedViewAt(0, mBottom); } } else if (yvel < 0) { // 向上滑动 if (top < mMiddle) { mViewDragHelper.settleCapturedViewAt(0, mTop); } else if (top < mBottom) { mViewDragHelper.settleCapturedViewAt(0, mMiddle); } } invalidate(); } }}
参考http://blog.csdn.net/lmj623565791/article/details/46858663
阅读全文
0 0
- ViewDragHelper使用简介
- ViewDragHelper简介
- ViewDragHelper 使用
- ViewDragHelper 使用
- ViewDragHelper使用
- ViewDragHelper 使用
- ViewDragHelper使用
- ViewDragHelper的使用
- viewdraghelper的使用
- android viewdraghelper使用
- ViewDragHelper API 的使用
- 使用ViewDragHelper实现slidemenu
- ViewDragHelper的使用介绍
- ViewDragHelper的使用
- ViewDragHelper使用详解
- ViewDragHelper使用介绍
- ViewDragHelper的使用
- ViewDragHelper的使用
- Java Arrays.sort和Collections.sort的简洁写法
- Python While循环语句 Python 编程中 while 语句用于循环执行程序,即在某条件下,循环执行某段程序,以处理需要重复处理的相同任务。其基本形式为: while 判断条件:
- SQL查询和优化(四)
- <8/5>集训日记
- CART分类与回归树与GBDT(Gradient Boost Decision Tree)
- ViewDragHelper使用简介
- python爬虫学习第十二天
- JDK 安装
- Vivado安装教程补丁
- 值得思考的JavaScript代码
- CSS选择器及其优先级
- Google算法题:不包含连续1的非负整数
- Protocol Buffer基本语法
- 树回归