/*
* @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;
}
}
ViewDragHelper的使用
最新推荐文章于 2021-11-08 23:21:44 发布