声明:请勿转载 否则子孙世世代代在第三世界做软件开发
该篇文章摘自google Android 框架设计者Adam Powell的博客
原文链接:Each Navigation Drawer hides a ViewDragHelper - Flavien Laurent
代码下载:https://github.com/flavienlaurent/flavienlaurent.com/tree/master/viewdraghelper
效果:
DrawerLayout
。
ViewDragHelper.Callback 通常用来作为VHD和父试图之间的通讯通道
使用VDH
LinearLayout,并且她包括了一个简单的子View。
1 public class DragLayout extends LinearLayout {
2
3 private final ViewDragHelper mDragHelper;
4 private View mDragView;
5
6 public DragLayout(Context context) {
7 this(context, null);
8 }
9
10 public DragLayout(Context context, AttributeSet attrs) {
11 this(context, attrs, 0);
12 }
13
14 public DragLayout(Context context, AttributeSet attrs, int defStyle) {
15 super(context, attrs, defStyle);
16 }
创建一个VDH和它的callback,记住:你可以给它指定一个滑动时候的灵敏度,官方文档上表示值越大,值越大,灵敏度也就越高,正常的大小是1.0f。
public DragLayout(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
mDragHelper = ViewDragHelper.create(this, 1.0f, new DragHelperCallback());
}
最重要的方式是调用VDH的onInterceptTouch
和 onTouch
.
public boolean onInterceptTouchEvent(MotionEvent ev) {
final int action = MotionEventCompat.getActionMasked(ev);
if (action == MotionEvent.ACTION_CANCEL || action == MotionEvent.ACTION_UP) {
mDragHelper.cancel();
return false;
}
return mDragHelper.shouldInterceptTouchEvent(ev);
}
@Override
public boolean onTouchEvent(MotionEvent ev) {
mDragHelper.processTouchEvent(ev);
return true;
}
现在你可以通过配置Callback方法去改变VDH的行为了。
只能横向滑动:之可以去实现clampViewPositionHorizontal允许横向的滑动,记住:官方文档上说,默认的情况下你如果没有显示的去配置是只能允许横向滑动的。你必须指定margins参数和 parent padding参数。下面的这种情况是不允许的。
public int clampViewPositionHorizontal(View child, int left, int dx) { Log.d("DragLayout", "clampViewPositionHorizontal " + left + "," + dx); final int leftBound = getPaddingLeft(); final int rightBound = getWidth() - mDragView.getWidth(); final int newLeft = Math.min(Math.max(left, leftBound), rightBound); return newLeft; }
效果图:
纵向滑动:实现clampViewPositionVertical允许纵向滑动,记住官方文档上说默认情况下是不允许纵向滑动的。你必须指定margins参数和 parent padding参数。下面的这种情况是不允许的。
@Override public int clampViewPositionVertical(View child, int top, int dy) { final int topBound = getPaddingTop(); final int bottomBound = getHeight() - mDragView.getHeight(); final int newTop = Math.min(Math.max(top, topBound), bottomBound); return newTop; }
效果图:
捕获或者是不捕获一个view
实现tryCaptureView去允许子view能不能被滑动,比如这里有两个子view,但是只能有一个子view被滑动。
@Override public boolean tryCaptureView(View child, int pointerId) { return child == mDragView1; }
效果图:
滑动范围:
实现getViewHorizontalDragRange or getViewVerticalDragRange来返回横向或者是纵向滑动的范围,这里是以像素为单位的。这个范围会被VDH用到,当你调用smoothSlideViewTo或者是
settleCapturedViewAt去计算滚动的距离,并且,它也可以用来检查横向和纵向触摸滚动.
边缘拖动:这个功能通常用在DrawerLayout with EDGE_LEFT and EDGE_RIGHT.
你可以去配置VDH允许其进行边缘滚动的检查
mDragHelper.setEdgeTrackingEnabled(ViewDragHelper.EDGE_LEFT);
实现onEdgeTouched,这时当前被滚动的子view就会被捕捉到。
@Override public void onEdgeTouched(int edgeFlags, int pointerId) { super.onEdgeTouched(edgeFlags, pointerId); Toast.makeText(getContext(), "edgeTouched", Toast.LENGTH_SHORT).show(); }
实现onEdgeDragStarted,当一个真正的拖动开始的时候,并且这是一个子view是不会被捕获到的,除非你给他制定一个子视图。
@Override public void onEdgeDragStarted(int edgeFlags, int pointerId) { mDragHelper.captureChildView(mDragView2, pointerId); }
效果图:
实战操作:
最近在我的手机上,我收到了youtube的更新,在更新之前,比较让人讨厌的是我不能同时看视频和搜索下一个视频,VDH很好的解决了这个问题。下面是效果图并且效果图之后贴上主要的代码。
所有评论(0)