Android之ViewDragHelper的使用

来源:互联网 发布:网络聊天用语段子 编辑:程序博客网 时间:2024/04/28 21:20

Android之ViewDragHelper的使用

关于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.
这段话很容易理解,不重复啰嗦了。

实例

使用步骤:
1.使用ViewDragHelper的静态方法create创建,需要传人一个ViewDragHelper.CallBack对象;
2.实现ViewDragHelper.CallBack中的方法,来实现对视图的一些操作,如拖拽等
3.onInterceptTouchEvent和onTouchEvent回调ViewDragHelper中对应方法

下面通过实例来简单了解一下一些主要方法的使用:

  • tryCaptureView
  • clampViewPositionHorizontal
  • clampViewPositionVertical
  • onEdgeDragStarted
  • onViewReleased
  • getViewHorizontalDragRange/getViewVerticalDragRange

activity_main.xml:

<?xml version="1.0" encoding="utf-8"?><c.viewdraghpdemo.ViewDrag xmlns:android="http://schemas.android.com/apk/res/android"    xmlns:tools="http://schemas.android.com/tools"    android:id="@+id/activity_main"    android:layout_width="match_parent"    android:layout_height="match_parent"    android:paddingBottom="16dp"    android:paddingLeft="@dimen/activity_horizontal_margin"    android:paddingRight="@dimen/activity_horizontal_margin"    android:paddingTop="@dimen/activity_vertical_margin"    tools:context="c.viewdraghpdemo.MainActivity">    <TextView        android:layout_width="150dp"        android:layout_height="150dp"        android:text="Hello World!"        android:background="@android:color/holo_blue_dark"/></c.viewdraghpdemo.ViewDrag>

自定义的View

package c.viewdraghpdemo;import android.content.Context;import android.support.v4.widget.DrawerLayout;import android.support.v4.widget.ViewDragHelper;import android.util.AttributeSet;import android.util.Log;import android.view.MotionEvent;import android.view.View;import android.widget.LinearLayout;import android.widget.TextView;/** * Created by Administrator on 2016/9/26. */public class ViewDrag extends LinearLayout {    private static final String TAG = "hly";    private ViewDragHelper mViewDrag;    private TextView tv;    public ViewDrag(Context context) {        super(context, null);    }    public ViewDrag(Context context, AttributeSet attrs) {        super(context, attrs);        init();    }    public ViewDrag(Context context, AttributeSet attrs, int defStyleAttr) {        super(context, attrs, defStyleAttr);        init();    }    private void init() {        //Step1:使用静态方法构造ViewDragHelper,其中需要传入一个ViewDragHelper.Callback回调对象.        mViewDrag = ViewDragHelper.create(this, 1.0f, mViewDragCB);        //setEdgeTrackingEnabled设置的边界滑动时触发        mViewDrag.setEdgeTrackingEnabled(ViewDragHelper.EDGE_LEFT);    }    ViewDragHelper.Callback mViewDragCB = new ViewDragHelper.Callback() {        @Override        public boolean tryCaptureView(View child, int pointerId) {            //返回ture则表示可以捕获该view            return true;        }        @Override        public int clampViewPositionHorizontal(View child, int left, int dx) {            //手指触摸移动时实时回调, left就是child.getLeft()的值            return left;        }        @Override        public int clampViewPositionVertical(View child, int top, int dy) {            //同理            return top;        }    };    //重写onInterceptTouchEvent回调ViewDragHelper中对应的方法.    @Override    public boolean onInterceptTouchEvent(MotionEvent ev) {        return mViewDrag.shouldInterceptTouchEvent(ev);    }    //重写onTouchEvent回调ViewDragHelper中对应的方法.    @Override    public boolean onTouchEvent(MotionEvent event) {        mViewDrag.processTouchEvent(event);        return true;    }    //得到child实例    @Override    protected void onFinishInflate() {        tv = (TextView) getChildAt(0);    }}

相关方法的用处已经在代码里注释了,应该很好理解

MainActivity.java

package c.viewdraghpdemo;import android.support.v7.app.AppCompatActivity;import android.os.Bundle;public class MainActivity extends AppCompatActivity {    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);    }}

简单运行一下,看看效果:
这里写图片描述

可以看见现在TextView可以被拖动了,但是这里发现可以被拖到屏幕外面,这时候就要在ViewDragHelper.CallBack里面处理一下了,具体修改如下:

        @Override        //手指触摸移动时实时回调, left就是child.getLeft()的值        public int clampViewPositionHorizontal(View child, int left, int dx) {            //可左右滑动的空间            int spaceX = getWidth()  - getPaddingRight() - child.getWidth();            return Math.min(Math.max(getPaddingLeft(), left), spaceX);        }        @Override        public int clampViewPositionVertical(View child, int top, int dy) {            //同理            int spaceY = getHeight() - getPaddingBottom() - child.getHeight();            return Math.min(Math.max(getPaddingTop(), top), spaceY);        }    };

运行一下,发现不会移动到屏幕外了:
这里写图片描述

在上面的代码里面还有一句

mViewDrag.setEdgeTrackingEnabled(ViewDragHelper.EDGE_LEFT);

这个是滑动到边界的时候触发的,还需要在CallBack中实现一个方法

 @Override        public void onEdgeDragStarted(int edgeFlags, int pointerId) {            //当tryCaptureView为false时也可以生效            mViewDrag.captureChildView(tv, pointerId);            }
     具体效果:     ![这里写图片描述](http://img.blog.csdn.net/20160926173405240)

当我们释放手指时,想让子View滑到一个指定位置,可以用CallBack中的onViewReleased方法:

 @Override        public void onViewReleased(View releasedChild, float xvel, float yvel) {            if (releasedChild == tv) {                mViewDrag.settleCapturedViewAt(300,300);                invalidate();            }       }

当onViewReleased中的invalidate()被调用之后,会不断调用调用computeScroll(),因此,要在ViewDrag类中重写一下这个方法:

@Override    public void computeScroll() {        if (mDragHelper.continueSettling(true)) {            invalidate();        }    }

运行效果:
这里写图片描述

当给tv设置了clickable为ture时,或者子view为Button时,发现根据上述的代码,拖拽子view是没反应的,原因是拖动的时候onInterceptTouchEvent方法,判断是否可以捕获,而在判断的过程中会去判断另外两个回调的方法getViewHorizontalDragRange和getViewVerticalDragRange,只有这两个方法返回大于0的值才能正常的捕获。如果未能正常捕获就会导致手势down后面的move以及up都没有进入到onTouchEvent。
解决方法:

@Override        public int getViewHorizontalDragRange(View child) {            return getMeasuredWidth() - child.getWidth();        }        @Override        public int getViewVerticalDragRange(View child) {            return getMeasuredHeight() - child.getHeight();        }

参考资料 :
http://blog.csdn.net/u012551350/article/details/51601985

0 0
原创粉丝点击