diff --git a/README.md b/README.md index 380c9b5..4cb8689 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,5 @@ +[![Android Gems](http://www.android-gems.com/badge/flyfei/CustomMenu.svg?branch=master)](http://www.android-gems.com/lib/flyfei/CustomMenu) + CustomMenu is a custom control that can help you quickly create Menu Features: @@ -20,7 +22,7 @@ Features: * Only the right menu - ![](https://github.com/flyfei/CustomMenu/blob/master/resources/only_right_menu.gif) + ![](https://github.com/flyfei/CustomMenu/blob/master/resources/only_right_menu.gif) * Together with the right and left menu @@ -49,8 +51,69 @@ customMenu.setLeftMenu(leftMenu); ImageView rightMenu = new ImageView(this); rightMenu.setBackgroundResource(R.drawable.left_view); customMenu.setRightMenu(rightMenu); + +//Open Left Menu +customMenu.openLeftMenuIfPossible(); + +//Open Right Menu +customMenu.openRightMenuIfPossible(); + +//Close Menu +customMenu.closeMenu(); + +//Get State +customMenu.getState() + +//Setting the right Shadow +setRightShadow(int resId); +setRightShadow(Drawable shadowRight); + +//Setting the left Shadow +setLeftShadow(int resId); +setLeftShadow(Drawable shadowLeft); ``` +* [Shadow picture resources](https://github.com/flyfei/CustomMenu/tree/master/resources/shadowImg) + +## Latest Version + + +[Download](https://github.com/flyfei/CustomMenu/wiki) + + ## Feedback If you have any questions,please emailto:zhaotengfei9@gmail.com + + + +## Thanks + +[designzway](http://freebies.designzway.com/) + + +## Copyright and Licensing + + +``` +The MIT License (MIT) + +Copyright © 2015 Tovi + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the “Software”), to deal in the +Software without restriction, including without limitation the rights to use, copy, +modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, +and to permit persons to whom the Software is furnished to do so, subject to the +following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, +INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A +PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +``` \ No newline at end of file diff --git a/README_CN.md b/README_CN.md index ccaa0b7..0498957 100644 --- a/README_CN.md +++ b/README_CN.md @@ -46,8 +46,36 @@ customMenu.setLeftMenu(leftMenu); ImageView rightMenu = new ImageView(this); rightMenu.setBackgroundResource(R.drawable.left_view); customMenu.setRightMenu(rightMenu); + +//打开左菜单 +customMenu.openLeftMenuIfPossible(); + +//打开右菜单 +customMenu.openRightMenuIfPossible(); + +//关闭菜单 +customMenu.closeMenu(); + +//获取状态 +customMenu.getState() + +//设置右侧阴影 +setRightShadow(int resId); +setRightShadow(Drawable shadowRight); + +//设置左侧阴影 +setLeftShadow(int resId); +setLeftShadow(Drawable shadowLeft); ``` +* [阴影图片资源](https://github.com/flyfei/CustomMenu/tree/master/resources/shadowImg) + +## Latest Version + + +[Download](https://github.com/flyfei/CustomMenu/wiki) + + ## 反馈 如果发现问题,请 emailto:zhaotengfei9@gmail.com diff --git a/app/src/main/java/com/tovi/custommenu/MainActivity.java b/app/src/main/java/com/tovi/custommenu/MainActivity.java index 2dd71e4..7870d0d 100644 --- a/app/src/main/java/com/tovi/custommenu/MainActivity.java +++ b/app/src/main/java/com/tovi/custommenu/MainActivity.java @@ -2,14 +2,27 @@ import android.app.Activity; import android.os.Bundle; +import android.util.Log; +import android.view.View; import android.view.Window; import android.view.WindowManager; import android.widget.ImageView; import cn.tovi.CustomMenu; +/** + * @author zhaotengfei9@gmail.com + */ + +/** + * The following code is only for understanding the Custom interface + */ public class MainActivity extends Activity { + private static final String TAG = MainActivity.class.getSimpleName(); + + CustomMenu customMenu; + @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); @@ -22,23 +35,56 @@ protected void onCreate(Bundle savedInstanceState) { WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION); - CustomMenu customMenu = new CustomMenu(this); + customMenu = new CustomMenu(this); - //设置中间布局 - ImageView contentView = new ImageView(this); - contentView.setBackgroundResource(R.drawable.main_view); - customMenu.setContentView(contentView); + //Setting Content Layout +// ImageView contentView = new ImageView(this); +// contentView.setBackgroundResource(R.drawable.main_view); + customMenu.setContentView(R.layout.activity_main); - //设置左菜单 + customMenu.setRightShadow(R.drawable.shadow_right); + customMenu.setLeftShadow(R.drawable.shadow_left); + //Setting the left menu ImageView leftMenu = new ImageView(this); leftMenu.setBackgroundResource(R.drawable.left_view); customMenu.setLeftMenu(leftMenu); - //设置右菜单 + //Setting the right menu ImageView rightMenu = new ImageView(this); rightMenu.setBackgroundResource(R.drawable.left_view); customMenu.setRightMenu(rightMenu); setContentView(customMenu); } + + private void leftMenu() { + if (customMenu.getState() == CustomMenu.State.CLOSE_MENU) { + customMenu.openLeftMenuIfPossible(); + } else if (customMenu.getState() == CustomMenu.State.LEFT_MENU_OPENS) { + customMenu.closeMenu(); + } else { + Log.e(TAG, "CustomMenu State:" + customMenu.getState()); + } + } + + private void rightMenu() { + if (customMenu.getState() == CustomMenu.State.CLOSE_MENU) { + customMenu.openRightMenuIfPossible(); + } else if (customMenu.getState() == CustomMenu.State.RIGHT_MENU_OPENS) { + customMenu.closeMenu(); + } else { + Log.e(TAG, "CustomMenu State:" + customMenu.getState()); + } + } + + public void onClick(View view) { + switch (view.getId()) { + case R.id.btn_left_menu: + leftMenu(); + break; + case R.id.btn_right_menu: + rightMenu(); + break; + } + } } diff --git a/app/src/main/res/drawable/main_view.png b/app/src/main/res/drawable/main_view.png index 3526896..05b2bd3 100644 Binary files a/app/src/main/res/drawable/main_view.png and b/app/src/main/res/drawable/main_view.png differ diff --git a/app/src/main/res/drawable/shadow_left.9.png b/app/src/main/res/drawable/shadow_left.9.png new file mode 100644 index 0000000..8cf8d4f Binary files /dev/null and b/app/src/main/res/drawable/shadow_left.9.png differ diff --git a/app/src/main/res/drawable/shadow_right.9.png b/app/src/main/res/drawable/shadow_right.9.png new file mode 100644 index 0000000..9273e09 Binary files /dev/null and b/app/src/main/res/drawable/shadow_right.9.png differ diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml index f7158b8..f1f7dc3 100644 --- a/app/src/main/res/layout/activity_main.xml +++ b/app/src/main/res/layout/activity_main.xml @@ -1,11 +1,27 @@ + xmlns:tools="http://schemas.android.com/tools" + android:layout_width="match_parent" + android:layout_height="match_parent" + android:background="@drawable/main_view" + tools:context=".MainActivity"> - + + diff --git a/library/src/main/java/cn/tovi/CustomMenu.java b/library/src/main/java/cn/tovi/CustomMenu.java index 7829c80..35990e6 100644 --- a/library/src/main/java/cn/tovi/CustomMenu.java +++ b/library/src/main/java/cn/tovi/CustomMenu.java @@ -1,8 +1,10 @@ package cn.tovi; import android.content.Context; +import android.graphics.Canvas; import android.graphics.Point; -import android.os.Build; +import android.graphics.drawable.Drawable; +import android.support.annotation.DrawableRes; import android.support.annotation.LayoutRes; import android.util.AttributeSet; import android.util.Log; @@ -11,59 +13,120 @@ import android.view.VelocityTracker; import android.view.View; import android.view.ViewConfiguration; +import android.view.animation.AccelerateDecelerateInterpolator; import android.view.animation.DecelerateInterpolator; import android.widget.FrameLayout; import android.widget.RelativeLayout; import android.widget.Scroller; +/** + * @author zhaotengfei9@gmail.com + */ public class CustomMenu extends RelativeLayout { private static final String TAG = CustomMenu.class.getSimpleName(); - + private static final int TEST_DIS = 20; private Context context; /** - * 左侧Menu + * To the left menu */ private FrameLayout leftMenu; /** - * 中间Menu + * Middle view */ - private FrameLayout middleMenu; + private FrameLayout middleView; /** - * 右侧Menu + * To the right menu */ private FrameLayout rightMenu; /** - * 中部遮罩 + * middle Mask */ - private FrameLayout middleMask; +// private FrameLayout middleMask; /** - * 滚动器 + * Scroller, more slowly */ - private Scroller mScroller; - - + private Scroller mScrollerMoreSlowly; + /** + * Scroller, slow down after + */ + private Scroller mScrollerSlowDownAfter; private int mTouchSlop; private int mMinimumVelocity; private int mMaximumVelocity; /** - * 速度管理器 + * Velocity Tracker */ private VelocityTracker mVelocityTracker; + private State state; + /** + * Whether the finger touch(In touch event, you must first set) + */ + private boolean fingerTouch; + private boolean isTestCompete; + /** + * Is not sliding around event + */ + private boolean isLeftrightEvent; + private Point point = new Point(); + +// private ImageView leftMask; +// private ImageView rightMask; + + private Drawable mShadowLeft; + private Drawable mShadowRight; + public CustomMenu(Context context) { - super(context); - initView(context); + this(context, null); } public CustomMenu(Context context, AttributeSet attrs) { - super(context, attrs); + this(context, attrs, 0); + } + + public CustomMenu(Context context, AttributeSet attrs, int defStyleAttr) { + super(context, attrs, defStyleAttr); initView(context); } - public void setLeftMenu(@LayoutRes int resid) { - setLeftMenu(LayoutInflater.from(getContext()).inflate(resid, null)); + public void setContentView(@LayoutRes int resId) { + setContentView(LayoutInflater.from(getContext()).inflate(resId, null)); + } + + public void setContentView(View view) { + if (view != null) { + middleView.removeView(view); + } + + middleView.setPadding(0, 0, 0, 0); + middleView.addView(view, new FrameLayout.LayoutParams(FrameLayout.LayoutParams.MATCH_PARENT, FrameLayout.LayoutParams.MATCH_PARENT)); + + //设置阴影 +// if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) { +// if (leftMask != null) +// middleView.removeView(leftMask); +// else { +// leftMask = new ImageView(context); +// leftMask.setBackgroundResource(R.drawable.middle_left); +// } +// if (rightMask != null) +// middleView.removeView(rightMask); +// else { +// rightMask = new ImageView(context); +// rightMask.setBackgroundResource(R.drawable.middle_right); +// } +// FrameLayout.LayoutParams f = new FrameLayout.LayoutParams(FrameLayout.LayoutParams.WRAP_CONTENT, FrameLayout.LayoutParams.MATCH_PARENT); +// f.gravity = Gravity.RIGHT; +// middleView.addView(leftMask, new FrameLayout.LayoutParams(FrameLayout.LayoutParams.WRAP_CONTENT, FrameLayout.LayoutParams.MATCH_PARENT)); +// middleView.addView(rightMask, f); +// } + + } + + public void setLeftMenu(@LayoutRes int resId) { + setLeftMenu(LayoutInflater.from(getContext()).inflate(resId, null)); } public void setLeftMenu(View view) { @@ -75,21 +138,17 @@ public void setLeftMenu(View view) { leftMenu.addView(view); } - public void setContentView(@LayoutRes int resid) { - setContentView(LayoutInflater.from(getContext()).inflate(resid, null)); + public void setLeftShadow(@DrawableRes int resId) { + setLeftShadow(getResources().getDrawable(resId)); } - public void setContentView(View view) { - if (view != null) { - middleMenu.removeView(view); - } - middleMenu.setPadding(0, 0, 0, 0); - middleMenu.addView(view, new FrameLayout.LayoutParams(FrameLayout.LayoutParams.MATCH_PARENT, FrameLayout.LayoutParams.MATCH_PARENT)); - Log.e("", "left:" + middleMenu.getPaddingLeft()); + public void setLeftShadow(Drawable shadowLeft) { + mShadowLeft = shadowLeft; + invalidate(); } - public void setRightMenu(@LayoutRes int resid) { - setRightMenu(LayoutInflater.from(getContext()).inflate(resid, null)); + public void setRightMenu(@LayoutRes int resId) { + setRightMenu(LayoutInflater.from(getContext()).inflate(resId, null)); } public void setRightMenu(View view) { @@ -101,24 +160,73 @@ public void setRightMenu(View view) { rightMenu.addView(view); } + public void setRightShadow(@DrawableRes int resId) { + setRightShadow(getResources().getDrawable(resId)); + } + + public void setRightShadow(Drawable shadowRight) { + mShadowRight = shadowRight; + invalidate(); + } + + public State getState() { + return this.state; + } + + public void openLeftMenuIfPossible() { + if (leftMenu != null) { + // If the view is rolling, stop + stopAllScroll(); + if (getScrollX() != -leftMenu.getMeasuredWidth()) { + mScrollerSlowDownAfter.startScroll(getScrollX(), 0, -leftMenu.getMeasuredWidth() - getScrollX(), 0); + invalidate(); + } + } + } + + public void openRightMenuIfPossible() { + if (rightMenu != null) { + // If the view is rolling, stop + stopAllScroll(); + if (getScrollX() != rightMenu.getMeasuredWidth()) { + mScrollerSlowDownAfter.startScroll(getScrollX(), 0, rightMenu.getMeasuredWidth() - getScrollX(), 0); + invalidate(); + } + } + } + + public void closeMenu() { + // If the view is rolling, stop + stopAllScroll(); + if (getScrollX() != 0) { + mScrollerSlowDownAfter.startScroll(getScrollX(), 0, -getScrollX(), 0); + invalidate(); + } + } + private void initView(Context context) { this.context = context; - middleMenu = new FrameLayout(context); - middleMask = new FrameLayout(context); + middleView = new FrameLayout(context); +// middleView.setBackgroundColor(Color.TRANSPARENT); +// middleMask = new FrameLayout(context); - middleMask.setBackgroundColor(0x88000000); - middleMask.setAlpha(0f); +// middleMask.setBackgroundColor(0x88000000); +// middleMask.setAlpha(0f); - addView(middleMenu); -// addView(middleMask);//注释遮罩 + addView(middleView); +// addView(middleMask);//note mask - mScroller = new Scroller(context, new DecelerateInterpolator()); + mScrollerMoreSlowly = new Scroller(context, new DecelerateInterpolator()); + mScrollerSlowDownAfter = new Scroller(context, new AccelerateDecelerateInterpolator()); final ViewConfiguration configuration = ViewConfiguration.get(context); mTouchSlop = configuration.getScaledTouchSlop(); mMinimumVelocity = configuration.getScaledMinimumFlingVelocity(); mMaximumVelocity = configuration.getScaledMaximumFlingVelocity(); + + state = State.CLOSE_MENU; + } private void initLeftMenu() { @@ -127,11 +235,10 @@ private void initLeftMenu() { leftMenu = new FrameLayout(context); //设置阴影 - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { - leftMenu.setElevation(120); - } else { -// leftMenu.setBackgroundResource(R.drawable.menu_background); - } +// if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { +// leftMenu.setElevation(120); +// } +// leftMenu.setBackgroundColor(Color.TRANSPARENT); addView(leftMenu); } @@ -141,30 +248,38 @@ private void initRightMenu() { rightMenu = new FrameLayout(context); //设置阴影 - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { - rightMenu.setElevation(120); - } else { -// leftMenu.setBackgroundResource(R.drawable.menu_background); - } +// if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { +// rightMenu.setElevation(120); +// } +// rightMenu.setBackgroundColor(Color.TRANSPARENT); addView(rightMenu); } - @Override - public void scrollTo(int x, int y) { - super.scrollTo(x, y); - - - //设置遮罩的透明度(这里以 “当前视图的偏移量/菜单的宽度” 的值作为透明度) - int curX = Math.abs(getScrollX()); - float scale = curX / (curX > 0 ? (float) (rightMenu == null ? 0 : rightMenu.getMeasuredWidth()) : (float) (leftMenu == null ? 0 : leftMenu.getMeasuredWidth())); - middleMask.setAlpha(scale * 0.8f); + private void stopAllScroll() { + if (mScrollerMoreSlowly.computeScrollOffset()) { + mScrollerMoreSlowly.forceFinished(true); + } + if (mScrollerSlowDownAfter.computeScrollOffset()) { + mScrollerSlowDownAfter.forceFinished(true); + } } +// @Override +// public void scrollTo(int x, int y) { +// super.scrollTo(x, y); +// +// +// //设置遮罩的透明度(这里以 “当前视图的偏移量/菜单的宽度” 的值作为透明度) +//// int curX = Math.abs(getScrollX()); +//// float scale = curX / (curX > 0 ? (float) (rightMenu == null ? 0 : rightMenu.getMeasuredWidth()) : (float) (leftMenu == null ? 0 : leftMenu.getMeasuredWidth())); +//// middleMask.setAlpha(scale * 0.8f); +// } + @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(widthMeasureSpec, heightMeasureSpec); - middleMenu.measure(widthMeasureSpec, heightMeasureSpec); - middleMask.measure(widthMeasureSpec, heightMeasureSpec); + middleView.measure(widthMeasureSpec, heightMeasureSpec); +// middleMask.measure(widthMeasureSpec, heightMeasureSpec); int realWidth = MeasureSpec.getSize(widthMeasureSpec); //宽度是middleMenu宽度的八成;MeasureSpec.EXACTLY:精确 int tempWidthMeasure = MeasureSpec.makeMeasureSpec( @@ -178,22 +293,19 @@ protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { @Override protected void onLayout(boolean changed, int l, int t, int r, int b) { super.onLayout(changed, l, t, r, b); - middleMenu.layout(l, t, r, b); - middleMask.layout(l, t, r, b); + middleView.layout(l, t, r, b); +// middleMask.layout(l, t, r, b); if (leftMenu != null) leftMenu.layout(l - leftMenu.getMeasuredWidth(), t, - r - middleMenu.getMeasuredWidth(), b); + r - middleView.getMeasuredWidth(), b); if (rightMenu != null) rightMenu.layout( - l + middleMenu.getMeasuredWidth(), + l + middleView.getMeasuredWidth(), t, - l + middleMenu.getMeasuredWidth() + l + middleView.getMeasuredWidth() + rightMenu.getMeasuredWidth(), b); } - private boolean isTestCompete; - private boolean isLeftrightEvent; - @Override public boolean dispatchTouchEvent(MotionEvent ev) { obtainVelocityTracker(ev); @@ -202,6 +314,7 @@ public boolean dispatchTouchEvent(MotionEvent ev) { return true; } if (isLeftrightEvent) { + //getAction() & ACTION_MASK switch (ev.getActionMasked()) { case MotionEvent.ACTION_MOVE: int curScrollX = getScrollX();// 当前整体视图的位置(矢量。+表示视图发生了左移;-表示视图发生了右移。 @@ -233,6 +346,7 @@ public boolean dispatchTouchEvent(MotionEvent ev) { case MotionEvent.ACTION_UP: case MotionEvent.ACTION_CANCEL: + fingerTouch = false; touchUp(); isLeftrightEvent = false; isTestCompete = false; @@ -241,6 +355,7 @@ public boolean dispatchTouchEvent(MotionEvent ev) { } else { switch (ev.getActionMasked()) { case MotionEvent.ACTION_UP: + fingerTouch = false; touchUp(); isLeftrightEvent = false; isTestCompete = false; @@ -256,25 +371,40 @@ public boolean dispatchTouchEvent(MotionEvent ev) { @Override public void computeScroll() { - if (mScroller.computeScrollOffset()) {//调用此方法,想要获取最新的当前位置。返回true:滑动没有停止;返回false:滑动停止 - int tempX = mScroller.getCurrX(); + if (mScrollerMoreSlowly.computeScrollOffset()) {//调用此方法,想要获取最新的当前位置。返回true:滑动没有停止;返回false:滑动停止 + int tempX = mScrollerMoreSlowly.getCurrX(); + scrollTo(tempX, 0); + postInvalidate(); + + if (mScrollerMoreSlowly.isFinished()) {//如果滚动停止,检测位置 + checkLocationInStop(); + } else { + if (state != State.SCROLLING) + state = State.SCROLLING; + } + } else if (mScrollerSlowDownAfter.computeScrollOffset()) {//调用此方法,想要获取最新的当前位置。返回true:滑动没有停止;返回false:滑动停止 + int tempX = mScrollerSlowDownAfter.getCurrX(); scrollTo(tempX, 0); postInvalidate(); - if (mScroller.isFinished())//如果滚动停止,检测位置 + if (mScrollerSlowDownAfter.isFinished()) {//如果滚动停止,检测位置 checkLocationInStop(); + } else { + if (state != State.SCROLLING) + state = State.SCROLLING; + } + } else { + //Stop scrolling view,Check location + checkLocationInStop(); } } - private Point point = new Point(); - private static final int TEST_DIS = 20; - private void getEventType(MotionEvent ev) { switch (ev.getActionMasked()) { case MotionEvent.ACTION_DOWN: - if (mScroller.computeScrollOffset()) { - mScroller.forceFinished(true); - } + fingerTouch = true; + // stop all scroll + stopAllScroll(); point.x = (int) ev.getX(); point.y = (int) ev.getY(); super.dispatchTouchEvent(ev); @@ -297,6 +427,7 @@ private void getEventType(MotionEvent ev) { break; case MotionEvent.ACTION_UP: case MotionEvent.ACTION_CANCEL: + fingerTouch = false; super.dispatchTouchEvent(ev); touchUp(); isLeftrightEvent = false; @@ -327,33 +458,54 @@ && getChildCount() > 0) {//如果速度达到一定值,并且有子类,则 * 滑动/滚动停止的时候检查位置 */ private void checkLocationInStop() { + //如果手指触屏(当前是按下或滑动状态),不做处理 + if (fingerTouch) { + return; + } int curScrollX = getScrollX(); int menuWith = curScrollX > 0 ? (rightMenu == null ? 0 : rightMenu.getMeasuredWidth()) : (leftMenu == null ? 0 : leftMenu.getMeasuredWidth()); if (Math.abs(curScrollX) > menuWith >> 1) { if (curScrollX < 0) { - mScroller.startScroll(curScrollX, 0, - -(leftMenu == null ? 0 : leftMenu.getMeasuredWidth()) - curScrollX, 0, - 200); + if (curScrollX != -leftMenu.getMeasuredWidth()) { + mScrollerMoreSlowly.startScroll(curScrollX, 0, + -(leftMenu == null ? 0 : leftMenu.getMeasuredWidth()) - curScrollX, 0, + 200); + invalidate(); + } else { + //完全显示左菜单 + state = State.LEFT_MENU_OPENS; + } } else { - mScroller.startScroll(curScrollX, 0, - (rightMenu == null ? 0 : rightMenu.getMeasuredWidth()) - curScrollX, 0, - 200); + if (curScrollX != rightMenu.getMeasuredWidth()) { + mScrollerMoreSlowly.startScroll(curScrollX, 0, + (rightMenu == null ? 0 : rightMenu.getMeasuredWidth()) - curScrollX, 0, + 200); + invalidate(); + } else { + // 完全显示右菜单 + state = State.RIGHT_MENU_OPENS; + } } } else { - mScroller.startScroll(curScrollX, 0, -curScrollX, 0, 200); + if (curScrollX != 0) { + mScrollerMoreSlowly.startScroll(curScrollX, 0, -curScrollX, 0, 200); + invalidate(); + } else { + // 完全关闭菜单 + state = State.CLOSE_MENU; + } } - invalidate(); } public void fling(int velocityX, int velocityY) { if (getChildCount() > 0) { velocityX = -velocityX; - //velocityX > 0,说明试图向右走,显示左菜单 - mScroller.fling(getScrollX(), getScrollY(), velocityX, velocityY, -(leftMenu == null ? 0 : leftMenu.getMeasuredWidth()), (rightMenu == null ? 0 : rightMenu.getMeasuredWidth()), 0, + //velocityX > 0,说明视图向右走,显示左菜单 + mScrollerMoreSlowly.fling(getScrollX(), getScrollY(), velocityX, velocityY, -(leftMenu == null ? 0 : leftMenu.getMeasuredWidth()), (rightMenu == null ? 0 : rightMenu.getMeasuredWidth()), 0, 0); - final boolean movingDown = velocityY > 0; - awakenScrollBars(mScroller.getDuration()); +// final boolean movingDown = velocityY > 0; + awakenScrollBars(mScrollerMoreSlowly.getDuration()); invalidate(); } } @@ -372,4 +524,43 @@ private void releaseVelocityTracker() { mVelocityTracker = null; } } + + @Override + protected boolean drawChild(Canvas canvas, View child, long drawingTime) { + final boolean result = super.drawChild(canvas, child, drawingTime); + if (mShadowLeft != null) { + final int shadowWidth = mShadowLeft.getIntrinsicWidth(); + final int childRight = child.getRight(); + mShadowLeft.setBounds(childRight, child.getTop(), + childRight + shadowWidth, child.getBottom()); + mShadowLeft.draw(canvas); + } + if (mShadowRight != null) { + final int shadowWidth = mShadowRight.getIntrinsicWidth(); + final int childLeft = child.getLeft(); + mShadowRight.setBounds(childLeft - shadowWidth, child.getTop(), + childLeft, child.getBottom()); + mShadowRight.draw(canvas); + } + return result; + } + + public enum State { + /** + * View is scrolling + */ + SCROLLING, + /** + * Left menu opens + */ + LEFT_MENU_OPENS, + /** + * Right menu opens + */ + RIGHT_MENU_OPENS, + /** + * Stop scrolling view,Left and Right menu menu is closed + */ + CLOSE_MENU, + } } diff --git a/resources/shadowImg/shadow_left.9.png b/resources/shadowImg/shadow_left.9.png new file mode 100644 index 0000000..8cf8d4f Binary files /dev/null and b/resources/shadowImg/shadow_left.9.png differ diff --git a/resources/shadowImg/shadow_right.9.png b/resources/shadowImg/shadow_right.9.png new file mode 100644 index 0000000..9273e09 Binary files /dev/null and b/resources/shadowImg/shadow_right.9.png differ