android ViewDragHelper介绍

来源:互联网 发布:淘宝店铺怎么添加宝贝 编辑:程序博客网 时间:2024/05/10 23:07

我们平时在自定义ViewGroup来实现一些复杂的效果时,基本都逃不过要处理事件的传递和分发,而ios在控件上可以上做的非常好,基本上都给封装好了,只需要调用和实现自己的业务逻辑就可以,这就是为什么同样的效果ios实现起来很简单,而android就不一样呢?最傻逼的是一些产品经理老拿ios跟android程序员说做出这个效果,心想妈的不知道开发成本不一样么,ios几行代码搞定,android有那么轻易搞定么,而且自定义控件本来就是android一个大头,比较难搞,像什么网络请求,图片加载之类的都有第三方会用就行,但是google就是给我们android挖坑,还好Google在你这方面也慢慢学习了ios,比如自定义viewgroup处理事件分发就引入了ViewDragHelper,它在v4包下,我也是最近没事干,所以找了相关资料研究下,也就是研究下它几个方法以及方法中的参数都是干嘛用的,

使用ViewDragHelper有二步:

1:创建ViewDragHelper对象实例,ViewDragHelper是不能new 只能通过类似工厂方法那样,具体你是不是工厂方法内部实现,我也不清楚,没看过这个源码,知道怎么创建它的实例对象就行

2;覆盖ViewDragHelper.CallBack接口中的几个方法,CallBack是ViewDragHelper内部定义的接口

现在就写个例子玩玩,新建一个android项目ViewDragHelperDemo,

activity_main.xml  里面写个了自定义控件

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"    xmlns:tools="http://schemas.android.com/tools"    android:layout_width="match_parent"    android:layout_height="match_parent"    tools:context="com.example.viewdraghelperdemo.MainActivity" >    <com.example.viewdraghelperdemo.MyLinearLayout        android:layout_width="match_parent"        android:layout_height="match_parent"        android:orientation="vertical"        >        <TextView            android:id="@+id/tv1"            android:layout_width="wrap_content"            android:layout_height="wrap_content"            android:padding="20dp"            android:text="东"            android:background="#ff9999"            />           <TextView            android:id="@+id/tv2"            android:layout_width="wrap_content"            android:layout_height="wrap_content"            android:padding="20dp"            android:text="西"            android:background="#ff00ff"            android:layout_marginTop="30dp"            />           <TextView            android:id="@+id/tv3"            android:layout_width="wrap_content"            android:layout_height="wrap_content"            android:padding="20dp"            android:text="北"            android:background="#ff0000"            android:layout_marginTop="30dp"            />        </com.example.viewdraghelperdemo.MyLinearLayout></RelativeLayout>

MyLinearLayout.java

/** * AUTHOR:Zhou Guizhi * * DESCRIPTION:create the File, and add the content. * * Copyright © ZhiMore. All Rights Reserved * */package com.example.viewdraghelperdemo;import android.content.Context;import android.support.v4.widget.ViewDragHelper;import android.support.v4.widget.ViewDragHelper.Callback;import android.util.AttributeSet;import android.view.MotionEvent;import android.view.View;import android.widget.LinearLayout;import android.widget.TextView;/** * Created in Mar 2, 2016 9:10:21 AM * @author Zhou Guizhi;  */public class MyLinearLayout extends LinearLayout {protected static final String TAG = "MyLinearLayout";private ViewDragHelper mDragHelper;private TextView tv1,tv2,tv3;/** * @param context * @param attrs * @param defStyleAttr */public MyLinearLayout(Context context, AttributeSet attrs, int defStyleAttr) {super(context, attrs, defStyleAttr);init();}/** *  */View temp;private void init() {mDragHelper = ViewDragHelper.create(this, 1.0f, new Callback() {@Overridepublic boolean tryCaptureView(View arg0, int arg1) {return arg0==tv1;}@Overridepublic int clampViewPositionHorizontal(View child, int left, int dx) {                 if(left<=0){                 left=0;                 }                 int w = getWidth()-child.getWidth();                 if(left>w){                 left = w;                 }return left;}@Overridepublic int clampViewPositionVertical(View child, int top, int dy) {if(top<=0){top=0;}int h = getHeight()-child.getHeight();if(top>h){top = h;}return top;}});}/** * @param context * @param attrs */public MyLinearLayout(Context context, AttributeSet attrs) {this(context, attrs,0);}/** * @param context */public MyLinearLayout(Context context) {this(context,null);}@Overridepublic boolean onTouchEvent(MotionEvent event) {mDragHelper.processTouchEvent(event);return true;}@Overridepublic boolean onInterceptTouchEvent(MotionEvent ev) {return mDragHelper.shouldInterceptTouchEvent(ev);}@Overrideprotected void onFinishInflate() {super.onFinishInflate();tv1 = (TextView) getChildAt(0);tv2 = (TextView) getChildAt(1);tv3 = (TextView) getChildAt(2);}}

如图:



现在可以实现这三个view随意在屏幕上拖动,也许会说这个太简单了,不用ViewDragHelper也能实现,是的,技术上实现方式很多种,但是你要考虑实现的时间成本,性能等各方面,当然了我们也是从简单往深点方面探索,

现在对实现CallBack中的三个方法做一个介绍

tryCaptureView(View arg0, int arg1) 是决定你铺货ViewGroup中那个子view,让这个子view可以在父view上有touch事件,比如你要一个子view可以有touch的话,就这样写

@Override
public boolean tryCaptureView(View arg0, int arg1) {
 return arg0==tv1;
}

它的第一个参数就是你拖动那个子view,如果你要想所有的子view都有touch事件的话,你可以直接返回true,当然了还有一个更傻逼的做法,就是获取viewGroup中所有的子view,然后

@Override
public boolean tryCaptureView(View arg0, int arg1) {
return arg0==tv1||arg0==tv2;
}

这种写法几乎不使用,但是比如你ViewGroup中有3个子view,想让其中二个子view可以有touch事件的话,就可以这样写了,如果你返回false的话,所有子view都不能接受touch事件

public int clampViewPositionHorizontal(View child, int left, int dx) 表示view水平方向滑动,第一个参数就是你当然拖动的子view,left是水平滑动的距离,自己可以打log看看它的值就知道了,如果你不想子view滑动超过屏幕的话,就要做些简单的逻辑判断了,

 if(left<=0){
     left=0;
}
int w = getWidth()-child.getWidth();
if(left>w){
    left = w;
 }

最后返回left就行,这就是限制view在滑动的过程中超过屏幕边缘,

public int clampViewPositionVertical(View child, int top, int dy) 表示的是view垂直滑动,第一个参数不用多说,第二个参数表示的是滑动时候离父view多少像素,第三个参数,没研究,

ViewDragHelper创建实例对象ViewDragHelper.create(this, 1.0f, new Callback())

第一个参数是ViewGroup,

第二个参数是是关于子view在滑动的灵敏度,它是这样计算的

mDragHelper.getTouchSlop()*(1/传递的第二个参数); 

第三个参数是CallBack的实现类,它是一个类,之前说它是一个接口,说错了,因为它里面很多方法,而不要求我们要实现它所有的方法所以是一个类,它里面大概有这么多方法 如下:


根据我们自己的需要 可以针对实现哪个方法,当然最好是每个方法都去研究分析下,

当然了还有二个很重要的方法,一个是onTouchEvent() 把touch事件交给ViewDragHelper处理,还有一个就是onInterceptTouchEvent()方法表示处理子view和父view的事件拦截

通常是这样写的

@Overridepublic boolean onTouchEvent(MotionEvent event) {mDragHelper.processTouchEvent(event);return true;}@Overridepublic boolean onInterceptTouchEvent(MotionEvent ev) {return mDragHelper.shouldInterceptTouchEvent(ev);}

现在对CallBack类中的其他方法也玩下,  打log分析

public void onViewReleased(View releasedChild, float xvel, float yvel)  这个方法从字面上都能看的懂他是干嘛用的,就是当你滑动过程中手指释放时候回调用的,

xvel:表示x方向每秒拖动的像素

yvel:同xvel参数

public void onEdgeTouched(int edgeFlags, int pointerId) 表示拖动到边缘时回调

public void onViewPositionChanged(View changedView, int left, int top, int dx, int dy) 子view拖动时发生改变时回调













0 0