ViewDragHelper基本方法讲解
来源:互联网 发布:有没有钢琴软件 编辑:程序博客网 时间:2024/06/06 05:47
package com.adnonstop.draghelper.viewgroups;import android.content.Context;import android.support.v4.widget.ViewDragHelper;import android.util.AttributeSet;import android.view.MotionEvent;import android.view.View;import android.view.ViewGroup;import android.view.ViewTreeObserver;import android.widget.FrameLayout;/** * Created by gzq on 2017/1/19. */public class DragViewGroup extends FrameLayout { private ViewDragHelper dragHelper; private View mDragView; private View mAutoBackView; private View mEdgeTrackerView; private int mAutoBackViewOriginalPos_x; private int mAutoBackViewOriginalPos_y; public DragViewGroup(Context context) { this(context, null); } public DragViewGroup(Context context, AttributeSet attrs) { this(context, attrs, 0); } public DragViewGroup(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); dragHelper = ViewDragHelper.create(this, new DragCallback()); getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() { @Override public void onGlobalLayout() { initChild(); } }); //拖拽左边界回调 dragHelper.setEdgeTrackingEnabled(ViewDragHelper.EDGE_LEFT); } /** * 在viewGroup绘制初始化过程中,要一个一个添加子view,有多少个子view,就会调用多少次onViewAdded; * 可以在次做一些view类型判断的工作。 * * @param child */ @Override public void onViewAdded(View child) { super.onViewAdded(child);// if (!(child instanceof ViewGroup))// throw new RuntimeException("the child most be a viewgroup!"); } /** * 获取到子view。 */ private void initChild() { for (int index = 0; index < getChildCount(); index++) { View child = getChildAt(index); } } @Override public boolean onInterceptTouchEvent(MotionEvent ev) { return dragHelper.shouldInterceptTouchEvent(ev); } @Override public boolean onTouchEvent(MotionEvent event) { dragHelper.processTouchEvent(event); return true; } @Override protected void onLayout(boolean changed, int left, int top, int right, int bottom) { super.onLayout(changed, left, top, right, bottom); mAutoBackViewOriginalPos_x = mAutoBackView.getLeft(); mAutoBackViewOriginalPos_y = mAutoBackView.getTop(); } @Override protected void onFinishInflate() { super.onFinishInflate(); mDragView = getChildAt(0); mAutoBackView = getChildAt(1); mEdgeTrackerView = getChildAt(2); } @Override public void computeScroll() { if (dragHelper.continueSettling(true)) { invalidate(); } } private class DragCallback extends ViewDragHelper.Callback { /** * tryCaptureView 返回ture则表示可以捕获该view,你可以根据传入的第一个参数view决定哪些可以捕获 * * @param child * @param pointerId * @return */ @Override public boolean tryCaptureView(View child, int pointerId) { return true; } /** * @param child * @param left 对移动的边界进行控制 * @param dx * @return */ @Override public int clampViewPositionHorizontal(View child, int left, int dx) { int newLeft = Math.max(0, Math.min(left, getWidth() - child.getWidth())); return newLeft; } /** * @param child * @param top 控制移动的边界 * @param dy * @return */ @Override public int clampViewPositionVertical(View child, int top, int dy) { int newTop = Math.max(0, Math.min(top, getHeight() - child.getHeight())); return newTop; } /** * @param releasedChild * @param xvel 松手时沿X轴的速度 * @param yvel 松手时沿Y轴的速度 */ @Override public void onViewReleased(View releasedChild, float xvel, float yvel) { super.onViewReleased(releasedChild, xvel, yvel); if (releasedChild == mAutoBackView) { dragHelper.settleCapturedViewAt(mAutoBackViewOriginalPos_x, mAutoBackViewOriginalPos_y); invalidate(); } } /** * @param changedView * @param left new left * @param top new top * @param dx * @param dy */ @Override public void onViewPositionChanged(View changedView, int left, int top, int dx, int dy) { super.onViewPositionChanged(changedView, left, top, dx, dy); } // See also: // STATE_IDLE 静止 // STATE_DRAGGING 拖拽中 // STATE_SETTLING 自动滚动 @Override public void onViewDragStateChanged(int state) { super.onViewDragStateChanged(state); } /* * 边界拖动回调: * 在viewGroup的左边界拖动时的回调。 * */ @Override public void onEdgeDragStarted(int edgeFlags, int pointerId) { super.onEdgeDragStarted(edgeFlags, pointerId); System.out.println("******边界拖动回调**********"); } }}
点击打开链接
第一个View基本没做任何修改。
第二个View,我们在onLayout之后保存了最开启的位置信息,最主要还是重写了Callback中的onViewReleased
,我们在onViewReleased中判断如果是mAutoBackView则调用settleCapturedViewAt
回到初始的位置。大家可以看到紧随其后的代码是invalidate();因为其内部使用的是mScroller.startScroll,所以别忘了需要invalidate()以及结合computeScroll
方法一起。
第三个View,我们在onEdgeDragStarted
回调方法中,主动通过captureChildView
对其进行捕获,该方法可以绕过tryCaptureView,所以我们的tryCaptureView虽然并为返回true,但却不影响。注意如果需要使用边界检测需要添加上mDragger.setEdgeTrackingEnabled(ViewDragHelper.EDGE_LEFT);
。
到此,我们已经介绍了Callback中常用的回调方法了,当然还有一些方法没有介绍,接下来我们修改下我们的布局文件,我们把我们的TextView全部加上clickable=true,意思就是子View可以消耗事件。再次运行,你会发现本来可以拖动的View不动了,(如果有拿Button测试的兄弟应该已经发现这个问题了,我希望你看到这了,而不是已经提问了,哈~)。
原因是什么呢?主要是因为,如果子View不消耗事件,那么整个手势(DOWN-MOVE*-UP)都是直接进入onTouchEvent,在onTouchEvent的DOWN的时候就确定了captureView。如果消耗事件,那么就会先走onInterceptTouchEvent
方法,判断是否可以捕获,而在判断的过程中会去判断另外两个回调的方法:getViewHorizontalDragRange
和getViewVerticalDragRange
,只有这两个方法返回大于0的值才能正常的捕获。
所以,如果你用Button测试,或者给TextView添加了clickable = true ,都记得重写下面这两个方法:
@Overridepublic int getViewHorizontalDragRange(View child){ return 1;}@Overridepublic int getViewVerticalDragRange(View child){ return 1;}
- ViewDragHelper基本方法讲解
- ViewDragHelper讲解
- android ViewDragHelper讲解
- ViewDragHelper基本用法总结
- ViewDragHelper基本使用
- ViewDragHelper几个方法的理解
- 对象族谱之基本方法作用讲解
- ViewDragHelper
- ViewDragHelper
- ViewDragHelper
- ViewDragHelper
- ViewDragHelper
- ViewDragHelper
- ViewDragHelper
- ViewDragHelper
- ViewDragHelper
- ViewDragHelper
- ViewDragHelper.CallBack中每个方法的用法
- Android开发-优雅的实现多类型列表的Adapter
- CCNA学习笔记-1 基础知识回顾
- c++ try catch
- 学习laravel笔记
- 【长郡NOIP2014模拟10.22】搞笑的代码
- ViewDragHelper基本方法讲解
- 剑指offer-面试题27-二叉搜索树与双向链表
- 基于sparkMLlib的机器学习_[1]_基本数据类型[4]分布式矩阵DistrubutedMatrix
- Redis的泛泛之谈
- 设备驱动中的pci(kernel-4.7)
- Zabbix Server 3.0.7 Centos6.5编译安装
- HDUoj 1872 稳定排序
- ECMAScript2016笔记
- 批量导入json到mongodb的shell脚本