Android UI开发第二十七篇——实现左右划出菜单

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

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

[java] view plain copy print ?
  1. public class SlidingView extends ViewGroup {  
  2.   
  3.     private FrameLayout mContainer;  
  4.     private Scroller mScroller;  
  5.     private VelocityTracker mVelocityTracker;  
  6.     private int mTouchSlop;  
  7.     private float mLastMotionX;  
  8.     private float mLastMotionY;  
  9.     private static final int SNAP_VELOCITY = 1000;  
  10.     private View mLeftView;  
  11.     private View mRightView;  
  12.   
  13.     public SlidingView(Context context) {  
  14.         super(context);  
  15.         init();  
  16.     }  
  17.   
  18.     public SlidingView(Context context, AttributeSet attrs) {  
  19.         super(context, attrs);  
  20.         init();  
  21.     }  
  22.   
  23.     public SlidingView(Context context, AttributeSet attrs, int defStyle) {  
  24.         super(context, attrs, defStyle);  
  25.         init();  
  26.     }  
  27.   
  28.     @Override  
  29.     protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {  
  30.         super.onMeasure(widthMeasureSpec, heightMeasureSpec);  
  31.         mContainer.measure(widthMeasureSpec, heightMeasureSpec);  
  32.     }  
  33.   
  34.     @Override  
  35.     protected void onLayout(boolean changed, int l, int t, int r, int b) {  
  36.         final int width = r - l;  
  37.         final int height = b - t;  
  38.         mContainer.layout(00, width, height);  
  39.     }  
  40.   
  41.     private void init() {  
  42.         mContainer = new FrameLayout(getContext());  
  43.         mContainer.setBackgroundColor(0xff000000);  
  44.         mScroller = new Scroller(getContext());  
  45.         mTouchSlop = ViewConfiguration.get(getContext()).getScaledTouchSlop();  
  46.         super.addView(mContainer);  
  47.     }  
  48.   
  49.     public void setView(View v) {  
  50.         if (mContainer.getChildCount() > 0) {  
  51.             mContainer.removeAllViews();  
  52.         }  
  53.         mContainer.addView(v);  
  54.     }  
  55.   
  56.     @Override  
  57.     public void scrollTo(int x, int y) {  
  58.         super.scrollTo(x, y);  
  59.         postInvalidate();  
  60.     }  
  61.   
  62.     @Override  
  63.     public void computeScroll() {  
  64.         if (!mScroller.isFinished()) {  
  65.             if (mScroller.computeScrollOffset()) {  
  66.                 int oldX = getScrollX();  
  67.                 int oldY = getScrollY();  
  68.                 int x = mScroller.getCurrX();  
  69.                 int y = mScroller.getCurrY();  
  70.                 if (oldX != x || oldY != y) {  
  71.                     scrollTo(x, y);  
  72.                 }  
  73.                 // Keep on drawing until the animation has finished.  
  74.                 invalidate();  
  75.             } else {  
  76.                 clearChildrenCache();  
  77.             }  
  78.         } else {  
  79.             clearChildrenCache();  
  80.         }  
  81.     }  
  82.   
  83.     private boolean mIsBeingDragged;  
  84.   
  85.       
  86.     /** 
  87.      * 实现了ontouch的分发拦截 
  88.      */  
  89.     @Override  
  90.     public boolean onInterceptTouchEvent(MotionEvent ev) {  
  91.   
  92.         final int action = ev.getAction();  
  93.         final float x = ev.getX();  
  94.         final float y = ev.getY();  
  95.   
  96.         switch (action) {  
  97.         case MotionEvent.ACTION_DOWN:  
  98.             mLastMotionX = x;  
  99.             mLastMotionY = y;  
  100.             mIsBeingDragged = false;  
  101.             break;  
  102.   
  103.         case MotionEvent.ACTION_MOVE:  
  104.             final float dx = x - mLastMotionX;  
  105.             final float xDiff = Math.abs(dx);  
  106.             final float yDiff = Math.abs(y - mLastMotionY);  
  107.             if (xDiff > mTouchSlop && xDiff > yDiff) {  
  108.                 mIsBeingDragged = true;  
  109.                 mLastMotionX = x;  
  110.             }  
  111.             Log.d("Sliding""SlidingView_Touch:"+x+"|"+y);  
  112.             Log.d("Sliding""SlidingView_Touch:"+xDiff+"|"+mTouchSlop+"|"+yDiff+"|"+mLastMotionY);  
  113.             Log.d("Sliding""SlidingView_Touch:"+mIsBeingDragged);  
  114.             break;  
  115.   
  116.         }  
  117.         return mIsBeingDragged;  
  118.     }  
  119.   
  120.     @Override  
  121.     public boolean onTouchEvent(MotionEvent ev) {  
  122.   
  123.         if (mVelocityTracker == null) {  
  124.             mVelocityTracker = VelocityTracker.obtain();  
  125.         }  
  126.         mVelocityTracker.addMovement(ev);  
  127.   
  128.         final int action = ev.getAction();  
  129.         final float x = ev.getX();  
  130.         final float y = ev.getY();  
  131.   
  132.         switch (action) {  
  133.         case MotionEvent.ACTION_DOWN:  
  134.             if (!mScroller.isFinished()) {  
  135.                 mScroller.abortAnimation();  
  136.             }  
  137.             mLastMotionX = x;  
  138.             mLastMotionY = y;  
  139.             if (getScrollX() == -getLeftMenuWidth()  
  140.                     && mLastMotionX < getLeftMenuWidth()) {  
  141.                 return false;  
  142.             }  
  143.   
  144.             if (getScrollX() == getRightMenuWidth()  
  145.                     && mLastMotionX > getLeftMenuWidth()) {  
  146.                 return false;  
  147.             }  
  148.   
  149.             break;  
  150.         case MotionEvent.ACTION_MOVE:  
  151.             if (mIsBeingDragged) {  
  152.                 enableChildrenCache();  
  153.                 final float deltaX = mLastMotionX - x;  
  154.                 mLastMotionX = x;  
  155.                 float oldScrollX = getScrollX();  
  156.                 float scrollX = oldScrollX + deltaX;  
  157.   
  158.                 if (deltaX < 0 && oldScrollX < 0) { // left view  
  159.                     final float leftBound = 0;  
  160.                     final float rightBound = -getLeftMenuWidth();  
  161.                     if (scrollX > leftBound) {  
  162.                         scrollX = leftBound;  
  163.                     } else if (scrollX < rightBound) {  
  164.                         scrollX = rightBound;  
  165.                     }  
  166.                 } else if (deltaX > 0 && oldScrollX > 0) { // right view  
  167.                     final float rightBound = getRightMenuWidth();  
  168.                     final float leftBound = 0;  
  169.                     if (scrollX < leftBound) {  
  170.                         scrollX = leftBound;  
  171.                     } else if (scrollX > rightBound) {  
  172.                         scrollX = rightBound;  
  173.                     }  
  174.                 }  
  175.   
  176.                 scrollTo((int) scrollX, getScrollY());  
  177.                 if (scrollX > 0) {  
  178.                     mLeftView.setVisibility(View.GONE);  
  179.                     mLeftView.clearFocus();  
  180.                     mRightView.setVisibility(View.VISIBLE);  
  181.                     mRightView.requestFocus();  
  182.                 } else {  
  183.                     mLeftView.setVisibility(View.VISIBLE);  
  184.                     mLeftView.requestFocus();  
  185.                     mRightView.setVisibility(View.GONE);  
  186.                     mRightView.clearFocus();  
  187.                 }  
  188.             }  
  189.             break;  
  190.         case MotionEvent.ACTION_CANCEL:  
  191.         case MotionEvent.ACTION_UP:  
  192.             if (mIsBeingDragged) {  
  193.                 final VelocityTracker velocityTracker = mVelocityTracker;  
  194.                 velocityTracker.computeCurrentVelocity(1000);  
  195.                 int velocityX = (int) velocityTracker.getXVelocity();  
  196.                 velocityX = 0;  
  197.                 int oldScrollX = getScrollX();  
  198.                 int dx = 0;  
  199.                 if (oldScrollX < 0) {  
  200.                     // 左边  
  201.                     if (oldScrollX < -getLeftMenuWidth() / 2  
  202.                             || velocityX > SNAP_VELOCITY) {  
  203.                         // 左侧页面划出  
  204.                         dx = -getLeftMenuWidth() - oldScrollX;  
  205.   
  206.                     } else if (oldScrollX >= -getLeftMenuWidth() / 2  
  207.                             || velocityX < -SNAP_VELOCITY) {  
  208.                         // 左侧页面关闭  
  209.                         dx = -oldScrollX;  
  210.                     }  
  211.                 } else {  
  212.                     // 右边  
  213.                     if (oldScrollX > getRightMenuWidth() / 2  
  214.                             || velocityX < -SNAP_VELOCITY) {  
  215.                         // 右侧页面划出  
  216.                         dx = getRightMenuWidth() - oldScrollX;  
  217.   
  218.                     } else if (oldScrollX <= getRightMenuWidth() / 2  
  219.                             || velocityX > SNAP_VELOCITY) {  
  220.                         // 右侧页面关闭  
  221.                         dx = -oldScrollX;  
  222.                     }  
  223.                 }  
  224.   
  225.                 smoothScrollTo(dx);  
  226.                 clearChildrenCache();  
  227.   
  228.             }  
  229.   
  230.             break;  
  231.   
  232.         }  
  233.         if (mVelocityTracker != null) {  
  234.             mVelocityTracker.recycle();  
  235.             mVelocityTracker = null;  
  236.         }  
  237.         return true;  
  238.     }  
  239.   
  240.     private int getLeftMenuWidth() {  
  241.         if (mLeftView == null) {  
  242.             return 0;  
  243.         }  
  244.         return mLeftView.getWidth();  
  245.     }  
  246.   
  247.     private int getRightMenuWidth() {  
  248.         if (mRightView == null) {  
  249.             return 0;  
  250.         }  
  251.         return mRightView.getWidth();  
  252.     }  
  253.   
  254.     @Override  
  255.     protected void onDraw(Canvas canvas) {  
  256.         super.onDraw(canvas);  
  257.     }  
  258.   
  259.     public View getRightView() {  
  260.         return mRightView;  
  261.     }  
  262.   
  263.     public void setRightView(View mRightView) {  
  264.         this.mRightView = mRightView;  
  265.     }  
  266.   
  267.     public View getMenuView() {  
  268.         return mLeftView;  
  269.     }  
  270.   
  271.     public void setLeftView(View mLeftView) {  
  272.         this.mLeftView = mLeftView;  
  273.     }  
  274.   
  275.     void toggle() {  
  276.         int menuWidth = mLeftView.getWidth();  
  277.         int oldScrollX = getScrollX();  
  278.         if (oldScrollX == 0) {  
  279.             smoothScrollTo(-menuWidth);  
  280.         } else if (oldScrollX == -menuWidth) {  
  281.             smoothScrollTo(menuWidth);  
  282.         }  
  283.     }  
  284.   
  285.     /** 
  286.      * 打开(关闭)左侧页面 
  287.      */  
  288.     public void showLeftView() {  
  289.         mLeftView.setVisibility(View.VISIBLE);  
  290.         mRightView.setVisibility(View.GONE);  
  291.         int menuWidth = mLeftView.getWidth();  
  292.         int oldScrollX = getScrollX();  
  293.         if (oldScrollX == 0) {  
  294.             smoothScrollTo(-menuWidth);  
  295.         } else if (oldScrollX == -menuWidth) {  
  296.             smoothScrollTo(menuWidth);  
  297.         }  
  298.     }  
  299.   
  300.     /** 
  301.      * 打开(关闭)右侧页面 
  302.      */  
  303.     public void showRightView() {  
  304.         mLeftView.setVisibility(View.GONE);  
  305.         mLeftView.clearFocus();  
  306.         mRightView.setVisibility(View.VISIBLE);  
  307.         mRightView.requestFocus();  
  308.         int menuWidth = mRightView.getWidth();  
  309.         int oldScrollX = getScrollX();  
  310.         if (oldScrollX == 0) {  
  311.             smoothScrollTo(menuWidth);  
  312.         } else if (oldScrollX == menuWidth) {  
  313.             smoothScrollTo(-menuWidth);  
  314.         }  
  315.     }  
  316.   
  317.     /** 
  318.      * 显示中间页面 
  319.      */  
  320.     public void showCenterView() {  
  321.         int menuWidth = mRightView.getWidth();  
  322.         int oldScrollX = getScrollX();  
  323.         if (oldScrollX == menuWidth) {  
  324.             showRightView();  
  325.         } else if (oldScrollX == -menuWidth) {  
  326.             showLeftView();  
  327.         }  
  328.     }  
  329.   
  330.     void smoothScrollTo(int dx) {  
  331.         int duration = 500;  
  332.         int oldScrollX = getScrollX();  
  333.         mScroller.startScroll(oldScrollX, getScrollY(), dx, getScrollY(),  
  334.                 duration);  
  335.         invalidate();  
  336.     }  
  337.   
  338.     void enableChildrenCache() {  
  339.         final int count = getChildCount();  
  340.         for (int i = 0; i < count; i++) {  
  341.             final View layout = (View) getChildAt(i);  
  342.             layout.setDrawingCacheEnabled(true);  
  343.         }  
  344.     }  
  345.   
  346.     void clearChildrenCache() {  
  347.         final int count = getChildCount();  
  348.         for (int i = 0; i < count; i++) {  
  349.             final View layout = (View) getChildAt(i);  
  350.             layout.setDrawingCacheEnabled(false);  
  351.         }  
  352.     }  
  353.   
  354. }  

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

[java] view plain copy print ?
  1. public class SlidingMenu extends RelativeLayout {  
  2.   
  3.     private SlidingView mSlidingView;  
  4.     private View mLeftView;  
  5.     private View mRightView;  
  6.     // menu width  
  7.     private int alignScreenWidth;  
  8.   
  9.     public SlidingMenu(Context context) {  
  10.         super(context);  
  11.     }  
  12.   
  13.     public SlidingMenu(Context context, AttributeSet attrs) {  
  14.         super(context, attrs);  
  15.     }  
  16.   
  17.     public SlidingMenu(Context context, AttributeSet attrs, int defStyle) {  
  18.         super(context, attrs, defStyle);  
  19.     }  
  20.   
  21.     public void setAlignScreenWidth(int alignScreenWidth) {  
  22.         this.alignScreenWidth = alignScreenWidth;  
  23.     }  
  24.   
  25.     public void setLeftView(View view) {  
  26.         LayoutParams behindParams = new LayoutParams(alignScreenWidth,  
  27.                 LayoutParams.MATCH_PARENT);  
  28.         addView(view, behindParams);  
  29.         mLeftView = view;  
  30.     }  
  31.   
  32.     public void setRightView(View view) {  
  33.         LayoutParams behindParams = new LayoutParams(alignScreenWidth,  
  34.                 LayoutParams.MATCH_PARENT);  
  35.         behindParams.addRule(RelativeLayout.ALIGN_PARENT_RIGHT);  
  36.         addView(view, behindParams);  
  37.         mRightView = view;  
  38.     }  
  39.   
  40.     public void setCenterView(View view) {  
  41.         LayoutParams aboveParams = new LayoutParams(LayoutParams.MATCH_PARENT,  
  42.                 LayoutParams.MATCH_PARENT);  
  43.         mSlidingView = new SlidingView(getContext());  
  44.         addView(mSlidingView, aboveParams);  
  45.         mSlidingView.setView(view);  
  46.         mSlidingView.invalidate();  
  47.         mSlidingView.setLeftView(mLeftView);  
  48.         mSlidingView.setRightView(mRightView);  
  49.     }  
  50.   
  51.     public void showLeftView() {  
  52.         mSlidingView.showLeftView();  
  53.     }  
  54.   
  55.     public void showRightView() {  
  56.         mSlidingView.showRightView();  
  57.     }  
  58.   
  59.     public void showCenterView() {  
  60.         mSlidingView.showCenterView();  
  61.     }  
  62.   
  63. }  

SlidingMenu的使用代码

[java] view plain copy print ?
  1. public class SlidingActivity extends Activity implements OnClickListener{  
  2.     SlidingMenu mSlidingMenu;  
  3.   
  4.     @Override  
  5.     protected void onCreate(Bundle arg0) {  
  6.         super.onCreate(arg0);  
  7.         setContentView(R.layout.main);  
  8.   
  9.   
  10.         DisplayMetrics dm = new DisplayMetrics();  
  11.         getWindowManager().getDefaultDisplay().getMetrics(dm);  
  12.   
  13.         mSlidingMenu = (SlidingMenu) findViewById(R.id.slidingMenu);  
  14.         mSlidingMenu.setAlignScreenWidth((dm.widthPixels / 5) * 2);  
  15.           
  16.         View leftView=getLayoutInflater().inflate(R.layout.left_menu, null);  
  17.         View rightView=getLayoutInflater().inflate(R.layout.right_menu, null);  
  18.         View centerView=getLayoutInflater().inflate(R.layout.center, null);  
  19.           
  20.         mSlidingMenu.setLeftView(leftView);  
  21.         mSlidingMenu.setRightView(rightView);  
  22.         mSlidingMenu.setCenterView(centerView);  
  23.           
  24.         Button showLeftMenu=(Button)centerView.findViewById(R.id.center_left_btn);  
  25.         showLeftMenu.setOnClickListener(this);  
  26.         Button showRightMenu=(Button)centerView.findViewById(R.id.center_right_btn);  
  27.         showRightMenu.setOnClickListener(this);  
  28.     }  
  29.   
  30.     @Override  
  31.     public void onClick(View v) {  
  32.         // TODO Auto-generated method stub  
  33.         switch (v.getId()) {  
  34.         case R.id.center_left_btn:  
  35.             mSlidingMenu.showLeftView();  
  36.             break;  
  37.         case R.id.center_right_btn:  
  38.             mSlidingMenu.showRightView();  
  39.             break;  
  40.         default:  
  41.             break;  
  42.         }  
  43.     }  
  44.       
  45. }  
Android UI开发第二十七篇——实现左右划出菜单_第1张图片                                 Android UI开发第二十七篇——实现左右划出菜单_第2张图片


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

你可能感兴趣的:(android)