原文:https://www.jianshu.com/p/d58e5766ae1c
https://www.jianshu.com/p/d78515acb4c6
ViewDragHelper是针对 ViewGroup 中的拖拽和重新定位 views 操作时提供了一系列非常有用的方法和状态追踪。基本上使用在自定义ViewGroup处理拖拽中!
public class DragLayout extends LinearLayout {
private ViewDragHelper mDragger;
private ImageView iv1;
private Point initPointPosition = new Point ();
@Override
protected void onFinishInflate() {
iv1 = (ImageView) this.findViewById (R.id.iv1);
super.onFinishInflate ();
}
public DragLayout(Context context) {
super (context);
}
public DragLayout(Context context, AttributeSet attrs) {
super (context, attrs);
ViewDragHelper.Callback callback = new DraggerCallBack ();
//第二个参数就是滑动灵敏度的意思 可以随意设置
mDragger = ViewDragHelper.create (this, 1.0f, callback);
}
class DraggerCallBack extends ViewDragHelper.Callback {
/**
* @param pointerId 表示触摸点的id, 比如多点按压的那个id
* @return 是否可以capture, 也就是是否可以滑动.可以根据不同的child决定是否可以滑动
*/
@Override
public boolean tryCaptureView(View child, int pointerId) {
return true;
}
/**
* @param left 表示当前的view正要移动到左边距为left的地方
* @param dx 表示和上一次滑动的距离间隔
* @return 最终确定的移动的位置
*/
@Override
public int clampViewPositionHorizontal(View child, int left, int dx) {
//取得左边界的坐标
final int leftBound = getPaddingLeft ();
//取得右边界的坐标
final int rightBound = getWidth () - child.getWidth () - leftBound;
return Math.min (Math.max (left, leftBound), rightBound);
}
@Override
public int clampViewPositionVertical(View child, int top, int dy) {
final int topBound = getPaddingTop ();
final int bottomBound = getHeight () - child.getHeight () - topBound;
return Math.min (Math.max (top, topBound), bottomBound);
}
@Override
public void onViewReleased(View releasedChild, float xvel, float yvel) {
//松手的时候 判断如果是这个view 就让他回到起始位置
mDragger.settleCapturedViewAt (initPointPosition.x, initPointPosition.y);
invalidate ();//postInvalidate
}
//如果需要滑动的View,会消耗touch事件,比如:Button,那么需要重写以下方法.
// @Override
// public int getViewHorizontalDragRange(View child) {
// return child.getMeasuredWidth();//只要返回大于0的值就行
// }
//
// @Override
// public int getViewVerticalDragRange(View child) {
// return child.getMeasuredHeight();//只要返回大于0的值就行
// }
}
@Override
public void computeScroll() {
if (mDragger.continueSettling (true)) {
invalidate ();//postInvalidate
}
}
@Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
super.onLayout (changed, l, t, r, b);
//布局完成的时候就记录一下位置
initPointPosition.x = iv1.getLeft ();
initPointPosition.y = iv1.getTop ();
}
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
//决定是否拦截当前事件
return mDragger.shouldInterceptTouchEvent (ev);
}
@Override
public boolean onTouchEvent(MotionEvent event) {
//处理事件
mDragger.processTouchEvent (event);
return true;
}
}
拖拽DEMO
public class DragView extends FrameLayout {
ViewDragHelper helper;
private View tv1;
private View tv2;
private int width;
private float dragRange;
FloatEvaluator floatEvaluator;
public DragView(@NonNull Context context) {
this(context,null);
}
public DragView(@NonNull Context context, @Nullable AttributeSet attrs) {
this(context, attrs,0);
}
public DragView(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
initData();
}
@Override
protected void onFinishInflate() {
super.onFinishInflate();
tv1 = getChildAt(0);
tv2 = getChildAt(1);
}
private void initData() {
floatEvaluator = new FloatEvaluator();
helper = ViewDragHelper.create(this,callback);
}
@Override
public boolean onTouchEvent(MotionEvent event) {
helper.processTouchEvent(event);
return true;
}
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
return helper.shouldInterceptTouchEvent(ev);
}
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
width = getMeasuredWidth();
dragRange = (width*0.6f);
}
ViewDragHelper.Callback callback = new ViewDragHelper.Callback() {
@Override
public boolean tryCaptureView(@NonNull View child, int pointerId) {
return child == tv2;
}
@Override
public void onViewPositionChanged(@NonNull View changedView, int left, int top, int dx, int dy) {
super.onViewPositionChanged(changedView, left, top, dx, dy);
executeAnim(changedView.getLeft()/dragRange);
}
@Override
public int getViewHorizontalDragRange(@NonNull View child) {
return (int) dragRange;
}
@Override
public int clampViewPositionHorizontal(@NonNull View child, int left, int dx) {
if(left<0){
left = 0;
}else if(left > dragRange){
left = (int) dragRange;
}
return left;
}
@Override
public void onViewReleased(@NonNull View releasedChild, float xvel, float yvel) {
super.onViewReleased(releasedChild, xvel, yvel);
if(releasedChild.getLeft() < dragRange/2){
helper.smoothSlideViewTo(releasedChild,0,releasedChild.getTop());
ViewCompat.postInvalidateOnAnimation(DragView.this);
}else{
helper.smoothSlideViewTo(releasedChild, (int) dragRange,releasedChild.getTop());
ViewCompat.postInvalidateOnAnimation(DragView.this);
}
}
};
private void executeAnim(float fraction) {
Float scaleValue = floatEvaluator.evaluate(fraction, 1, 0.8);
tv2.setScaleX(scaleValue);
tv2.setScaleY(scaleValue);
}
@Override
public void computeScroll() {
if (helper.continueSettling(true)) {
ViewCompat.postInvalidateOnAnimation(DragView.this);
}
}
}
网友评论