Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> Android -- SlidingMenu

Android -- SlidingMenu

編輯:關於Android編程

實現原理                                                                                 在一個Activity的布局中需要有兩部分,一個是菜單(menu)的布局,一個是內容(content)的布局。兩個布局橫向排列,菜單布局在左,內容布局在右。初始化的時候將菜單布局向左偏移,以至於能夠完全隱藏,這樣內容布局就會完全顯示在Activity中。然後通過監聽手指滑動事件,來改變菜單布局的左偏移距離,從而控制菜單布局的顯示和隱藏。   布局                                                                                      復制代碼 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"     xmlns:tools="http://schemas.android.com/tools"     android:layout_width="match_parent"     android:layout_height="match_parent"     android:orientation="horizontal"     tools:context=".MyActivity">       <LinearLayout         android:id="@+id/menu"         android:layout_width="fill_parent"         android:layout_height="fill_parent"         android:background="#ff00ff00"         android:orientation="vertical"></LinearLayout>       <LinearLayout         android:id="@+id/content"         android:layout_width="fill_parent"         android:layout_height="fill_parent"         android:background="#ffff0000"         android:orientation="vertical"></LinearLayout>   </LinearLayout> 復制代碼 這個布局文件的最外層布局是一個LinearLayout,排列方向是水平方向排列。這個LinearLayout下面嵌套了兩個子LinearLayout,分別就是菜單的布局和內容的布局。這裡為了要讓布局盡量簡單,菜單布局和內容布局裡面沒有加入任何控件。   Code                                                                                      復制代碼 public class MyActivity extends Activity implements View.OnTouchListener {     /**      * 手指每單位時間滑動200個像素      */     private static final int SPEED = 200;     /**      * 屏幕寬度      */     private int mScreenWidth;     /**      * menu的layout      */     private LinearLayout mMenuLayout;     /**      * content的layout      */     private LinearLayout mContentLayout;     /**      * menu的layout的Paramters      */     private LinearLayout.LayoutParams mMenuParams;     /**      * menu完全顯示的時候給content的寬度值      */     private int mMenuPadding = 80;     /**      * menu最多滑到左邊緣,值由menu布局的寬度決定,marginLeft到達此值之後,不能在減少      */     private int mLeftEdge;     /**      * 測速度的對象      */     private VelocityTracker mVelocityTracker;     /**      * 手指按下的X坐標      */     private float mXDown;     /**      * 手指移動時候的X坐標      */     private float mXMove;     /**      * 手指抬起的X坐標      */     private float mXUp;     /**      * menu是否再顯示      */     private boolean mIsMenuVisible = false;         @Override     protected void onCreate(Bundle savedInstanceState) {         super.onCreate(savedInstanceState);         setContentView(R.layout.activity_my);         initViewsAndValues();         mContentLayout.setOnTouchListener(this);     }       /**      * 初始化menu和content並且設置他們的位置      */     private void initViewsAndValues() {         //得到windowManager         WindowManager window = (WindowManager) getSystemService(Context.WINDOW_SERVICE);         //得到屏幕寬度         mScreenWidth = window.getDefaultDisplay().getWidth();         //找到控件         mMenuLayout = (LinearLayout) findViewById(R.id.menu);         mContentLayout = (LinearLayout) findViewById(R.id.content);         //得到menu的paramter         mMenuParams = (LinearLayout.LayoutParams) mMenuLayout.getLayoutParams();         //將menu的寬度設置為屏幕寬度減去mMenuPading         mMenuParams.width = mScreenWidth - mMenuPadding;         //左邊緣的值復制為menu寬度的負數,這樣的話就可以將menu隱藏         mLeftEdge = -mMenuParams.width;         //將margin設置為mLeftEdge         mMenuParams.leftMargin = mLeftEdge;         //將content顯示再屏幕上         mContentLayout.getLayoutParams().width = mScreenWidth;     }         @Override     public boolean onTouch(View view, MotionEvent event) {         createVelocityTracker(event);         switch (event.getAction()) {             case MotionEvent.ACTION_DOWN:                 //記錄X坐標                 mXDown = event.getRawX();                 break;             case MotionEvent.ACTION_MOVE:                 mXMove = event.getRawX();                 int distanceX = (int) (mXMove - mXDown);                 if (mIsMenuVisible) {                     mMenuParams.leftMargin = distanceX;                 } else {                     mMenuParams.leftMargin = mLeftEdge + distanceX;                 }                 if (mMenuParams.leftMargin < mLeftEdge) {                     //因為leftEdge是負數,就是menu已經隱藏完畢了,不能再往左隱藏了                     mMenuParams.leftMargin = mLeftEdge;                 } else if (mMenuParams.leftMargin > 0) {                     //menu顯示完全了,不能再往右移動了                     mMenuParams.leftMargin = 0;                 }                 mMenuLayout.setLayoutParams(mMenuParams);                 break;             case MotionEvent.ACTION_UP:                 mXUp = event.getRawX();                 if (wantToShowMenu()) {                     if (shouldScrollToMenu()) {                         scrollToMenu();                     } else {                         //條件不滿足,把menu繼續隱藏掉                         scrollToContent();                     }                 } else if (wantToShowContent()) {                     if (shouldScrollToContent()) {                         scrollToContent();                     } else {                         scrollToMenu();                     }                 }                 break;         }         recycleVelocityTracker();         return true;     }       /**      * 創建VelocityTracker對象,針對於content的界面的滑動事件      *      * @param event      */     private void createVelocityTracker(MotionEvent event) {         if (null == mVelocityTracker) {             mVelocityTracker = VelocityTracker.obtain();         }         mVelocityTracker.addMovement(event);     }       /**      * 判斷手勢是不是想要顯示Content && menu處於顯示狀態      *      * @return      */     private boolean wantToShowContent() {         return mXUp - mXDown < 0 && mIsMenuVisible;     }       /**      * 是不是要顯示menu && menu處於隱藏狀態      *      * @return      */     private boolean wantToShowMenu() {         return mXUp - mXDown > 0 && !mIsMenuVisible;     }       /**      * 是否應該滑動出menu      *      * @return      */     private boolean shouldScrollToMenu() {         return mXUp - mXDown > mScreenWidth / 2 || getScrollVelocity() > SPEED;     }       /**      * 是否應該讓content全部顯示出來      *      * @return      */     private boolean shouldScrollToContent() {         return mXDown - mXUp < mScreenWidth / 2 || getScrollVelocity() > SPEED;     }       /**      * 顯示出menu      */     private void scrollToMenu() {         new ScrollAsyncTask().execute(30);     }       /**      * 隱藏掉menu      */     private void scrollToContent() {         new ScrollAsyncTask().execute(-30);     }         /**      * 得到手指滑動速度,每秒移動多少單位像素      *      * @return      */     private int getScrollVelocity() {         mVelocityTracker.computeCurrentVelocity(1000);         int velocity = (int) mVelocityTracker.getXVelocity();         return Math.abs(velocity);     }       /**      * 回收VelocityTracker對象。      */     private void recycleVelocityTracker() {         mVelocityTracker.recycle();         mVelocityTracker = null;     }       class ScrollAsyncTask extends AsyncTask<Integer, Integer, Integer> {           @Override         protected Integer doInBackground(Integer[] speed) {             //得到當前margin             int leftMargin = mMenuParams.leftMargin;             //不斷更改margin的值             while (true) {                 leftMargin = leftMargin + speed[0];                 if (leftMargin > 0) {                     leftMargin = 0;                     break;                 }                 if (leftMargin < mLeftEdge) {                     leftMargin = mLeftEdge;                     break;                 }                 publishProgress(leftMargin);                 sleep();             }             if (speed[0] > 0) {                 mIsMenuVisible = true;             } else {                 mIsMenuVisible = false;             }             return leftMargin;         }           @Override         protected void onPostExecute(Integer integer) {             mMenuParams.leftMargin = integer;             mMenuLayout.setLayoutParams(mMenuParams);         }           @Override         protected void onProgressUpdate(Integer... values) {             mMenuParams.leftMargin = values[0];             mMenuLayout.setLayoutParams(mMenuParams);         }     }       /**      * sleep線程睡眠一下      */     private void sleep() {         try {             Thread.sleep(20);         } catch (InterruptedException e) {             e.printStackTrace();         }     } } 復制代碼 首先初始化的時候調用initViewsAndValues方法,在這裡面將內容布局的寬度設定為屏幕的寬度,菜單布局的寬度設定為屏幕的寬度減去menuPadding值,這樣可以保證在菜單布局展示的時候,仍有一部分內容布局可以看到。如果不在初始化的時候重定義兩個布局寬度,就會按照layout文件裡面聲明的一樣,兩個布局都是fill_parent,這樣就無法實現滑動菜單的效果了。然後將菜單布局的左偏移量設置為負的菜單布局的寬度,這樣菜單布局就會被完全隱藏,只有內容布局會顯示在界面上。   之後給內容布局注冊監聽事件,這樣當手指在內容布局上滑動的時候就會觸發onTouch事件。在onTouch事件裡面,根據手指滑動的距離會改變菜單布局的左偏移量,從而控制菜單布局的顯示和隱藏。當手指離開屏幕的時候,會判斷應該滑動到菜單布局還是內容布局,判斷依據是根據手指滑動的距離或者滑動的速度,細節可以看代碼中的注釋。
  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved