/*
* @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.graphics.PorterDuff;
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.widget.FrameLayout;
import com.nineoldandroids.animation.FloatEvaluator;
import com.nineoldandroids.animation.IntEvaluator;
import com.nineoldandroids.view.ViewHelper;
import com.study.tcl.studio.utils.ColorUtil;
/**
* Created by TCL on 2016/6/22.
*/
public class SlideMenu extends FrameLayout {
private View menuView;
private View mainView;
private ViewDragHelper mViewDragHelper;
private int width;
float dragRange;//拖拽范围
private onDragStateChangeListener mOnDragStateChangeListener;//拖拽的回调
//定义状态常量
public enum DragState {
Open, Close;
}
private DragState mCurrentState = DragState.Close;
public SlideMenu(Context context) {
super(context);
init();
}
public SlideMenu(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init();
}
public SlideMenu(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
private void init() {
mViewDragHelper = ViewDragHelper.create(this, new ViewDragHelper.Callback() {
@Override
public boolean tryCaptureView(View child, int pointerId) {
return child == menuView || child == mainView;
}
@Override
public int getViewHorizontalDragRange(View child) {
return (int) dragRange;
}
@Override
public int clampViewPositionHorizontal(View child, int left, int dx) {
if (child == mainView) {
if (left < 0) {
left = 0;//限制左边
}
if (left > dragRange) {
left = (int) dragRange;//限制右边
}
}
return left;
}
@Override
public void onViewPositionChanged(View changedView, int left, int top, int dx, int dy) {
super.onViewPositionChanged(changedView, left, top, dx, dy);
if (changedView == menuView) {
//固定menuView
menuView.layout(0, 0, menuView.getMeasuredWidth(), menuView.getMeasuredHeight());
//限制边界
int newLeft = mainView.getLeft() + dx;
if (newLeft < 0) {
newLeft = 0;
}
if (newLeft > dragRange) {
newLeft = (int) dragRange;//限制右边
}
mainView.layout(newLeft, mainView.getTop() + dy, newLeft + mainView.getMeasuredWidth(),
mainView.getBottom() + dy);
}
//1.计算当前百分比
float fraction = mainView.getLeft() / dragRange;
//2.执行伴随动画
executeAnim(fraction);
//3.更改状态回调方法
if (fraction == 0 && mCurrentState != DragState.Close) {
//更改状态为关闭,并回调关闭方法
mCurrentState = DragState.Close;
if (mOnDragStateChangeListener != null) {
mOnDragStateChangeListener.onClose();
}
}
if (fraction == 1 && mCurrentState != DragState.Open) {
//更改状态为打开,并回调关闭方法
mCurrentState = DragState.Open;
if (mOnDragStateChangeListener != null) {
mOnDragStateChangeListener.onOpen();
}
}
//将drag的fraction暴露给外界
if (mOnDragStateChangeListener != null) {
mOnDragStateChangeListener.onDraging(fraction);
}
}
@Override
public void onViewReleased(View releasedChild, float xvel, float yvel) {
super.onViewReleased(releasedChild, xvel, yvel);
if (mainView.getLeft() < dragRange / 2) {
//在左半边
close();
} else {
//在右半边
open();
}
//处理用户稍微滑动
if (xvel > 200 && mCurrentState != DragState.Open) {
open();
}
if (xvel < -200 && mCurrentState != DragState.Close) {
close();
}
}
});
}
public void open() {
mViewDragHelper.smoothSlideViewTo(mainView, (int) dragRange, 0);
ViewCompat.postInvalidateOnAnimation(SlideMenu.this);
}
public void close() {
mViewDragHelper.smoothSlideViewTo(mainView, 0, 0);
ViewCompat.postInvalidateOnAnimation(SlideMenu.this);
}
public interface onDragStateChangeListener {
/**
* 拖拽开始的回调
*/
void onOpen();
/**
* 拖拽结束的回调
*/
void onClose();
/**
* 拖拽中的回调
*
* @param fraction
*/
void onDraging(float fraction);
}
/**
* 获取当前状态
*
* @return
*/
public DragState getCurrentState() {
return mCurrentState;
}
public void setOnDragStateChangeListener(onDragStateChangeListener onDragStateChangeListener) {
this.mOnDragStateChangeListener = onDragStateChangeListener;
}
/**
* 执行伴随动画
*
* @param fraction
*/
private void executeAnim(float fraction) {
//fraction 0-1
//缩小mainView
FloatEvaluator floatEvaluator = new FloatEvaluator();//float的计算器
ViewHelper.setScaleX(mainView, (Float) floatEvaluator.evaluate(fraction, 1f, 0.8f));
ViewHelper.setScaleY(mainView, (Float) floatEvaluator.evaluate(fraction, 1f, 0.8f));
//移动menuView
IntEvaluator intEvaluator = new IntEvaluator();//int的计算器
ViewHelper.setTranslationX(menuView, intEvaluator.evaluate(fraction, -menuView.getMeasuredWidth() /
2, 0));
//放大menuView
ViewHelper.setScaleX(menuView, floatEvaluator.evaluate(fraction, 0.5, 1));
ViewHelper.setScaleY(menuView, floatEvaluator.evaluate(fraction, 0.5, 1));
//改变menuView的透明度
ViewHelper.setAlpha(menuView, floatEvaluator.evaluate(fraction, 0.3, 1));
//给SlideMenu添加黑色遮罩层效果
getBackground().setColorFilter((Integer) ColorUtil.evaluateColor(fraction, Color.BLACK, Color.TRANSPARENT),
PorterDuff.Mode.SRC_OVER);
}
@Override
public void computeScroll() {
if (mViewDragHelper.continueSettling(true)) {
ViewCompat.postInvalidateOnAnimation(SlideMenu.this);
}
}
/**
* 该方法在OnMearsure执行后执行,那么可以在该方法中初始化自己和子view的宽高
*
* @param w
* @param h
* @param oldw
* @param oldh
*/
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
width = getMeasuredWidth();
dragRange = width * 0.6f;
}
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
return mViewDragHelper.shouldInterceptTouchEvent(ev);
}
@Override
public boolean onTouchEvent(MotionEvent event) {
mViewDragHelper.processTouchEvent(event);
return true;
}
@Override
protected void onFinishInflate() {
super.onFinishInflate();
//简单的异常处理
if (getChildCount() != 2) {
throw new IllegalArgumentException("SlideMenu only have 2 children!");
}
menuView = getChildAt(0);
mainView = getChildAt(1);
}
}
自定义控件之QQ5.0侧滑效果
最新推荐文章于 2017-03-22 16:36:14 发布