博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Android ViewDragHelper:控制子View能否拖曳及水平方向的拖曳边界(2)
阅读量:6496 次
发布时间:2019-06-24

本文共 3954 字,大约阅读时间需要 13 分钟。



Android ViewDragHelper:控制子View能否拖曳及水平方向的拖曳边界(2)

附录文章1简单介绍了Android ViewDragHelper的使用,注意到附录文章1的代码运行结果,附录文章1的示例有三个子view,每个子view均可拖曳,但是,它们可以拖曳越出边界超出屏幕的显示范围,被拖曳到视野看不到的地方去了。

(1)在某些情况下,也许开发者不希望子view被拖曳到不可见的区域内,允许子view可以被拖曳,但不允许拖曳到不可见找不到它们!这些需求是可以代码控制。以水平拖曳为例,意图控制子view在水平方向视野可见区域内拖曳,不允许超出边界,那么就需要在:
clampViewPositionHorizontal()
里面添加约束条件。
水平拖曳的约束条件,并不是很复杂,只是需要了解设备屏幕的坐标体系。ViewGroup进行getWidth()获得的是该ViewGroup整个占据的屏幕坐标宽度,在我写的这个例子中,因为是MATCH_PARENT,且只有一个布局铺满整个屏幕,那么getWidth()就是完整的宽度。当用户在水平左边拖曳拖曳到极限位置(超出左边屏幕),那么此时clampViewPositionHorizontal()的left值为负数,意为越界,在这里下手,如果left值超出左边的边界,直接返回一个大于0的值即可。通常在实际的布局中处于设计美观的要求会padding一些值,刚好,如果此时getPaddingLeft(),获得的就是Android系统换算后左边的宽度,那么直接返回getPaddingLeft()值即可,如果没有padding值,返回一个0也可以。
右边的情况类似但稍微复杂些,考虑一种极限情况假设子view的右边刚好拖曳到父ViewGroup的右边完全重合,此时如果哪怕再往右拖曳1个坐标单位就要越界。那么此时可以得到如下等式:
getWidth() = pos + childView.getWidth()
pos为子view的左边坐标量。
如果父布局(ViewGroup)里面再padding一些值,那么等式变形为:
getWidth() = pos + childView.getWidth()+getPaddingRight()
多一个padding值而已。
计算得到的pos值即为最右边的极限位置,入股left > pos,那么此时就表明子view要越界了,立即返回pos值,这样就控制子view无法越界了。

(2)另外,通常一个布局文件里面有很多个子view,在某些情况下,可能开发者希望特定的子view不可被拖曳,完成这一些需求,则仅仅在tryCaptureView()里面针对特定的view返回false即可,false就是告诉Android系统,这个特定的子view是不被允许拖曳的。True则允许拖曳。

按照上述原理和思路修改增强附录1文章的MyLayout(其他代码不需改动):

package zhangphil.demo;import android.content.Context;import android.support.v4.widget.ViewDragHelper;import android.util.AttributeSet;import android.util.Log;import android.view.MotionEvent;import android.view.View;import android.widget.LinearLayout;/** * Created by Phil on 2016/4/15. */public class MyLayout extends LinearLayout {    private ViewDragHelper mViewDragHelper;    public MyLayout(Context context, AttributeSet attrs) {        super(context, attrs);        init();    }    private void init() {        mViewDragHelper = ViewDragHelper.create(this, 1.0f, new ViewDragHelperCallback());    }    private class ViewDragHelperCallback extends ViewDragHelper.Callback {        @Override        public boolean tryCaptureView(View view, int pointerId) {            //假设我不希望红色的子view可以被拖曳,那就加一层判断,只要是特定的view,直接返回false,false告诉Android系统,这个子view是不允许拖曳操作的。            if (view.getId() == R.id.red)                return false;            return true;        }        @Override        public int clampViewPositionHorizontal(View child, int left, int dx) {            //控制左边的拖曳距离,不能越界。            //当拖曳的距离超过左边的padding值,也意味着child view越界,复位            //默认的padding值=0            int paddingleft = getPaddingLeft();            if (left < paddingleft) {                return paddingleft;            }            //这里是控制右边的拖曳边缘极限位置。            //假设pos的值刚好是子view child右边边缘与父view的右边重合的情况            //pos值即为一个极限的最右边位置,超过也即意味着拖曳越界:越出右边的界限,复位。            //可以再加一个paddingRight值,缺省的paddingRight=0,所以即便不加也在多数情况正常可以工作            int pos = getWidth() - child.getWidth() - getPaddingRight();            if (left > pos) {                return pos;            }            //其他情况属于在范围内的拖曳,直接返回系统计算默认的left即可            return left;        }        @Override        public int clampViewPositionVertical(View child, int top, int dy) {            return top;        }        @Override        public void onViewDragStateChanged(int state) {            /**             switch (state) {             case ViewDragHelper.STATE_DRAGGING:             // 正在拖动             break;             case ViewDragHelper.STATE_IDLE:             // 没有被拖拽或者正在进行fling/snap             break;             case ViewDragHelper.STATE_SETTLING:             // fling完毕后被放置到一个位置             break;             }             */            super.onViewDragStateChanged(state);        }    }    @Override    public boolean onInterceptTouchEvent(MotionEvent event) {        return mViewDragHelper.shouldInterceptTouchEvent(event);    }    @Override    public boolean onTouchEvent(MotionEvent event) {        mViewDragHelper.processTouchEvent(event);        return true;    }}

代码运行结果,可以看到右上角的红色子view无法被拖到,剩余的子view控制在设计的区域范围内没有越界:

附录文章:
1,《Android ViewDragHelper(1)》链接地址:

你可能感兴趣的文章
[詹兴致矩阵论习题参考解答]习题1.3
查看>>
Android Fragment的使用
查看>>
mysql半同步复制实现
查看>>
沙朗javascript总结一下(一)---基础知识
查看>>
js深入研究之函数内的函数
查看>>
LeetCode:4_Median of Two Sorted Arrays | 求两个排序数组的中位数 | Hard
查看>>
uva-12657 - Boxes in a Line(双向链表)
查看>>
python之commands模块
查看>>
android应用开发--------------看RadioGroup源代码,写相似单选选项卡的集成控件(如底部导航,tab等等)...
查看>>
GCD 和延时调用
查看>>
LeetCode - Binary Tree Level Order Traversal
查看>>
FTP协议完全详解
查看>>
iOS:实现图片的无限轮播
查看>>
【C语言天天练(十五)】字符串输入函数fgets、gets和scanf
查看>>
【环境配置】配置sdk
查看>>
accept()
查看>>
USB 2.0 Hub IP Core
查看>>
USB 2.0 OTG IP Core
查看>>
解读浮动闭合最佳方案:clearfix
查看>>
Charles使用
查看>>