自定义ViewGroup和ViewHelper的用法

参考网址:https://blog.csdn.net/itermeng/article/details/52159637?hmsr=toutiao.io&utm_medium=toutiao.io&utm_source=toutiao.io

package com.example.lirui.draggroupdemo;


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

import com.nineoldandroids.view.ViewHelper;

/**
 * Created by lirui on 2018/5/16.
 * 自定义ViewGroup必须重写OnLayout方法。
 */

public class MyDragView extends ViewGroup {
    private View mRedView;
    private View mBlueView;
    private ViewDragHelper viewDragHelper;

    //初始化的时候调用
    public MyDragView(Context context) {
        this(context, null);
    }

    //xml布局的调用
    public MyDragView(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public MyDragView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        //初始化
        init();
    }

    private void init() {
      /*创建ViewDragHelper 作用:它主要用于处理ViewGroup中对子View的拖拽处理
        它主要封装了对View的触摸位置,触摸速度,移动距离等的检测和Scroller,通过接口回调的方式通知我们。所以我们需要做的只是用接收来的数据指定这些子View是否需要移动,移动多少等。
      */
        viewDragHelper = ViewDragHelper.create(this, callBack);
    }

    private ViewDragHelper.Callback callBack = new ViewDragHelper.Callback() {
        //尝试捕获拖拽的view
        @Override
        public boolean tryCaptureView(@NonNull View child, int pointerId) {
            //返回要拖拽的view 确定那个view可以被拖拽
            return child==mRedView||child==mBlueView;
        }

        //捕获拖拽的view
        @Override
        public void onViewCaptured(@NonNull View capturedChild, int activePointerId) {
            super.onViewCaptured(capturedChild, activePointerId);
        }

        //View的位置发生变化 多次被调用 可做伴随动画
        @Override
        public void onViewPositionChanged(@NonNull View changedView, int left, int top, int dx, int dy) {
            super.onViewPositionChanged(changedView, left, top, dx, dy);
            if(changedView==mRedView){
                mBlueView.layout(mBlueView.getLeft()+dx,mBlueView.getTop()+dy,mBlueView.getRight()+dx,mBlueView.getBottom()+dy);
            }else if(changedView==mBlueView){
                mRedView.layout(mRedView.getLeft()+dx,mRedView.getTop()+dy,mRedView.getRight()+dx,mRedView.getBottom()+dy);
            }
            //执行动画
            //1.计算view移动的百分比
            float fraction = changedView.getLeft() * 1f / (getMeasuredWidth() - changedView.getMeasuredWidth());
            Log.e("tag","fraction:"+fraction);
            //2.执行一系列的伴随动画
            executeAnim(fraction);
        }

        //View被释放,手离开了屏幕
        @Override
        public void onViewReleased(@NonNull View releasedChild, float xvel, float yvel) {
            super.onViewReleased(releasedChild, xvel, yvel);
            int center = getMeasuredWidth() / 2 - releasedChild.getMeasuredWidth() / 2;
            if(releasedChild.getLeft()//自动向左移动 ScrollerScrollTo+ComputrScroll, 渐进式移动 , 属性动画
                viewDragHelper.smoothSlideViewTo(releasedChild,0,releasedChild.getTop());
                ViewCompat.postInvalidateOnAnimation(MyDragView.this);
            }else{
                //自动向右移动 注意调用动画必须重写computeScroll()方法
                viewDragHelper.smoothSlideViewTo(releasedChild,getMeasuredWidth()-releasedChild.getMeasuredWidth(),releasedChild.getTop());
                ViewCompat.postInvalidateOnAnimation(MyDragView.this);
            }
        }

        //view横向拖拽范围
        @Override
        public int getViewHorizontalDragRange(@NonNull View child) {
            return getMeasuredWidth()-mRedView.getMeasuredWidth();
        }

        //view纵向拖拽范围
        @Override
        public int getViewVerticalDragRange(@NonNull View child) {
            return getMeasuredHeight()-mRedView.getMeasuredHeight();
        }

        //改变view的横向滑动位置
        @Override
        public int clampViewPositionHorizontal(@NonNull View child, int left, int dx) {
            //不让子view滑出屏幕外
            if(left<0){
                left=0;
            }else if(left>getViewHorizontalDragRange(child)){
                left=getViewHorizontalDragRange(child);
            }
            return left;
        }

        //改变View的纵向滑动位置
        @Override
        public int clampViewPositionVertical(@NonNull View child, int top, int dy) {
            //不让子view滑出屏幕外
            if(top<0){
                top=0;
            }else if(top>getViewVerticalDragRange(child)){
                top=getViewVerticalDragRange(child);
            }
            return top;
        }
    };

    private void executeAnim(float fraction) {
        //ViewHelper.setScaleX(mRedView, fraction + 1);
        // ViewHelper.setScaleY(mRedView, fraction + 1);
        // ViewHelper.setRotationY(mRedView, 720 * fraction);
        //ViewHelper.setRotationY(mBlueView, 720 * fraction);
        // ViewHelper.setTranslationX(mRedView,100*fraction);
        //  ViewHelper.setAlpha(mRedView, 1 - fraction);
        ViewHelper.setRotationX(mRedView,720*fraction);
        mRedView.setBackgroundColor((Integer) ColorUtil.evaluateColor(fraction, Color.RED,Color.BLACK));
        setBackgroundColor((Integer) ColorUtil.evaluateColor(fraction, Color.YELLOW,Color.BLUE));
    }

    //xml文件执行完,紧接着执行该方法
    @Override
    protected void onFinishInflate() {
        super.onFinishInflate();
        //获取两个view的实例 开始测量
        mRedView = getChildAt(0);
        mBlueView = getChildAt(1);
    }

    //测量的方法
    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        //测量布局的宽和高 开始摆放位置
        measureChild(mRedView, widthMeasureSpec, heightMeasureSpec);
        measureChild(mBlueView, widthMeasureSpec, heightMeasureSpec);
    }

    //确定子view的位置的方法
    @Override
    protected void onLayout(boolean changed, int l, int t, int r, int b) {
        //确定两个子view的位置
        //如何摆放到父布局的中间位置 父布局的宽度的一般减去子view宽度的一半。
        //int left=getPaddingLeft()+getMeasuredWidth()/2-mRedView.getMeasuredWidth()/2;
        int left = getPaddingLeft();
        int top = getPaddingTop();
        mRedView.layout(left, top, left + mRedView.getMeasuredWidth(), top + mRedView.getMeasuredHeight());
        mBlueView.layout(left, top + mRedView.getMeasuredHeight(), left + mRedView.getMeasuredWidth(), top + mRedView.getMeasuredHeight() + mBlueView.getMeasuredHeight());
    }
    //ViewGroup的拦截事件交给DragHelper让其决定是否拦截
    @Override
    public boolean onInterceptHoverEvent(MotionEvent event) {
        return viewDragHelper.shouldInterceptTouchEvent(event);
    }
    //将触摸事件交给DragHelper进行处理 通过这一步和上一步ViewGroup的子View就可以滑动了。
    @Override
    public boolean onTouchEvent(MotionEvent event) {
        viewDragHelper.processTouchEvent(event);
        return true;
    }

    @Override
    public void computeScroll() {
        super.computeScroll();
        if(viewDragHelper.continueSettling(true)){
            ViewCompat.postInvalidateOnAnimation(MyDragView.this);
        }
    }
}

你可能感兴趣的:(自定义ViewGroup和ViewHelper的用法)