Android側滑菜單完整詳細樣本(基礎版)

來源:互聯網
上載者:User

Android側滑菜單完整詳細樣本(基礎版)
MainActivity如下:

package cc.cd;import android.os.AsyncTask;import android.os.Bundle;import android.util.Log;import android.view.MotionEvent;import android.view.VelocityTracker;import android.view.View;import android.view.View.OnTouchListener;import android.view.WindowManager;import android.widget.LinearLayout;import android.app.Activity;import android.content.Context;/** * Demo描述: * 側滑菜單SlidingMenu的簡單樣本 * 即在一個Activity中加入SlidingMenu *  * 樣本說明: * 樣本中一共兩個介面menu和content.當進入應用時顯示content介面. * 若手指滑向螢幕右側則顯示menu和隱藏content.反之,同理. * menu的顯示和隱藏主要是修改menu的LayoutParams中的leftMargin從而達到效果. *  * 步驟整理: * 1 初始化時,通過設定menu的LayoutParams中的leftMargin使其完全隱藏. * 2 為content設定Touch監聽. * 3 在move的過程中不斷修改menu的LayoutParams中的leftMargin使其按照 *   手勢的滑動而顯示或者隱藏 * 4 在up時通過非同步任務AsyncTask修改menu的LayoutParams中的leftMargin *   從而實現menu的完全顯示或者完全隱藏. *    * 以上套路還是挺常見的. *  * 參考資料: * 1 http://blog.csdn.net/guolin_blog/article/details/8714621 * 2 http://blog.csdn.net/hudashi/article/details/7352157 *   Thank you very much *  * 備忘說明: * 1 樣本中使用的圖片亦來自參考資料1 * 2 為簡化邏輯,樣本中的兩個介面均為而不是實際View介面 */public class MainActivity extends Activity {private int screenWidth;    private View contentView;    private View menuView;    private float xDown;    private float xMove;    private float xUp;    //當完全顯示menu時content的寬度最小值    private int contentViewMinWidth = 80;    //menu是否可見的標誌位,該值在滑動過程中無效.    //只有在滑動結束後,完全顯示或隱藏menu時才會更改此值    private boolean isMenuVisible=false;    private int menuParamsMaxLeftMargin=0;    private int menuParamsMinLeftMargin=0;    //速度追蹤    private VelocityTracker mVelocityTracker;    //閾值    public static final int VELOCITY_THRESHOLD=200;    //TAG    private final static String TAG="MainActivity";    //menu的布局LayoutParams    private LinearLayout.LayoutParams menuLayoutParams;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.main);init();}private void init(){//擷取螢幕寬度WindowManager windowManager=(WindowManager) getSystemService(Context.WINDOW_SERVICE);screenWidth=windowManager.getDefaultDisplay().getWidth();//初始化contentViewcontentView=findViewById(R.id.contentLinearLayout);//將contentView的寬度設定為螢幕的寬度contentView.getLayoutParams().width=screenWidth;//設定Touch監聽contentView.setOnTouchListener(new TouchListenerImpl());//初始化menuViewmenuView=findViewById(R.id.menuLinearLayout);menuLayoutParams=(LinearLayout.LayoutParams) menuView.getLayoutParams();//設定menuView的寬度.//設定其寬度為螢幕寬度減去contentView的最小寬度menuLayoutParams.width=screenWidth-contentViewMinWidth;//初始化時完全隱藏了menuView.menuParamsMinLeftMargin=-menuLayoutParams.width;menuLayoutParams.leftMargin=menuParamsMinLeftMargin;}/** * 關於ACTION_MOVE中distanceX的細節說明. * 在一次滑動過程中(從手指按下到手指抬起)distanceX的值是持續變大或者變小的. * 因為int distanceX=(int) (xMove-xDown); * 這個xDown是按下時的座標值,在Moving的過程中計算distanceX時一直採用 * 的是xDown減去每時刻的xMove.即在滑動過程中xDown一直不變而xMove是不斷 * 在變化的. * 代碼說明: * if (isMenuVisible) { *     menuLayoutParams.leftMargin=distanceX; * } else { *    menuLayoutParams.leftMargin=menuParamsMinLeftMargin+distanceX; * } * 在最開始時,menu是隱藏的.手指按下,滑向螢幕的右邊.調用: * menuLayoutParams.leftMargin=menuParamsMinLeftMargin+distanceX; * 所以這個menuLayoutParams.leftMargin是不斷在變大的直到0為止(注意越界判斷),此時 * menuView完全顯示.這時手指再按下,滑向螢幕的左邊.調用: * menuLayoutParams.leftMargin=distanceX; * distanceX這個負數一直在減小,它就是menuLayoutParams.leftMargin的值直至 * menuView完全隱藏為止,此時它的值為menuParamsMinLeftMargin(注意越界判斷). *  * 該問題不難,但在此備忘一下以防以後反應不過來. */private class TouchListenerImpl implements OnTouchListener{@Overridepublic boolean onTouch(View v, MotionEvent event) {//開始速度追蹤startVelocityTracker(event);switch (event.getAction()) {case MotionEvent.ACTION_DOWN:xDown=event.getRawX();break;case MotionEvent.ACTION_MOVE:xMove=event.getRawX();int distanceX=(int) (xMove-xDown);Log.i(TAG, "xDown="+xDown+",xMove="+xMove+",distanceX="+distanceX);if (isMenuVisible) {menuLayoutParams.leftMargin=distanceX;} else {menuLayoutParams.leftMargin=menuParamsMinLeftMargin+distanceX;}//處理越界的情況if(menuLayoutParams.leftMarginmenuParamsMaxLeftMargin){menuLayoutParams.leftMargin=menuParamsMaxLeftMargin;}//設定menuView的LayoutParamsmenuView.setLayoutParams(menuLayoutParams);break;case MotionEvent.ACTION_UP:xUp=event.getRawX();//判斷手勢意圖想顯示menuif (wantToShowMenu()) {//判斷是否顯示menuif (shouldScrollToMenu()) {scrollToMenu();} else {scrollToContent();}}//判斷手勢意圖想顯示contentif (wantToShowContent()) {//判斷是否顯示contentif (shouldScrollToContent()) {scrollToContent();} else {scrollToMenu();}}//終止速度追蹤stopVelocityTracker();break;default:break;}return true;}}/** * 判斷當前手勢是否想顯示菜單Menu * 判斷條件: * 1 抬起座標大於按下座標 * 2 menu本身不可見 */private boolean wantToShowMenu(){return ((xUp-xDown>0)&&(!isMenuVisible));}/** * 判斷是否應該將menu完整顯示出來 * 判斷條件: * 滑動距離大於螢幕的二分之一 * 或者滑動速度大於速度閾值VELOCITY_THRESHOLD */private boolean shouldScrollToMenu(){return ((xUp-xDown>screenWidth/2)||(getScrollVelocity()>VELOCITY_THRESHOLD));}/** * 將螢幕滾動到menu.即將menu完整顯示. * 按照30的步調不斷修改修改menu的LayoutParams中的leftMargin */private void scrollToMenu(){new ScrollAsyncTask().execute(30);}/** * 判斷當前手勢是否想顯示菜單Content * 判斷條件: * 1 抬起座標小於按下座標 * 2 menu本身可見 */private boolean wantToShowContent(){return ((xUp-xDown<0)&&(isMenuVisible));}/** * 判斷是否應該將content完整顯示出來 * 判斷條件: * xDown-xUp+contentViewMinWidth大於螢幕的二分之一 * 或者滑動速度大於速度閾值VELOCITY_THRESHOLD */private boolean shouldScrollToContent(){return ((xDown-xUp+contentViewMinWidth>screenWidth/2)||(getScrollVelocity()>VELOCITY_THRESHOLD));}/** * 將螢幕滾動到content.即將content完整顯示 * 按照-30的步調不斷修改修改menu的LayoutParams中的leftMargin */private void scrollToContent(){new ScrollAsyncTask().execute(-30);}/** * 開始速度追蹤 */private void startVelocityTracker(MotionEvent event){if (mVelocityTracker==null) {mVelocityTracker=VelocityTracker.obtain(); }mVelocityTracker.addMovement(event);}/** * 擷取在content上X方向的手指滑動速度 */private int getScrollVelocity(){//設定VelocityTracker單位.1000表示1秒時間內運動的像素 mVelocityTracker.computeCurrentVelocity(1000);//擷取在1秒內X方向所滑動像素值int xVelocity=(int) mVelocityTracker.getXVelocity();return Math.abs(xVelocity);}/** * 終止速度追蹤 */private void stopVelocityTracker(){if (mVelocityTracker!=null) {mVelocityTracker.recycle();mVelocityTracker=null;}}/** * 利用非同步任務不斷修改menu的LayoutParams中的leftMargin從而達到一個 * 視圖移動的效果 */private class ScrollAsyncTask extends AsyncTask{@Overrideprotected Integer doInBackground(Integer... speed) {int leftMargin=menuLayoutParams.leftMargin;while(true){//每次變化的speedleftMargin=leftMargin+speed[0];//若越界,則處理越界且跳出迴圈if (leftMargin>menuParamsMaxLeftMargin) {leftMargin=menuParamsMaxLeftMargin;break;}//若越界,則處理越界且跳出迴圈if (leftMargin0) {isMenuVisible=true;}else{isMenuVisible=false;}return leftMargin;}@Overrideprotected void onProgressUpdate(Integer... leftMargin) {super.onProgressUpdate(leftMargin);menuLayoutParams.leftMargin=leftMargin[0];menuView.setLayoutParams(menuLayoutParams);}@Overrideprotected void onPostExecute(Integer leftMargin) {super.onPostExecute(leftMargin);menuLayoutParams.leftMargin=leftMargin;menuView.setLayoutParams(menuLayoutParams);}}}

main.xml如下:
        

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.