DrawerLayout 从下方弹出的菜单控件

public class DrawerLayout extends FrameLayout {
	private ViewDragHelper mDragHelper;
	private Status mStatus = Status.Close;
	private Status target = mStatus;
	private int menuContainer;

	/**
	 * {@link DrawerLayout#replaceMenuView(FragmentManager, Fragment)}
	 * @param v
	 * @return
     */
	@Deprecated
	public DrawerLayout replaceMenuView(View v) {
		v.measure(0, 0);
		mMenuViewHeight = v.getMeasuredHeight();
		mMenuView.removeAllViews();
		mMenuView.addView(v);
		return this;
	}

	/**
	 * {@link DrawerLayout#replaceMenuView(FragmentManager, Fragment)}
	 * @param resId
     */
	@Deprecated
	public DrawerLayout replaceMenuView(int resId) {
		View inflate = LayoutInflater.from(getContext()).inflate(resId, mMenuView, false);
		replaceMenuView(inflate);
		return this;
	}

	public DrawerLayout replaceMenuView(FragmentManager fragmentManager, Fragment fragment){
		fragmentManager.beginTransaction().replace(menuContainer,fragment).commitAllowingStateLoss();
		return this;
	}

	public DrawerLayout(Context context, AttributeSet attrs, int defStyle) {
		super(context, attrs, defStyle);
		setFocusableInTouchMode(true);
		setFocusable(true);
		setBackgroundColor(Color.BLACK);
		mDragHelper = ViewDragHelper.create(this, mCallback);
	}

	public DrawerLayout(Context context, AttributeSet attrs) {
		this(context, attrs, 0);
	}

	public DrawerLayout(Context context) {
		this(context, null);
	}

	ViewDragHelper.Callback mCallback = new ViewDragHelper.Callback() {
		public boolean tryCaptureView(View arg0, int arg1) {
			return false;
		}

		public void onViewPositionChanged(View changedView, int left, int top, int dx, int dy) {
			float percent = (getHeight() - top) * 1.0f / mMenuViewHeight;
			animViews(percent);
			mStatus = updateStatus(percent);
			if (mStatus == Status.Close) {
				mShadeView.setVisibility(INVISIBLE);
			} else {
				mShadeView.setVisibility(VISIBLE);
			}
			invalidate();
		};
	};

	private Status updateStatus(float percent) {
		if (percent == 0f) {
			return Status.Close;
		} else if (percent == 1.0f) {
			return Status.Open;
		}
		return Status.Draging;
	}

	private void animViews(float percent) {
		mMainView.setScaleX(evaluate(percent, 1.0f, 0.8f));
		mMainView.setScaleY(evaluate(percent, 1.0f, 0.8f));
		mMainView.setTranslationY(evaluate(percent, 0, -0.4f * mMenuViewHeight));
		int color = evaluateColor(percent, Color.TRANSPARENT, 0x55000000);
		mShadeView.setBackgroundColor(color);
	}

	public Float evaluate(float fraction, Number startValue, Number endValue) {
		float startFloat = startValue.floatValue();
		return startFloat + fraction * (endValue.floatValue() - startFloat);
	}

	public int evaluateColor(float fraction, int startValue, int endValue) {
		int startInt = (Integer) startValue;
		int startA = (startInt >> 24) & 0xff;
		int startR = (startInt >> 16) & 0xff;
		int startG = (startInt >> 8) & 0xff;
		int startB = startInt & 0xff;

		int endInt = (Integer) endValue;
		int endA = (endInt >> 24) & 0xff;
		int endR = (endInt >> 16) & 0xff;
		int endG = (endInt >> 8) & 0xff;
		int endB = endInt & 0xff;

		return (int) ((startA + (int) (fraction * (endA - startA))) << 24)
				| (int) ((startR + (int) (fraction * (endR - startR))) << 16)
				| (int) ((startG + (int) (fraction * (endG - startG))) << 8)
				| (int) ((startB + (int) (fraction * (endB - startB))));
	}

	private ViewGroup mMenuView;
	private ViewGroup mMainView;
	private int mMenuViewHeight;
	private View mShadeView;
	private OnStateChangeListener listener;
	private Rect mTouchFrame;

	public void open(boolean isSmooth) {
		target = Status.Open;
		if (isSmooth) {
			int top = getHeight() - mMenuViewHeight;
			if (mDragHelper.smoothSlideViewTo(mMenuView, 0, top > 0 ? top : 0)) {
				ViewCompat.postInvalidateOnAnimation(this);
			}
			if (listener != null)
				listener.onStateChange(true);
		} else {
		}
	}

	public void close(boolean b) {
		target = Status.Close;
		if (b) {
			if (mDragHelper.smoothSlideViewTo(mMenuView, 0, getHeight())) {
				ViewCompat.postInvalidateOnAnimation(this);
			}
			if (listener != null)
				listener.onStateChange(false);
		} else {

		}
	}

	public void computeScroll() {
		super.computeScroll();
		if (mDragHelper.continueSettling(true)) {
			ViewCompat.postInvalidateOnAnimation(this);
		}
	}

	protected void onFinishInflate() {
		super.onFinishInflate();

		if (getChildCount() < 2) {
			throw new IllegalStateException(" Your ViewGroup must have 2 ViewGroup children at least.");
		}
		if (!(getChildAt(0) instanceof ViewGroup && getChildAt(1) instanceof ViewGroup)) {
			throw new IllegalArgumentException(AppConfiguration.getInstance().getContext().getString(R.string.view_exception)+"Your children must be an instance of ViewGroup");
		}

		mMenuView = (ViewGroup) getChildAt(1);
		mMainView = (ViewGroup) getChildAt(0);
		mShadeView = new View(getContext());
		mShadeView.setBackgroundColor(Color.TRANSPARENT);
		mMainView.addView(mShadeView);
		menuContainer = mMenuView.getId();
		if (menuContainer ==NO_ID){
			menuContainer = R.id.view_group_drawer_layout_container;
			mMenuView.setId(menuContainer);
		}
	}

	protected void onSizeChanged(int w, int h, int oldw, int oldh) {
		super.onSizeChanged(w, h, oldw, oldh);
		mMenuViewHeight = mMenuView.getMeasuredHeight();
		if(mStatus != Status.Close){
			mDragHelper.abort();
			if(target==Status.Close){
				close(true);
			}else {
				open(true);
			}
		}
	}

	@Override
	protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
		super.onLayout(changed, left, top, right, bottom);
		if (mStatus == Status.Close) {
			mMenuView.layout(left, bottom, right, bottom + mMenuViewHeight);
		} else if (mStatus == Status.Open) {
			mMenuView.layout(left, bottom - mMenuViewHeight, right, bottom);
		}
	}

	@Override
	public boolean onInterceptTouchEvent(MotionEvent ev) {
		int a = ev.getAction();

		if (MotionEvent.ACTION_DOWN == a && mStatus != Status.Close) {
			if (!inRangeOfView((int)ev.getX(), (int)ev.getY())) {
				close(true);
				return true;
			}
		}
		return super.onInterceptTouchEvent(ev);
	}

	public boolean inRangeOfView(int x, int y) {
		Rect frame = mTouchFrame;
		if (frame == null) {
			mTouchFrame = new Rect();
			frame = mTouchFrame;
		}
		if (mMenuView.getVisibility() == VISIBLE) {
			mMenuView.getHitRect(frame);
			return frame.contains(x, y);
		}
		return false;
	}

	public static enum Status {
		Close, Open, Draging;
	}

	public boolean isOpen() {
		return mStatus == Status.Open;
	}

	@Override
	public boolean onKeyDown(int keyCode, KeyEvent event) {
		if (KeyEvent.KEYCODE_BACK == keyCode && isOpen()) {// 事件拦截失败........
			close(true);
			return true;
		}
		return super.onKeyDown(keyCode, event);
	}

	public void setOnStateChangeListener(OnStateChangeListener listener) {
		this.listener = listener;
	}

	public static interface OnStateChangeListener {
		void onStateChange(boolean open);
	}
}

转载于:https://my.oschina.net/SSS555/blog/838558

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值