|
|
楼主 |
发表于 2014-1-22 15:52:40
|
显示全部楼层
- package com.zhaoxufeng.leftsliderlayout.lib;
- import android.content.Context;
- import android.graphics.Rect;
- import android.util.AttributeSet;
- import android.util.Log;
- import android.view.MotionEvent;
- import android.view.VelocityTracker;
- import android.view.View;
- import android.view.ViewConfiguration;
- import android.view.ViewGroup;
- import android.widget.Scroller;
- public class LeftSliderLayout extends ViewGroup {
- private static final String TAG = "LeftSliderLayout" ;
- private Scroller mScroller;
- private VelocityTracker mVelocityTracker;
- /**
- * Constant value for touch state
- * TOUCH_STATE_REST : no touch
- * TOUCH_STATE_SCROLLING : scrolling
- */
- private static final int TOUCH_STATE_REST = 0;
- private static final int TOUCH_STATE_SCROLLING = 1;
- private int mTouchState = TOUCH_STATE_REST;
-
- /**
- * Distance in pixels a touch can wander before we think the user is scrolling
- */
- private int mTouchSlop;
-
- /**
- * Values for saving axis of the last touch event.
- */
- private float mLastMotionX;
- private float mLastMotionY;
-
- /**
- * Values for VelocityTracker to compute current velocity.
- * VELOCITY_UNITS in dp
- * mVelocityUnits in px
- */
- private static final int VELOCITY_UNITS = 1000;
- private int mVelocityUnits;
-
- /**
- * The minimum velocity for determining the direction.
- * MINOR_VELOCITY in dp
- * mMinorVelocity in px
- */
- private static final float MINOR_VELOCITY = 150.0f;
- private int mMinorVelocity;
-
- /**
- * The width of Sliding distance from left.
- * And it should be the same with the width of the View below SliderLayout in a FrameLayout.
- * DOCK_WIDTH in dp
- * mDockWidth in px
- */
- private static final float SLIDING_WIDTH = 270.0f;
- private int mSlidingWidth;
-
- /**
- * The default values of shadow.
- * VELOCITY_UNITS in dp
- * mVelocityUnits in px
- */
- private static final float DEF_SHADOW_WIDTH = 10.0f;
- private int mDefShadowWidth;
- /**
- * Value for checking a touch event is completed.
- */
- private boolean mIsTouchEventDone = false;
-
- /**
- * Value for checking slider is open.
- */
- private boolean mIsOpen = false;
-
- /**
- * Value for saving the last offset of scroller ’ x-axis.
- */
- private int mSaveScrollX = 0;
-
- /**
- * Value for checking slider is allowed to slide.
- */
- private boolean mEnableSlide = true;
-
- private View mMainChild = null;
- private OnLeftSliderLayoutStateListener mListener = null;
- /**
- * Instantiates a new LeftSliderLayout.
- *
- * @param context the associated Context
- * @param attrs AttributeSet
- */
- public LeftSliderLayout(Context context, AttributeSet attrs) {
- this(context, attrs, 0);
- }
- /**
- * Instantiates a new LeftSliderLayout.
- *
- * @param context the associated Context
- * @param attrs AttributeSet
- * @param defStyle Style
- */
- public LeftSliderLayout(Context context, AttributeSet attrs, int defStyle) {
- super(context, attrs, defStyle);
- mScroller = new Scroller(context);
- mTouchSlop = ViewConfiguration.get(getContext()).getScaledTouchSlop();
-
- /**
- * Convert values in dp to values in px;
- */
- final float fDensity = getResources().getDisplayMetrics().density;
- mVelocityUnits = (int) (VELOCITY_UNITS * fDensity + 0.5f);
- mMinorVelocity = (int) (MINOR_VELOCITY * fDensity + 0.5f);
- mSlidingWidth = (int) (SLIDING_WIDTH * fDensity + 0.5f);
- mDefShadowWidth = (int) (DEF_SHADOW_WIDTH * fDensity + 0.5f);
- }
-
- @Override
- protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
- super.onMeasure(widthMeasureSpec, heightMeasureSpec);
-
- // check Measure Mode is Exactly.
- final int widthMode = MeasureSpec.getMode(widthMeasureSpec);
- if (widthMode != MeasureSpec.EXACTLY) {
- throw new IllegalStateException("LeftSliderLayout only canmCurScreen run at EXACTLY mode!");
- }
- final int heightMode = MeasureSpec.getMode(heightMeasureSpec);
- if (heightMode != MeasureSpec.EXACTLY) {
- throw new IllegalStateException("LeftSliderLayout only can run at EXACTLY mode!");
- }
- // measure child views
- int nCount = getChildCount();
- for (int i = 2; i < nCount; i++) {
- removeViewAt(i);
- }
- nCount = getChildCount();
- if (nCount > 0) {
- if (nCount > 1) {
- mMainChild = getChildAt(1);
- getChildAt(0).measure(widthMeasureSpec, heightMeasureSpec);
- } else {
- mMainChild = getChildAt(0);
- }
- mMainChild.measure(widthMeasureSpec, heightMeasureSpec);
- }
-
- // Set the scrolled position
- scrollTo(mSaveScrollX, 0);
- }
-
- @Override
- protected void onLayout(boolean changed, int l, int t, int r, int b) {
- final int nCount = getChildCount();
- if (nCount <= 0) {
- return;
- }
-
- // Set the size and position of Main Child
- if (mMainChild != null) {
- mMainChild.layout(
- l,
- t,
- l + mMainChild.getMeasuredWidth(),
- t + mMainChild.getMeasuredHeight());
- }
-
- // Set the size and position of Shadow Child
- if (nCount > 1) {
- int nLeftChildWidth = 0;
- View leftChild = getChildAt(0);
- ViewGroup.LayoutParams layoutParams = leftChild.getLayoutParams();
- if (layoutParams.width == ViewGroup.LayoutParams.FILL_PARENT
- || layoutParams.width == ViewGroup.LayoutParams.MATCH_PARENT) {
- nLeftChildWidth = mDefShadowWidth;
- } else {
- nLeftChildWidth = layoutParams.width;
- }
- leftChild.layout(
- l - nLeftChildWidth,
- t,
- l,
- t + leftChild.getMeasuredHeight());
- }
- }
-
- @Override
- public void computeScroll() {
- if (mScroller.computeScrollOffset()) {
- Log.d(TAG,"computeScroll exeuted:" + "x:" + mScroller.getCurrX() + "Y:" + mScroller.getCurrY()) ;
- scrollTo(mScroller.getCurrX(), mScroller.getCurrY());
- postInvalidate();
- }
- }
- @Override
- public boolean onTouchEvent(MotionEvent event) {
-
- int nCurScrollX = getScrollX();
-
- // check touch point is in the rectangle of Main Child
- if (mMainChild != null
- && mTouchState != TOUCH_STATE_SCROLLING
- && mIsTouchEventDone) {
- Rect rect = new Rect();
- mMainChild.getHitRect(rect);
- if (!rect.contains((int)event.getX() + nCurScrollX, (int)event.getY())) {
- return false;
- }
- }
-
- if (mVelocityTracker == null) {
- mVelocityTracker = VelocityTracker.obtain();
- }
- mVelocityTracker.addMovement(event);
-
- final int action = event.getAction();
- final float x = event.getX();
-
- switch (action) {
- case MotionEvent.ACTION_DOWN: {
- if (!mScroller.isFinished()) {
- mScroller.abortAnimation();
- }
-
- mIsTouchEventDone = false;
- mLastMotionX = x;
- break;
- }
- case MotionEvent.ACTION_MOVE: {
- // check slider is allowed to slide.
- if (!mEnableSlide) {
- break;
- }
-
- // compute the x-axis offset from last point to current point
- int deltaX = (int) (mLastMotionX - x);
- if (nCurScrollX + deltaX < getMinScrollX()) {
- deltaX = getMinScrollX() - nCurScrollX;
- mLastMotionX = mLastMotionX - deltaX;
- } else if (nCurScrollX + deltaX > getMaxScrollX()) {
- deltaX = getMaxScrollX() - nCurScrollX;
- mLastMotionX = mLastMotionX - deltaX;
- } else {
- mLastMotionX = x;
- }
-
- // Move view to the current point
- if (deltaX != 0) {
- scrollBy(deltaX, 0);
- }
-
- // Save the scrolled position
- mSaveScrollX = getScrollX();
- break;
- }
- case MotionEvent.ACTION_CANCEL:
- case MotionEvent.ACTION_UP: {
-
- // check slider is allowed to slide.
- if (!mEnableSlide) {
- break;
- }
-
- final VelocityTracker velocityTracker = mVelocityTracker;
- velocityTracker.computeCurrentVelocity(mVelocityUnits);
-
- // Set open or close state, when get ACTION_UP or ACTION_CANCEL event.
- if (nCurScrollX < 0) {
- int velocityX = (int) velocityTracker.getXVelocity();
- if (velocityX > mMinorVelocity) {
- scrollByWithAnim(getMinScrollX() - nCurScrollX);
- setState(true);
- }
- else if (velocityX < -mMinorVelocity) {
- scrollByWithAnim(-nCurScrollX);
- setState(false);
- } else {
- if (nCurScrollX >= getMinScrollX() / 2) {
- scrollByWithAnim(- nCurScrollX);
- setState(false);
- } else {
- scrollByWithAnim(getMinScrollX() - nCurScrollX);
- setState(true);
- }
- }
- } else {
- if (nCurScrollX > 0) {
- scrollByWithAnim(-nCurScrollX);
- }
- setState(false);
- }
-
- if (mVelocityTracker != null) {
- mVelocityTracker.recycle();
- mVelocityTracker = null;
- }
- mTouchState = TOUCH_STATE_REST;
- mIsTouchEventDone = true;
- break;
- }
-
- }
- return true;
- }
-
复制代码
|
|