用ViewDragHelper自定義SlideMenu
阿新 • • 發佈:2018-11-30
記得匯入nineoldandroids-2.4.0.jar包
package com.example.slidemenu.view; import android.animation.FloatEvaluator; import android.animation.IntEvaluator; import android.content.Context; import android.graphics.Color; import android.graphics.PorterDuff.Mode; import android.support.v4.view.ViewCompat; import android.support.v4.widget.ViewDragHelper; import android.support.v4.widget.ViewDragHelper.Callback; import android.util.AttributeSet; import android.view.MotionEvent; import android.view.View; import android.widget.FrameLayout; import com.nineoldandroids.view.ViewHelper; public class SlideMenu extends FrameLayout { private View menuView; private View mainView; private int slidWidth; private ViewDragHelper viewDragHelper; private double RangeWidth; public State state = State.CLOSE; public SlideMenu(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); init(); } public SlideMenu(Context context, AttributeSet attrs) { super(context, attrs); init(); } public SlideMenu(Context context) { super(context); init(); } private void init() { menuView = getChildAt(0); mainView = getChildAt(1); viewDragHelper = ViewDragHelper.create(this, callBack); floatEvaluator = new FloatEvaluator(); intEvaluator = new IntEvaluator(); } public enum State { CLOSE, OPEN; } @Override protected void onFinishInflate() { super.onFinishInflate(); menuView = getChildAt(0); mainView = getChildAt(1); } @Override protected void onSizeChanged(int w, int h, int oldw, int oldh) { super.onSizeChanged(w, h, oldw, oldh); slidWidth = getMeasuredWidth(); RangeWidth = slidWidth * 0.6; } @Override public boolean onInterceptTouchEvent(MotionEvent ev) { return viewDragHelper.shouldInterceptTouchEvent(ev); } @Override public boolean onTouchEvent(MotionEvent event) { viewDragHelper.processTouchEvent(event); return true; } private Callback callBack = new Callback() { public boolean tryCaptureView(View child, int pointerId) { // 設定可拖拽的控制元件 return child == menuView || child == mainView; } public int getViewHorizontalDragRange(View child) { return (int) RangeWidth; }; @Override public int clampViewPositionHorizontal(View child, int left, int dx) { if (child == mainView) { if (left < 0) left = 0; if (left > RangeWidth) { left = (int) RangeWidth; } } return left; } @Override public void onViewPositionChanged(View changedView, int left, int top, int dx, int dy) { if (changedView == menuView) { menuView.layout(0, 0, menuView.getMeasuredWidth(), menuView.getMeasuredHeight()); int newLeft = dx + mainView.getLeft(); if (newLeft < 0) newLeft = 0; if (newLeft > RangeWidth) newLeft = (int) RangeWidth; mainView.layout(newLeft, 0, newLeft + mainView.getMeasuredWidth(), mainView.getMeasuredHeight()); } float fraction = (float) (mainView.getLeft() / RangeWidth); executeAnimation(fraction); if (fraction == 0 && state != State.CLOSE) { state = State.CLOSE; if (listener != null) { System.out.println("listener.onClose();"); listener.onClose(); } } if (fraction == 1 && state != State.OPEN) { state = State.OPEN; if (listener != null) { System.out.println("listener.onOpen();"); listener.onOpen(); } } // System.out.println("fraction" + fraction + "state" + state); if (listener != null) { listener.fractionChange(fraction); } super.onViewPositionChanged(changedView, left, top, dx, dy); } @Override public void onViewReleased(View releasedChild, float xvel, float yvel) { int mainLeft = mainView.getLeft(); if (mainLeft < RangeWidth / 2) { // 關閉 close(); } else { // 開啟 open(); } if (xvel > 200 && Math.abs(xvel) > Math.abs(yvel)) { open(); } if (xvel < -200 && Math.abs(xvel) > Math.abs(yvel)) { close(); } super.onViewReleased(releasedChild, xvel, yvel); } }; private FloatEvaluator floatEvaluator; private IntEvaluator intEvaluator; private onStateChangeListener listener; protected void executeAnimation(float fraction) { ViewHelper.setScaleX(menuView, floatEvaluator.evaluate(fraction, 0.6f, 1f)); ViewHelper.setScaleY(menuView, floatEvaluator.evaluate(fraction, 0.6f, 1f)); ViewHelper.setScaleX(mainView, floatEvaluator.evaluate(fraction, 1f, 0.6f)); ViewHelper.setScaleY(mainView, floatEvaluator.evaluate(fraction, 1f, 0.6f)); ViewHelper.setTranslationX(menuView, floatEvaluator.evaluate(fraction, -menuView.getMeasuredWidth() / 2, 0)); ViewHelper.setAlpha(menuView, floatEvaluator.evaluate(fraction, 0.5f, 1f)); getBackground().setColorFilter( (Integer) ColorUtil.evaluateColor(fraction, Color.BLACK, Color.TRANSPARENT), Mode.SRC_OVER); } public void close() { viewDragHelper.smoothSlideViewTo(mainView, 0, mainView.getTop()); ViewCompat.postInvalidateOnAnimation(SlideMenu.this); } public void open() { viewDragHelper.smoothSlideViewTo(mainView, (int) RangeWidth, mainView.getTop()); ViewCompat.postInvalidateOnAnimation(SlideMenu.this); } //注意,必須實現這個方法,用於滑動 @Override public void computeScroll() { if (viewDragHelper.continueSettling(true)) { ViewCompat.postInvalidateOnAnimation(SlideMenu.this); } super.computeScroll(); } public void setOnStateChangeListener(onStateChangeListener listener) { this.listener = listener; } public interface onStateChangeListener { public abstract void onClose(); public abstract void onOpen(); public abstract void fractionChange(float fraction); } }