ViewDragHelper详解(一)
来源:互联网 发布:网络侦探 艾可萨兽 编辑:程序博客网 时间:2024/05/03 04:46
一、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是一个实用的类,用来开发自定义ViewGroup。它定义了一组有用的操作和状态追踪,允许用户在父ViewGroup中拖动并且重新定位子View(child view)。
从官方的介绍中我们了解到了几个关键点:
- 自定义ViewGroup
- 拖动以及重新定位
- 操作和状态追踪
二、ViewHelper的看的见的地方有哪些?
当我们看到一个未知的东西,我们的心里总是充满疑惑,想要探究一下可以看得见和摸得着的感知。 在我的系列文章中也将会给大家奉献看得见的GIF,将相关函数和具体表现形象的展示出来。
- DrawerLayout
- QQ5.0以上的侧滑效果
三、 从实例来讲解ViewDragHelper
我们将会看到常用函数的用法
步骤一: 创建我们自定义的LinearLayout
public class VDHLinearLayout extends LinearLayout { private ViewDragHelper mViewDragHelper = null; public VDHLinearLayout(Context context, AttributeSet attrs) { super(context, attrs); createVDH(null); } public void createVDH(ViewDragHelper.Callback callback) { if (callback == null) { mViewDragHelper = ViewDragHelper.create(this, new ViewDragHelper.Callback() { @Override public boolean tryCaptureView(View child, int pointerId) { return true; } }); } else { mViewDragHelper = ViewDragHelper.create(this, 1.0f, callback); } } @Override public boolean onTouchEvent(MotionEvent event) { if (mViewDragHelper == null) { return super.dispatchTouchEvent(event); } mViewDragHelper.processTouchEvent(event); return true; } @Override public boolean onInterceptTouchEvent(MotionEvent ev) { if (mViewDragHelper == null) { return super.onInterceptTouchEvent(ev); } int keyCode = ev.getAction(); if (keyCode == MotionEvent.ACTION_CANCEL) { mViewDragHelper.cancel(); return false; } return mViewDragHelper.shouldInterceptTouchEvent(ev); } public ViewDragHelper getViewDragHelper() { return mViewDragHelper; }}
步骤二:创建布局文件activity_main.xml
<?xml version="1.0" encoding="utf-8"?><com.demonli.vdh.view.VDHLinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:fitsSystemWindows="true" android:orientation="vertical" tools:context="com.demonli.vdh.MainActivity" android:id="@+id/root_vdh" android:paddingTop="10dp" android:paddingBottom="30dp" android:paddingLeft="15dp" android:paddingRight="20dp" > <TextView android:id="@+id/child1" android:layout_margin="10dp" android:gravity="center" android:layout_gravity="center" android:background="@color/colorPrimary" android:text="CommonDragView" android:layout_width="100dp" android:layout_height="100dp"/> <TextView android:id="@+id/child2" android:layout_margin="10dp" android:layout_gravity="center" android:gravity="center" android:background="@color/colorAccent" android:text="AutobackView" android:layout_width="100dp" android:layout_height="100dp"/> <TextView android:id="@+id/child3" android:layout_margin="10dp" android:layout_gravity="center" android:gravity="center" android:background="@android:color/holo_red_dark" android:text="EdgeTrackerView" android:layout_width="100dp" android:layout_height="100dp"/></com.demonli.vdh.view.VDHLinearLayout>
步骤三:创建MainActivity
public class MainActivity extends AppCompatActivity { private VDHLinearLayout mVDHLiearLayout; private TextView mDragView; private TextView mAutobackView; private TextView mEdgeView; Point mAutobackPoint = new Point(); @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); mDragView = (TextView) findViewById(R.id.child1); mAutobackView = (TextView) findViewById(R.id.child2); mEdgeView = (TextView) findViewById(R.id.child3); mVDHLiearLayout = (VDHLinearLayout) findViewById(R.id.root_vdh); init(); } protected void init() { mVDHLiearLayout.createVDH(new VDHCallback()); mAutobackView.postDelayed(new Runnable() { @Override public void run() { mAutobackPoint.set(mAutobackView.getLeft(), mAutobackView.getTop()); } }, 0); } class VDHCallback extends ViewDragHelper.Callback { /** * 此例中 mEdgeView将无法被拖动 * 此函数必须实现 * * @param child * @param pointerId * @return if false,那么child view将无法拖动(Drag) */ @Override public boolean tryCaptureView(View child, int pointerId) { if (child == mEdgeView) {// return false; } return true; } /** * 实现对child view x 轴方向的控制 * * @param child * @param left * @param dx * @return */ @Override public int clampViewPositionHorizontal(View child, int left, int dx) { int leftBound = mVDHLiearLayout.getPaddingLeft(); int rightBound = mVDHLiearLayout.getWidth() - mVDHLiearLayout.getPaddingRight() - child.getWidth();// if(left<leftBound){// left = leftBound;// }else if(left>rightBound){// left = rightBound;// } //更加简洁的写法 left = Math.min(Math.max(left, leftBound), rightBound); return left; } /** * 对child view y 轴方向的控制 * * @param child * @param top * @param dy * @return */ @Override public int clampViewPositionVertical(View child, int top, int dy) { int topBound = mVDHLiearLayout.getPaddingTop(); int bottomBound = mVDHLiearLayout.getHeight() - child.getHeight() - mVDHLiearLayout.getPaddingBottom(); if (top < topBound) { top = topBound; } else if (top > bottomBound) { top = bottomBound; } return top; } }}
经过步骤一、二、三之后我们可以看到以下的效果:
我们会发现:
1、mDragView和mAutobackView可以Drag,而mEdgeView没有移动。
2、同时我们会主要到mDragView和mAutobackView无法到达屏幕的边界。
1、tryCaptureView( ) :试图捕获child view的drag 事件,如果指定子view 返回false,则会出现像mEdgeView那样无法Drag的情况。
2、布局文件activity_main.xml中我们定义根布局中的paddingLeft等,并且在MainActivity中实现了clampViewPositionVertical()与clampViewPositionHorizontal()两个函数。函数的具体意义见代码中的注释。
步骤四:实现mAutobackView的拖动后自动返回到原来的位置:
在VDHLinearLayout中添加:
@Override public void computeScroll() { super.computeScroll(); if(mViewDragHelper.continueSettling(true)){ invalidate(); } }
在MainActivty中添加:
@Override public void onViewReleased(View releasedChild, float xvel, float yvel) { if(releasedChild==mAutobackView){ mVDHLiearLayout.getViewDragHelper().settleCapturedViewAt(mAutobackPoint.x,mAutobackPoint.y); mVDHLiearLayout.invalidate(); } }
接下来我们会看到这样的效果:
我们可以看出来mAutobackView自动的回到原来的位置。
1、首先我们保存了mAutobackView的初始坐标
mAutobackView.postDelayed(new Runnable() { @Override public void run() { mAutobackPoint.set(mAutobackView.getLeft(), mAutobackView.getTop()); } }, 0);
然后我们在VDHCallback实现了:
/** * 此函数用于捕捉用户的ACTION_UP * @param releasedChild * @param xvel * @param yvel */ @Override public void onViewReleased(View releasedChild, float xvel, float yvel) { if(releasedChild==mAutobackView){ mVDHLiearLayout.getViewDragHelper().settleCapturedViewAt(mAutobackPoint.x,mAutobackPoint.y); mVDHLiearLayout.invalidate(); } }
步骤五:实现mEdgeView从屏幕边界滑动时的移动效果
@Override public void onEdgeDragStarted(int edgeFlags, int pointerId) { // super.onEdgeDragStarted(edgeFlags, pointerId); mVDHView.getViewDragHelper().captureChildView(mEageView, pointerId); }
mViewDragHelper.setEdgeTrackingEnabled(ViewDragHelper.EDGE_ALL);
这样我们的mEdgeView便可拖动了。
对于ViewDragHelper.Callback中没有讲到的方法如下:
onViewDragStateChanged()
当ViewDragHelper状态发生变化时回调(IDLE,DRAGGING,SETTING[自动滚动时])onViewPositionChanged
当captureview的位置发生改变时回调onViewCaptured()
当captureview被捕获时回调onEdgeTouched()
当触摸到边界时回调。onEdgeLock()
true的时候会锁住当前的边界,false则unLock。getOrderedChildIndex()
改变同一个坐标(x,y)去寻找captureView位置的方法。(具体在:findTopChildUnder方法中)
- ViewDragHelper详解(一)
- ViewDragHelper详解(一)
- ViewDragHelper详解
- ViewDragHelper详解
- ViewDragHelper详解
- ViewDragHelper详解
- ViewDragHelper详解
- ViewDragHelper详解
- ViewDragHelper详解
- ViewDragHelper详解
- ViewDragHelper详解
- ViewDragHelper详解
- ViewDragHelper详解
- ViewDragHelper详解
- ViewDragHelper详解
- ViewDragHelper详解
- ViewDragHelper详解
- ViewDragHelper详解
- 民生银行信用卡心得---网络整理
- 【浅谈web网站验证码生成方案之中文验证码 】
- 简单的八皇后问题---NOJ1593
- HDOJ(HDU) 1673 Optimal Parking
- 用python实现DES加解密,并附带EBC和CBC两种分组加密模式
- ViewDragHelper详解(一)
- 云主机ubuntu12 64安装php7
- 基于百度地图记录运动轨迹案例分析与实现
- 数据库性能优化之SQL语句优化
- CentOS7下php安装mcrypt扩展
- 详解Android接口Interface的使用和意义
- XE5的单步调试功能开关问题
- [调参算法]Sebastian Thrun
- web day12 JSP三大指令,九个内置对象,动作标签,JavaBean(包含内省),EL表达式,函数库