年前就想写左右滑动菜单,苦于没有时间,一直拖到现在,这篇代码实现参考了网上流行的SlidingMenu,使用的FrameLayout布局,不是扩展的HorizontalScrollView。

程序中自定义了菜单view:SlidingView,继承自ViewGroup,使用FrameLayout布局。重写了onInterceptTouchEvent(MotionEvent ev)方法实现ontouch的分发拦截,重写了onTouchEvent(MotionEvent ev)方法,实现左右滑动。

public class SlidingView extends ViewGroup {  private FrameLayout mContainer; private Scroller mScroller; private VelocityTracker mVelocityTracker; private int mTouchSlop; private float mLastMotionX; private float mLastMotionY; private static final int SNAP_VELOCITY = 1000; private View mLeftView; private View mRightView;  public SlidingView(Context context) { super(context); init(); }  public SlidingView(Context context, AttributeSet attrs) { super(context, attrs); init(); }  public SlidingView(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); init(); }  @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(widthMeasureSpec, heightMeasureSpec); mContainer.measure(widthMeasureSpec, heightMeasureSpec); }  @Override protected void onLayout(boolean changed, int l, int t, int r, int b) { final int width = r - l; final int height = b - t; mContainer.layout(0, 0, width, height); }  private void init() { mContainer = new FrameLayout(getContext()); mContainer.setBackgroundColor(0xff000000); mScroller = new Scroller(getContext()); mTouchSlop = ViewConfiguration.get(getContext()).getScaledTouchSlop(); super.addView(mContainer); }  public void setView(View v) { if (mContainer.getChildCount() > 0) { mContainer.removeAllViews(); } mContainer.addView(v); }  @Override public void scrollTo(int x, int y) { super.scrollTo(x, y); postInvalidate(); }  @Override public void computeScroll() { if (!mScroller.isFinished()) { if (mScroller.computeScrollOffset()) { int oldX = getScrollX(); int oldY = getScrollY(); int x = mScroller.getCurrX(); int y = mScroller.getCurrY(); if (oldX != x || oldY != y) { scrollTo(x, y); } // Keep on drawing until the animation has finished. invalidate(); } else { clearChildrenCache(); } } else { clearChildrenCache(); } }  private boolean mIsBeingDragged;       /**      * 实现了ontouch的分发拦截      */ @Override public boolean onInterceptTouchEvent(MotionEvent ev) {  final int action = ev.getAction(); final float x = ev.getX(); final float y = ev.getY();  switch (action) { case MotionEvent.ACTION_DOWN: mLastMotionX = x; mLastMotionY = y; mIsBeingDragged = false; break;  case MotionEvent.ACTION_MOVE: final float dx = x - mLastMotionX; final float xDiff = Math.abs(dx); final float yDiff = Math.abs(y - mLastMotionY); if (xDiff > mTouchSlop && xDiff > yDiff) { mIsBeingDragged = true; mLastMotionX = x; } Log.d("Sliding", "SlidingView_Touch:"+x+"|"+y); Log.d("Sliding", "SlidingView_Touch:"+xDiff+"|"+mTouchSlop+"|"+yDiff+"|"+mLastMotionY); Log.d("Sliding", "SlidingView_Touch:"+mIsBeingDragged); break;  } return mIsBeingDragged; }  @Override public boolean onTouchEvent(MotionEvent ev) {  if (mVelocityTracker == null) { mVelocityTracker = VelocityTracker.obtain(); } mVelocityTracker.addMovement(ev);  final int action = ev.getAction(); final float x = ev.getX(); final float y = ev.getY();  switch (action) { case MotionEvent.ACTION_DOWN: if (!mScroller.isFinished()) { mScroller.abortAnimation(); } mLastMotionX = x; mLastMotionY = y; if (getScrollX() == -getLeftMenuWidth() && mLastMotionX < getLeftMenuWidth()) { return false; }  if (getScrollX() == getRightMenuWidth() && mLastMotionX > getLeftMenuWidth()) { return false; }  break; case MotionEvent.ACTION_MOVE: if (mIsBeingDragged) { enableChildrenCache(); final float deltaX = mLastMotionX - x; mLastMotionX = x; float oldScrollX = getScrollX(); float scrollX = oldScrollX + deltaX;  if (deltaX < 0 && oldScrollX < 0) { // left view final float leftBound = 0; final float rightBound = -getLeftMenuWidth(); if (scrollX > leftBound) { scrollX = leftBound; } else if (scrollX < rightBound) { scrollX = rightBound; } } else if (deltaX > 0 && oldScrollX > 0) { // right view final float rightBound = getRightMenuWidth(); final float leftBound = 0; if (scrollX < leftBound) { scrollX = leftBound; } else if (scrollX > rightBound) { scrollX = rightBound; } }  scrollTo((int) scrollX, getScrollY()); if (scrollX > 0) { mLeftView.setVisibility(View.GONE); mLeftView.clearFocus(); mRightView.setVisibility(View.VISIBLE); mRightView.requestFocus(); } else { mLeftView.setVisibility(View.VISIBLE); mLeftView.requestFocus(); mRightView.setVisibility(View.GONE); mRightView.clearFocus(); } } break; case MotionEvent.ACTION_CANCEL: case MotionEvent.ACTION_UP: if (mIsBeingDragged) { final VelocityTracker velocityTracker = mVelocityTracker; velocityTracker.computeCurrentVelocity(1000); int velocityX = (int) velocityTracker.getXVelocity(); velocityX = 0; int oldScrollX = getScrollX(); int dx = 0; if (oldScrollX < 0) { // 左边 if (oldScrollX < -getLeftMenuWidth() / 2 || velocityX > SNAP_VELOCITY) { // 左侧页面划出 dx = -getLeftMenuWidth() - oldScrollX;  } else if (oldScrollX >= -getLeftMenuWidth() / 2 || velocityX < -SNAP_VELOCITY) { // 左侧页面关闭 dx = -oldScrollX; } } else { // 右边 if (oldScrollX > getRightMenuWidth() / 2 || velocityX < -SNAP_VELOCITY) { // 右侧页面划出 dx = getRightMenuWidth() - oldScrollX;  } else if (oldScrollX <= getRightMenuWidth() / 2 || velocityX > SNAP_VELOCITY) { // 右侧页面关闭 dx = -oldScrollX; } }  smoothScrollTo(dx); clearChildrenCache();  }  break;  } if (mVelocityTracker != null) { mVelocityTracker.recycle(); mVelocityTracker = null; } return true; }  private int getLeftMenuWidth() { if (mLeftView == null) { return 0; } return mLeftView.getWidth(); }  private int getRightMenuWidth() { if (mRightView == null) { return 0; } return mRightView.getWidth(); }  @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); }  public View getRightView() { return mRightView; }  public void setRightView(View mRightView) { this.mRightView = mRightView; }  public View getMenuView() { return mLeftView; }  public void setLeftView(View mLeftView) { this.mLeftView = mLeftView; }  void toggle() { int menuWidth = mLeftView.getWidth(); int oldScrollX = getScrollX(); if (oldScrollX == 0) { smoothScrollTo(-menuWidth); } else if (oldScrollX == -menuWidth) { smoothScrollTo(menuWidth); } }  /**  * 打开(关闭)左侧页面  */ public void showLeftView() { mLeftView.setVisibility(View.VISIBLE); mRightView.setVisibility(View.GONE); int menuWidth = mLeftView.getWidth(); int oldScrollX = getScrollX(); if (oldScrollX == 0) { smoothScrollTo(-menuWidth); } else if (oldScrollX == -menuWidth) { smoothScrollTo(menuWidth); } }  /**  * 打开(关闭)右侧页面  */ public void showRightView() { mLeftView.setVisibility(View.GONE); mLeftView.clearFocus(); mRightView.setVisibility(View.VISIBLE); mRightView.requestFocus(); int menuWidth = mRightView.getWidth(); int oldScrollX = getScrollX(); if (oldScrollX == 0) { smoothScrollTo(menuWidth); } else if (oldScrollX == menuWidth) { smoothScrollTo(-menuWidth); } }  /**  * 显示中间页面  */ public void showCenterView() { int menuWidth = mRightView.getWidth(); int oldScrollX = getScrollX(); if (oldScrollX == menuWidth) { showRightView(); } else if (oldScrollX == -menuWidth) { showLeftView(); } }  void smoothScrollTo(int dx) { int duration = 500; int oldScrollX = getScrollX(); mScroller.startScroll(oldScrollX, getScrollY(), dx, getScrollY(), duration); invalidate(); }  void enableChildrenCache() { final int count = getChildCount(); for (int i = 0; i < count; i++) { final View layout = (View) getChildAt(i); layout.setDrawingCacheEnabled(true); } }  void clearChildrenCache() { final int count = getChildCount(); for (int i = 0; i < count; i++) { final View layout = (View) getChildAt(i); layout.setDrawingCacheEnabled(false); } }  }

SlidingMenu对SlidingView做了进一步封装处理:

public class SlidingMenu extends RelativeLayout {  private SlidingView mSlidingView; private View mLeftView; private View mRightView; // menu width private int alignScreenWidth;  public SlidingMenu(Context context) { super(context); }  public SlidingMenu(Context context, AttributeSet attrs) { super(context, attrs); }  public SlidingMenu(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); }  public void setAlignScreenWidth(int alignScreenWidth) { this.alignScreenWidth = alignScreenWidth; }  public void setLeftView(View view) { LayoutParams behindParams = new LayoutParams(alignScreenWidth, LayoutParams.MATCH_PARENT); addView(view, behindParams); mLeftView = view; }  public void setRightView(View view) { LayoutParams behindParams = new LayoutParams(alignScreenWidth, LayoutParams.MATCH_PARENT); behindParams.addRule(RelativeLayout.ALIGN_PARENT_RIGHT); addView(view, behindParams); mRightView = view; }  public void setCenterView(View view) { LayoutParams aboveParams = new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT); mSlidingView = new SlidingView(getContext()); addView(mSlidingView, aboveParams); mSlidingView.setView(view); mSlidingView.invalidate(); mSlidingView.setLeftView(mLeftView); mSlidingView.setRightView(mRightView); }  public void showLeftView() { mSlidingView.showLeftView(); }  public void showRightView() { mSlidingView.showRightView(); }  public void showCenterView() { mSlidingView.showCenterView(); }  }

SlidingMenu的使用代码

public class SlidingActivity extends Activity implements OnClickListener{ SlidingMenu mSlidingMenu;  @Override protected void onCreate(Bundle arg0) { super.onCreate(arg0); setContentView(R.layout.main);   DisplayMetrics dm = new DisplayMetrics(); getWindowManager().getDefaultDisplay().getMetrics(dm);  mSlidingMenu = (SlidingMenu) findViewById(R.id.slidingMenu); mSlidingMenu.setAlignScreenWidth((dm.widthPixels / 5) * 2);  View leftView=getLayoutInflater().inflate(R.layout.left_menu, null); View rightView=getLayoutInflater().inflate(R.layout.right_menu, null); View centerView=getLayoutInflater().inflate(R.layout.center, null);  mSlidingMenu.setLeftView(leftView); mSlidingMenu.setRightView(rightView); mSlidingMenu.setCenterView(centerView);          Button showLeftMenu=(Button)centerView.findViewById(R.id.center_left_btn); showLeftMenu.setOnClickListener(this); Button showRightMenu=(Button)centerView.findViewById(R.id.center_right_btn); showRightMenu.setOnClickListener(this); }  @Override public void onClick(View v) { // TODO Auto-generated method stub switch (v.getId()) { case R.id.center_left_btn: mSlidingMenu.showLeftView(); break;         case R.id.center_right_btn:         mSlidingMenu.showRightView(); break; default: break; } }  }


代码:http://download.csdn.net/detail/xyz_lmn/5109965

/**
* @author 张兴业
* android开发进阶群: 241395671
*/

更多相关文章

  1. android轻量框架四__滑动手势
  2. 安卓数据库连接解决办法 ,避免 sqlite3 database is locked
  3. Android中进入页面默认定位到ListView的第一条数据解决方法
  4. Android:SwipeRefreshLayout和ViewPager滑动冲突的原因和正确的解
  5. android自定义字体和程序启动时的加载页面
  6. Android(安卓)嵌套XRecyclerView滑动迟缓以及上拉不好用解决办法
  7. Android(安卓)menu关闭应用程序
  8. ListView从底部开始绘制和新item自动移动到底部
  9. webview使用中遇到的坑

随机推荐

  1. Android(安卓)网络调试
  2. Android(安卓)9 (P)之init进程启动源码分
  3. Android公共库(缓存,下拉ListView,下载管
  4. android报表例子
  5. android 热更新(无框架)
  6. android中的selector背景选择器的用法
  7. Android应用开发——TextView控件属性列
  8. Android系统分析之Activity的启动流程
  9. android通过adb设置以太网共享
  10. Android调用shell脚本并获得输出