Android ViewDragHelper:控制子View垂直方向拖曳不能越界(3)
附录文章1简单介绍了Android ViewDragHelper的使用,附录文章2介绍了如何控制ViewDragHelper在水平方向上拖曳不会被拖曳出边界,以及那些子view可以被拖曳,那些子view不能被拖曳。
但是还有一些遗漏问题尚未解决:垂直方向的拖曳。本文再附录文章2的基础加以改进,控制子view在垂直方向上的拖曳不越界。技术路线仍然是计算并通过调节边界极限坐标量实现。原理和附录文章2中控制水平方向子view拖曳不越界原理相同。
在附录文章2的MyLayout基础上改进代码,只需在clampViewPositionVertical()里面增加约束条件即可,其他代码不变:
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) {
//控制子view拖曳不能超过最顶部
int paddingTop = getPaddingTop();
if (top < paddingTop) {
return paddingTop;
}
//控制子view不能越出底部的边界。
int pos = getHeight() - child.getHeight() - getPaddingBottom();
if (top > pos) {
return pos;
}
//其他情况正常,直接返回Android系统计算的top即可。
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;
}
}
代码运行结果:
附录文章:
1,《Android ViewDragHelper(1)》链接地址:http://blog.csdn.net/zhangphil/article/details/51177588
2,《Android ViewDragHelper:控制子View能否拖曳及水平方向的拖曳边界(2)》链接地址:http://blog.csdn.net/zhangphil/article/details/51179680