ViewDragHelper的使用

/*
 *  @Copyright (c) tianchenglin
 *  @Author TCL
 *  @Date 2016.6.22
 */

package com.study.tcl.studio.view;

import android.content.Context;
import android.graphics.Color;
import android.support.v4.view.ViewCompat;
import android.support.v4.widget.ViewDragHelper;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;

import com.nineoldandroids.view.ViewHelper;
import com.study.tcl.studio.utils.ColorUtil;

/**
 * Created by TCL on 2016/6/20.
 */
public class DragLayout extends ViewGroup {
    private View redView;
    private View blueView;
    private ViewDragHelper mViewDragHelper;

    public DragLayout(Context context) {
        super(context);
        init();
    }

    public DragLayout(Context context, AttributeSet attrs) {
        super(context, attrs);
        init();
    }

    public DragLayout(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init();
    }

    private void init() {
        mViewDragHelper = ViewDragHelper.create(this, 1.0f, new ViewDragHelper.Callback() {
            /**
             * 由于判断是否捕获当前child的触摸事件
             * @param child
             * @param pointerId
             * @return true:捕获并解析,false:不处理
             */
            @Override
            public boolean tryCaptureView(View child, int pointerId) {
                return blueView == child || redView == child;
            }

            /**
             * 当view被开始捕获和解析的回调
             * @param capturedChild 当前被捕获的子view
             * @param activePointerId
             */
            @Override
            public void onViewCaptured(View capturedChild, int activePointerId) {
                super.onViewCaptured(capturedChild, activePointerId);
            }

            /**
             * 获取view水平方向的拖拽范围,目前不能限制边界,返回的值目前用在
             * 手指抬起的时候view缓慢移动的动画时间的计算
             * @param child
             * @return
             */
            @Override
            public int getViewHorizontalDragRange(View child) {
                return getMeasuredWidth() - child.getMeasuredWidth();
            }

            /**
             * 控制view在水平方向的移动
             * @param child
             * @param left
             * 表示ViewDragHelper认为你想当前child的left改变的值,left=child.getLeft()+dx;
             * @param dx 本次child水平方向移动的距离
             * @return 你想让child的left变成的值
             */
            @Override
            public int clampViewPositionHorizontal(View child, int left, int dx) {
                //对左右边界进行限制
                if (left < 0) {
                    left = 0;
                } else if (left > getMeasuredWidth() - child.getMeasuredWidth()) {
                    left = getMeasuredWidth() - child.getMeasuredWidth();
                }
                return left;
            }

            /**
             * 获取view垂直方向的拖拽范围
             * @param child
             * @return
             */
            @Override
            public int getViewVerticalDragRange(View child) {
                return getMeasuredHeight() - child.getMeasuredHeight();
            }

            /**
             * 控制view在垂直方向的移动
             * @param child
             * @param top 表示ViewDragHelper认为你想当前child的top改变的值,top=child.getTop()+dy;
             * @param dy 本次child垂直方向移动的距离
             * @return
             */
            @Override
            public int clampViewPositionVertical(View child, int top, int dy) {
                if (top < 0) {
                    top = 0;
                } else if (top > getMeasuredHeight() - child.getMeasuredHeight()) {
                    top = getMeasuredHeight() - child.getMeasuredHeight();
                }
                return top;
            }

            /**
             * 当child位置改变时执行 一般用来做其他子view的伴随移动
             * @param changedView 位置改变的子view
             * @param left child当前最新的left
             * @param top child当前最新的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);
                if (changedView == redView) {
                    blueView.layout(blueView.getLeft() + dx, blueView.getTop() + dy, blueView.getRight() + dx,
                            blueView.getBottom() + dy);
                } else if (changedView == blueView) {
                    redView.layout(redView.getLeft() + dx, redView.getTop() + dy, redView.getRight() + dx, redView
                            .getBottom() + dy);
                }
                //1.计算view移动的百分比
                float fraction = changedView.getLeft() * 1f / (getMeasuredWidth() - changedView.getMeasuredWidth());
                executeAnim(fraction);
            }

            /**
             * 手指抬起执行该方法
             * @param releasedChild 当前抬起的view
             * @param xvel x方向移动的速度 正:向右移动 负:向左移动
             * @param yvel y方向移动的速度 正:向下移动 负:向上移动
             */
            @Override
            public void onViewReleased(View releasedChild, float xvel, float yvel) {
                super.onViewReleased(releasedChild, xvel, yvel);
                int centerLeft = (getMeasuredWidth() - releasedChild.getMeasuredWidth()) / 2;
                if (releasedChild.getLeft() < centerLeft) {
                    //在左半边,应该向左缓慢移动
                    mViewDragHelper.smoothSlideViewTo(releasedChild, 0, releasedChild.getTop());
//                    invalidate();
                    ViewCompat.postInvalidateOnAnimation(DragLayout.this);//刷新布局
                } else {
                    //向右缓慢移动
                    mViewDragHelper.smoothSlideViewTo(releasedChild, getMeasuredWidth() - releasedChild
                            .getMeasuredWidth(), releasedChild.getTop());
                    ViewCompat.postInvalidateOnAnimation(DragLayout.this);//刷新布局
                }
            }
        });
    }

    /**
     * 执行伴随动画
     *
     * @param fraction
     */
    private void executeAnim(float fraction) {

        //需要nineoldandroids.jar
        //放大缩小
//        ViewHelper.setScaleX(redView, 1 + 0.5f * fraction);
//        ViewHelper.setScaleY(redView, 1 + 0.5f * fraction);

        //旋转
//        ViewHelper.setRotation(redView, 720 * fraction);
        ViewHelper.setRotationX(redView, 360 * fraction);
        ViewHelper.setRotationX(blueView, 360 * fraction);

        //平移
//        ViewHelper.setTranslationX(redView, 80 * fraction);

        //透明
//        ViewHelper.setAlpha(redView, 1 - fraction);

        //过渡颜色的渐变
        redView.setBackgroundColor((Integer) ColorUtil.evaluateColor(fraction, Color.RED, Color.GREEN));
        //设置背景过渡
//        setBackgroundColor((Integer) ColorUtil.evaluateColor(fraction,Color.RED,Color.GREEN));
    }


    @Override
    public void computeScroll() {
        if (mViewDragHelper.continueSettling(true)) {
            ViewCompat.postInvalidateOnAnimation(DragLayout.this);//刷新布局
        }
    }

    /**
     * 当DragLayout的xml布局的结束的标签读取完成会执行此方法,此时就知道有几个字view了
     * 一般用来初始化子view的引用
     */
    @Override
    protected void onFinishInflate() {
        super.onFinishInflate();
        redView = getChildAt(0);
        blueView = getChildAt(1);
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        //测量自己的子view
        int childWidthMeasureSpec = MeasureSpec.makeMeasureSpec(redView.getLayoutParams().width, MeasureSpec.EXACTLY);
        int childHeightMeasureSpec = MeasureSpec.makeMeasureSpec(redView.getLayoutParams().height, MeasureSpec.EXACTLY);

        redView.measure(childWidthMeasureSpec, childHeightMeasureSpec);
        blueView.measure(childWidthMeasureSpec, childHeightMeasureSpec);

    }

    @Override
    protected void onLayout(boolean changed, int l, int t, int r, int b) {
        int left = 0 + getPaddingLeft() + (getMeasuredWidth() - redView.getMeasuredWidth()) / 2;
        int top = 0 + getPaddingTop();
        redView.layout(left, top, left + redView.getMeasuredWidth(), top + redView.getMeasuredHeight());
        blueView.layout(left, top + redView.getBottom(), left + blueView.getMeasuredWidth(), top + redView.getBottom
                () + blueView.getMeasuredHeight());
    }

    /**
     * 事件拦截
     */
    @Override
    public boolean onInterceptTouchEvent(MotionEvent ev) {
        //让ViewDragHelper帮我们判断是否拦截
        return mViewDragHelper.shouldInterceptTouchEvent(ev);
    }

    /**
     * 将触摸事件
     */
    @Override
    public boolean onTouchEvent(MotionEvent event) {
        //将触摸事件交给ViewDragHelper来解析处理
        mViewDragHelper.processTouchEvent(event);
        return true;
    }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值