android ViewDragHelper介绍

我们平时在自定义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() {
			@Override
			public boolean tryCaptureView(View arg0, int arg1) {
				return arg0==tv1;
			}
			@Override
			public 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;
			}
			@Override
			public 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);
	}
	@Override
	public boolean onTouchEvent(MotionEvent event) {
		mDragHelper.processTouchEvent(event);
		return true;
	}
	@Override
	public boolean onInterceptTouchEvent(MotionEvent ev) {
		return mDragHelper.shouldInterceptTouchEvent(ev);
	}
	@Override
	protected 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的事件拦截

通常是这样写的

	@Override
	public boolean onTouchEvent(MotionEvent event) {
		mDragHelper.processTouchEvent(event);
		return true;
	}
	@Override
	public 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
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值