您的位置:首页 > 其它

ViewDragHelper简介

2016-07-03 13:42 381 查看

1,概述

简单地来说,ViewDragHelper是一个实现滑动布局的辅助类。比如Google在support库中提供的DrawerLayout布局,就是用ViewDragHelper来实现的。

虽然现在有现成的滑动布局可以供我们使用,但是只有掌握ViewDragHelper的用法,我们才能够更加灵活地自定义我们需要的控件。

通常,ViewDragHelper用在一个自定义的ViewGroup中。在自定义控件的过程中,除了实现callback的一些方法外,也要重写该ViewGroup的一些方法。

2,ViewGroup需要重写的方法

加载布局

@Override
protected void onFinishInflate() {
super.onFinishInflate();
mMenuView=getChildAt(0);
mMainView=getChildAt(1);
}


在本实例中,有两个子布局。一个是菜单布局,一个是主布局。

2.获取布局控件的大小

@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
mWidth=mMenuView.getMeasuredWidth();
}


在该方法中,可以获得一些控件的大小。该方法不一定需要重写。如果需要获得控件大小的话,该方法需要重写,否则不需要重写。在本例中是不需要获取某个控件的大小,这里只是举例说明该方法的用法。

3.事件拦截

/**
* 将事件传递给ViewDragHelper。
* @param ev
* @return
*/

@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
return mViewDragHelper.shouldInterceptTouchEvent(ev);

}

/**
* 返回true表示:事件不再继续向下传递,到本ViewGroup为止。
* @param event
* @return
*/
@Override
public boolean onTouchEvent(MotionEvent event) {
mViewDragHelper.processTouchEvent(event);
return true;
}


这两个方法必须要重写。

4.滑动时视图的绘制方法

/**
*
*Scroller的核心方法,系统在绘制View的时候会在draw()方法中调用该方法。
*如果在继续滚动,mViewDragHelper.continueSettling(true)返回值为true,视图进行更新。*/

@Override
public void computeScroll() {
if(mViewDragHelper.continueSettling(true)){
ViewCompat.postInvalidateOnAnimation(this);
}
}


3,ViewDragHelper.Callback常用方法介绍

@Override
public boolean tryCaptureView(View child, int pointerId) {
return mMainView==child;
}


该方法表示什么时候开始检测事件,返回true表示开始检测滑动事件。更直观的理解就是,返回哪个View,哪个View就可以滑动。在本例中,只需要主布局mMainView可以滑动。

@Override
public int clampViewPositionHorizontal(View child, int left, int dx) {
/**
* dx描述的是速度
*/
Log.i("liang","left is"+left);
Log.i("liang","dx is"+dx);
if(left<0){
left=0;//使其不能向左滑动
}
return left;
}

@Override
public int clampViewPositionVertical(View child, int top, int dy) {
return 0;
}


这是两个实现滑动的具体方法。如果是水平滑动,则需要重写第一个方法。如果是垂直滑动,则需要重写第二个方法。

这两个方法返回0表示不能滑动。left和top这两个参数分别表示在水平方向和垂直方向上滑动的距离(严格的来说是x和y方向上的坐标)。

在本例中,我们是水平滑动的,因此需要重写clampViewPositionHorizontal(View child, int left, int dx)方法。而clampViewPositionVertical(View child, int top, int dy)我们返回0或者不去重写。

在第一个方法中,如果我们只返回left,那么主布局便可以左右滑动,这样显然不是我们需要的,一般情况下侧滑只需要右滑动即可。left<0表示向左滑动,因此一旦检测出用户有向右滑动的手势,那么我们就直接返回0,不去响应滑动事件。

@Override
public void onViewReleased(View releasedChild, float xvel, float yvel) {
super.onViewReleased(releasedChild, xvel, yvel);
if(mMainView.getLeft()<300){
mViewDragHelper.smoothSlideViewTo(mMainView,0,0);
ViewCompat.postInvalidateOnAnimation(DragViewGroup.this);
}else{
mViewDragHelper.smoothSlideViewTo(mMainView, 500, 0);
ViewCompat.postInvalidateOnAnimation(DragViewGroup.this);
}
}


该方法实现手指离开屏幕后实现的操作。

滑动后,如果主布局距离左侧少于300个像素,则通过mViewDragHelper.smoothSlideViewTo(mMainView,0,0)使主布局停留在起始的位置。即左上角的坐标仍为(0,0)。

如果距离左侧的像素大于300,则使主布局左上角停留在坐标为(500,0)的位置上。即主布局距离左侧有500个像素,这样,菜单布局就显示出来了。

ViewCompat.postInvalidateOnAnimation(DragViewGroup.this)是用来刷新视图的。每次主布局的坐标改变后,该方法通知UI线程刷新画面。

除了这几个方法之外,onViewCaptured(),onViewDragStateChanged(),onViewPositionChanged()等方法。有兴趣的读者可以自行查看其用法。

4,源码

自定义的ViewCroup:DragViewGroup

public class DragViewGroup extends FrameLayout {
private ViewDragHelper mViewDragHelper;
private View mMenuView,mMainView;
private int mWidth;
private Context context;

public DragViewGroup(Context context) {
super(context);
this.context=context;
initView();
}

public DragViewGroup(Context context, AttributeSet attrs) {
super(context, attrs);
this.context=context;
initView();
}

public DragViewGroup(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
this.context=context;
initView();
}

@Override
protected void onFinishInflate() {
super.onFinishInflate();
mMenuView=getChildAt(0);
mMainView=getChildAt(1);
}

@Override protected void onSizeChanged(int w, int h, int oldw, int oldh) { super.onSizeChanged(w, h, oldw, oldh); mWidth=mMenuView.getMeasuredWidth(); }

/**
* 将事件传递给ViewDragHelper。
* @param ev
* @return
*/

@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
return mViewDragHelper.shouldInterceptTouchEvent(ev);

}

/**
* 返回true表示:事件不再继续向下传递,到本ViewGroup为止。
* @param event
* @return
*/
@Override
public boolean onTouchEvent(MotionEvent event) {
mViewDragHelper.processTouchEvent(event);
return true;
}

private void initView(){
mViewDragHelper=ViewDragHelper.create(this,callback);
}

private ViewDragHelper.Callback callback=new ViewDragHelper.Callback() {
@Override
public boolean tryCaptureView(View child, int pointerId) {
return mMainView==child;
}

@Override
public int clampViewPositionHorizontal(View child, int left, int dx) {
/**
* dx描述的是速度
*/
Log.i("liang","left is"+left);
Log.i("liang","dx is"+dx);
if(left<0){
left=0;//使其不能向左滑动
}
return left;
}

@Override
public int clampViewPositionVertical(View child, int top, int dy) {
return 0;
}

@Override public void onViewReleased(View releasedChild, float xvel, float yvel) { super.onViewReleased(releasedChild, xvel, yvel); if(mMainView.getLeft()<300){ mViewDragHelper.smoothSlideViewTo(mMainView,0,0); ViewCompat.postInvalidateOnAnimation(DragViewGroup.this); }else{ mViewDragHelper.smoothSlideViewTo(mMainView, 500, 0); ViewCompat.postInvalidateOnAnimation(DragViewGroup.this); } }

@Override
public void onViewDragStateChanged(int state) {
super.onViewDragStateChanged(state);

}
};

/**
*
*Scroller的核心方法,系统在绘制View的时候会在draw()方法中调用该方法。
*如果在继续滚动,mViewDragHelper.continueSettling(true)返回值为true,视图进行更新。*/

@Override
public void computeScroll() {
if(mViewDragHelper.continueSettling(true)){
ViewCompat.postInvalidateOnAnimation(this);
}
}
}


2.布局文件:activity_main

包含两个子布局,menuLayout和mainLayout

<widget.DragViewGroup 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=".MainActivity">

<RelativeLayout
android:id="@+id/mennuLyout"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:orientation="vertical" >

<RelativeLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:id="@+id/rl1"
>

<ImageView
android:id="@+id/id_img1"
android:layout_width="50dp"
android:layout_height="50dp"
android:layout_centerVertical="true"
android:layout_marginLeft="20dp"
android:layout_marginTop="20dp"
android:src="@mipmap/img_1" />

<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:layout_marginLeft="20dp"
android:layout_toRightOf="@id/id_img1"
android:text="第一个Item"
android:textColor="@android:color/black"
android:textSize="20sp" />
</RelativeLayout>

<RelativeLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content"
>

<ImageView
android:id="@+id/id_img2"
android:layout_width="50dp"
android:layout_height="50dp"
android:layout_centerVertical="true"
android:layout_marginLeft="20dp"
android:layout_marginTop="20dp"
android:src="@mipmap/img_2" />

<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:layout_marginLeft="20dp"
android:layout_toRightOf="@id/id_img2"
android:text="第二个Item"
android:textColor="@android:color/black"
android:textSize="20sp" />
</RelativeLayout>

<RelativeLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content" >

<ImageView
android:id="@+id/id_img3"
android:layout_width="50dp"
android:layout_height="50dp"
android:layout_centerVertical="true"
android:layout_marginLeft="20dp"
android:layout_marginTop="20dp"
android:src="@mipmap/img_3" />

<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:layout_marginLeft="20dp"
android:layout_toRightOf="@id/id_img3"
android:text="第三个Item"
android:textColor="@android:color/black"
android:textSize="20sp" />
</RelativeLayout>

<RelativeLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content" >

<ImageView
android:id="@+id/id_img4"
android:layout_width="50dp"
android:layout_height="50dp"
android:layout_centerVertical="true"
android:layout_marginLeft="20dp"
android:layout_marginTop="20dp"
android:src="@mipmap/img_4" />

<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:layout_marginLeft="20dp"
android:layout_toRightOf="@id/id_img4"
android:text="第四个Item"
android:textColor="@android:color/black"
android:textSize="20sp" />
</RelativeLayout>

<RelativeLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content" >

<ImageView
android:id="@+id/id_img5"
android:layout_width="50dp"
android:layout_height="50dp"
android:layout_centerVertical="true"
android:layout_marginLeft="20dp"
android:layout_marginTop="20dp"
android:src="@mipmap/img_5" />

<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:layout_marginLeft="20dp"
android:layout_toRightOf="@id/id_img5"
android:text="第五个Item"
android:textColor="@android:color/black"
android:textSize="20sp" />
</RelativeLayout>

<RelativeLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content" >

<ImageView
android:id="@+id/id_img6"
android:layout_width="50dp"
android:layout_height="50dp"
android:layout_centerVertical="true"
android:layout_marginLeft="20dp"
android:layout_marginTop="20dp"
android:src="@mipmap/img_1" />

<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:layout_marginLeft="20dp"
android:layout_toRightOf="@id/id_img6"
android:text="第一个Item"
android:textColor="@android:color/black"
android:textSize="20sp" />
</RelativeLayout>
</LinearLayout>

</RelativeLayout>

<RelativeLayout
android:id="@+id/mainLayout"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
>
<ImageView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scaleType="centerCrop"
android:src="@drawable/zhangdi"
/>

</RelativeLayout>

</widget.DragViewGroup>


3.效果图

滑动之前的效果。主界面仅仅是一张图片



滑动后,菜单布局显示出来了

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  布局 谷歌 控件