package com.zhy.blogcodes.vdh; import android.content.Context; import android.support.v4.widget.ViewDragHelper; import android.util.AttributeSet; import android.view.MotionEvent; import android.view.View; import android.view.ViewGroup; /** * Created by zhy on 15/5/29. */ public class LeftDrawerLayout extends ViewGroup { private static final int MIN_DRAWER_MARGIN = 64; // dp /** * Minimum velocity that will be detected as a fling */ private static final int MIN_FLING_VELOCITY = 400; // dips per second /** * drawer离父容器右边的最小外边距 */ private int mMinDrawerMargin; private View mLeftMenuView; private View mContentView; private ViewDragHelper mHelper; /** * drawer显示出来的占自身的百分比 */ private float mLeftMenuOnScrren; public LeftDrawerLayout(Context context, AttributeSet attrs) { super(context, attrs); //setup drawer's minMargin final float density = getResources().getDisplayMetrics().density; final float minVel = MIN_FLING_VELOCITY * density; mMinDrawerMargin = (int) (MIN_DRAWER_MARGIN * density + 0.5f); mHelper = ViewDragHelper.create(this, 1.0f, new ViewDragHelper.Callback() { @Override public int clampViewPositionHorizontal(View child, int left, int dx) { int newLeft = Math.max(-child.getWidth(), Math.min(left, 0)); return newLeft; } @Override public boolean tryCaptureView(View child, int pointerId) { return child == mLeftMenuView; } @Override public void onEdgeDragStarted(int edgeFlags, int pointerId) { mHelper.captureChildView(mLeftMenuView, pointerId); } @Override public void onViewReleased(View releasedChild, float xvel, float yvel) { final int childWidth = releasedChild.getWidth(); float offset = (childWidth + releasedChild.getLeft()) * 1.0f / childWidth; mHelper.settleCapturedViewAt(xvel > 0 || xvel == 0 && offset > 0.5f ? 0 : -childWidth, releasedChild.getTop()); invalidate(); } @Override public void onViewPositionChanged(View changedView, int left, int top, int dx, int dy) { final int childWidth = changedView.getWidth(); float offset = (float) (childWidth + left) / childWidth; mLeftMenuOnScrren = offset; //offset can callback here changedView.setVisibility(offset == 0 ? View.INVISIBLE : View.VISIBLE); invalidate(); } @Override public int getViewHorizontalDragRange(View child) { return mLeftMenuView == child ? child.getWidth() : 0; } }); //设置edge_left track mHelper.setEdgeTrackingEnabled(ViewDragHelper.EDGE_LEFT); //设置minVelocity mHelper.setMinVelocity(minVel); } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { int widthSize = MeasureSpec.getSize(widthMeasureSpec); int heightSize = MeasureSpec.getSize(heightMeasureSpec); setMeasuredDimension(widthSize, heightSize); View leftMenuView = getChildAt(1); MarginLayoutParams lp = (MarginLayoutParams) leftMenuView.getLayoutParams(); final int drawerWidthSpec = getChildMeasureSpec(widthMeasureSpec, mMinDrawerMargin + lp.leftMargin + lp.rightMargin, lp.width); final int drawerHeightSpec = getChildMeasureSpec(heightMeasureSpec, lp.topMargin + lp.bottomMargin, lp.height); leftMenuView.measure(drawerWidthSpec, drawerHeightSpec); View contentView = getChildAt(0); lp = (MarginLayoutParams) contentView.getLayoutParams(); final int contentWidthSpec = MeasureSpec.makeMeasureSpec( widthSize - lp.leftMargin - lp.rightMargin, MeasureSpec.EXACTLY); final int contentHeightSpec = MeasureSpec.makeMeasureSpec( heightSize - lp.topMargin - lp.bottomMargin, MeasureSpec.EXACTLY); contentView.measure(contentWidthSpec, contentHeightSpec); mLeftMenuView = leftMenuView; mContentView = contentView; } @Override protected void onLayout(boolean changed, int l, int t, int r, int b) { View menuView = mLeftMenuView; View contentView = mContentView; MarginLayoutParams lp = (MarginLayoutParams) contentView.getLayoutParams(); contentView.layout(lp.leftMargin, lp.topMargin, lp.leftMargin + contentView.getMeasuredWidth(), lp.topMargin + contentView.getMeasuredHeight()); lp = (MarginLayoutParams) menuView.getLayoutParams(); final int menuWidth = menuView.getMeasuredWidth(); int childLeft = -menuWidth + (int) (menuWidth * mLeftMenuOnScrren); menuView.layout(childLeft, lp.topMargin, childLeft + menuWidth, lp.topMargin + menuView.getMeasuredHeight()); } @Override public boolean onInterceptTouchEvent(MotionEvent ev) { boolean shouldInterceptTouchEvent = mHelper.shouldInterceptTouchEvent(ev); return shouldInterceptTouchEvent; } @Override public boolean onTouchEvent(MotionEvent event) { mHelper.processTouchEvent(event); return true; } @Override public void computeScroll() { if (mHelper.continueSettling(true)) { invalidate(); } } public void closeDrawer() { View menuView = mLeftMenuView; mLeftMenuOnScrren = 0.f; mHelper.smoothSlideViewTo(menuView, -menuView.getWidth(), menuView.getTop()); } public void openDrawer() { View menuView = mLeftMenuView; mLeftMenuOnScrren = 1.0f; mHelper.smoothSlideViewTo(menuView, 0, menuView.getTop()); } @Override protected LayoutParams generateDefaultLayoutParams() { return new MarginLayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT); } public LayoutParams generateLayoutParams(AttributeSet attrs) { return new MarginLayoutParams(getContext(), attrs); } protected LayoutParams generateLayoutParams(LayoutParams p) { return new MarginLayoutParams(p); } }