Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> 自定義android側滑菜單

自定義android側滑菜單

編輯:關於Android編程

這裡實現兩種側滑菜單效果,第一種拖拽內容部分,菜單像是被拖出來的感覺的這種效果,第二種是拖拽內容部分,菜單在內容後面不動,感覺有一種層次感的效果,如下


\\


<喎?/kf/ware/vc/" target="_blank" class="keylink">vcD4KPHA+tdrSu9bW0Ke5+7XEtPrC68q1z9bI58/Co7o8L3A+CjxwPjxwcmUgY2xhc3M9"brush:java;">package com.tenghu.customsideslip.menu.view; import android.content.Context; import android.os.AsyncTask; import android.util.AttributeSet; import android.util.DisplayMetrics; import android.view.MotionEvent; import android.view.VelocityTracker; import android.view.View; import android.view.WindowManager; import android.widget.LinearLayout; /** * Created by Arvin_Li on 2014/11/19. */ public class ScrollSideslipMenu extends LinearLayout{ private static final int SNAP_VELOCITY=200;//速度阈值 private View mMenu;//菜單布局 private View mContent;//內容布局 private int screenWidth;//屏幕寬度 private int menuWidth;//菜單寬度 private int leftEdge;//左邊界 private int rightEdge=0;//右邊界,值恆為0 private float xUp;//手指抬起時記錄橫坐標 private float xDown;//手指按下時記錄橫坐標 private float xMove;//手指移動時記錄橫坐標 private int toRightPaddingWidth=50;//菜單完全顯示時,留給內容的寬度 private LayoutParams menuParams;//菜單布局參數 private boolean once=false;//初始化數據只加載一次 private boolean isShowMenu;//是否顯示菜單 private VelocityTracker velocityTracker;//速度跟蹤器 public ScrollSideslipMenu(Context context) { super(context); initWindowWidth(context); } public ScrollSideslipMenu(Context context, AttributeSet attrs) { super(context, attrs); initWindowWidth(context); } /** * 初始化獲取屏幕寬度 */ private void initWindowWidth(Context context){ WindowManager windowManager= (WindowManager) context.getSystemService(Context.WINDOW_SERVICE); DisplayMetrics displayMetrics=new DisplayMetrics(); windowManager.getDefaultDisplay().getMetrics(displayMetrics); //獲取屏幕寬度 screenWidth=displayMetrics.widthPixels; } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(widthMeasureSpec, heightMeasureSpec); if(!once){ mMenu=this.getChildAt(0);//獲取菜單布局 mContent=this.getChildAt(1);//獲取內容布局 menuParams= (LayoutParams) mMenu.getLayoutParams();//獲取菜單布局參數 menuWidth=menuParams.width=screenWidth-toRightPaddingWidth;//設置菜單寬度 mContent.getLayoutParams().width=screenWidth;//設置內容寬度 leftEdge=-menuWidth;//左邊界 menuParams.leftMargin=leftEdge;//默認菜單不顯示 once=true; } } @Override public boolean onTouchEvent(MotionEvent event) { createVelocityTracker(event); switch (event.getAction()){ //按下 case MotionEvent.ACTION_DOWN: xDown=event.getRawX();//記錄按下時的橫坐標 break; //移動 case MotionEvent.ACTION_MOVE: //記錄移動時的橫坐標 xMove=event.getRawX(); //計算移動時與按下時的距離 int moveDistanceX= (int) (xMove-xDown); if(isShowMenu){ menuParams.leftMargin=moveDistanceX; }else{ menuParams.leftMargin=leftEdge+moveDistanceX; } if(menuParams.leftMarginrightEdge){ menuParams.leftMargin=rightEdge; } mMenu.setLayoutParams(menuParams);//設置參數 break; //抬起 case MotionEvent.ACTION_UP: //記錄抬起時的橫坐標 xUp=event.getRawX(); //計算抬起時與按下時的距離 int upDistanceX= (int) (xUp-xDown); if(upDistanceX>0&&!isShowMenu){ if(upDistanceX>menuWidth/2||getScrollVelocity()>SNAP_VELOCITY){ scrollToMenu(); }else{ scrollToContent(); } }else if(upDistanceX<0&&isShowMenu){ if(Math.abs(upDistanceX)>menuWidth/2||getScrollVelocity()>SNAP_VELOCITY){ scrollToContent(); }else{ scrollToMenu(); } } mMenu.setLayoutParams(menuParams); break; } return true; } /** * 滾動內容部分 */ private void scrollToContent(){ new ScrollTask().execute(-30); } /** * 滾動菜單部分 */ private void scrollToMenu(){ new ScrollTask().execute(30); } /** * 創建速度阈值 */ private void createVelocityTracker(MotionEvent event){ if(null==velocityTracker){ velocityTracker=VelocityTracker.obtain(); } velocityTracker.addMovement(event); } /** * 獲取滾動時的速度 * @return */ private int getScrollVelocity(){ velocityTracker.computeCurrentVelocity(1000); int velocity= (int) velocityTracker.getXVelocity();//獲取橫向速度 return Math.abs(velocity); } /** * 創建一個異步滾動任務 */ class ScrollTask extends AsyncTask{ @Override protected Integer doInBackground(Integer... params) { int leftMargin=menuParams.leftMargin; while(true){ leftMargin=leftMargin+params[0]; if(leftMarginrightEdge){ leftMargin=rightEdge; break; } publishProgress(leftMargin); sleep(20); } if(params[0]>0){ isShowMenu=true; }else{ isShowMenu=false; } return leftMargin; } /** * 執行結束 * @param integer */ @Override protected void onPostExecute(Integer integer) { menuParams.leftMargin=integer; mMenu.setLayoutParams(menuParams); } /** * 執行doInBackground中的publishProgress調用該方法 * @param values */ @Override protected void onProgressUpdate(Integer... values) { menuParams.leftMargin=values[0]; mMenu.setLayoutParams(menuParams); } } /** * 當前線程睡眠多少毫秒 * @param millis */ private void sleep(long millis){ try { Thread.sleep(millis); } catch (InterruptedException e) { e.printStackTrace(); } } }
布局文件:



    
    
    


第二種效果實現:

package com.tenghu.customsideslip.menu.view;

import android.content.Context;
import android.os.AsyncTask;
import android.util.AttributeSet;
import android.util.DisplayMetrics;
import android.view.MotionEvent;
import android.view.VelocityTracker;
import android.view.View;
import android.view.WindowManager;
import android.widget.RelativeLayout;

/**
 * Created by Arvin_Li on 2014/11/19.
 */
public class CustomSideslipMenu extends RelativeLayout {
    private static final int SNAP_VELOCITY=200;//手勢滑動的速度
    //屏幕寬度
    private int mScreenWidth;
    //菜單布局
    private View mMenu;
    //主體內容部分
    private View mContent;
    //聲明菜單寬度
    private int menuWidth;
    //菜單完全顯示時,留給內容部分的寬度
    private int toRightPaddingWidth=50;
    //主體內容布局參數
    private LayoutParams contentParams;
    //主體內容滑動到左邊緣,由菜單寬度來決定
    private int leftEdge;
    //菜單顯示時,主體內容到右邊界,值恆為0
    private int rightEdge=0;
    private VelocityTracker velocityTracker;//聲明速度跟蹤器
    private float xDown;//記錄手指按下的橫坐標
    private float xUp;//記錄手指抬起時的橫坐標
    private float xMove;//記錄手指移動時的橫坐標
    private boolean once=false;//只執行一次
    private boolean isShowMenu=true;//是否顯示菜單
    public CustomSideslipMenu(Context context) {
        super(context);
        init(context);
    }

    public CustomSideslipMenu(Context context, AttributeSet attrs) {
        super(context, attrs);
        init(context);
    }

    /**
     * 初始化
     */
    private void init(Context context){
        //獲取窗口管理類
        WindowManager windowManager= (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
        //創建DisplayMetrics
        DisplayMetrics displayMetrics=new DisplayMetrics();
        windowManager.getDefaultDisplay().getMetrics(displayMetrics);
        //獲取屏幕寬度
        mScreenWidth=displayMetrics.widthPixels;
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        if(!once){
            //獲取菜單布局
            mMenu=this.getChildAt(0);
            //獲取主體內容布局
            mContent=this.getChildAt(1);
            contentParams= (LayoutParams) mContent.getLayoutParams();//獲取主體菜單參數
            //菜單寬度
            menuWidth=mMenu.getLayoutParams().width=mScreenWidth-toRightPaddingWidth;
            //設置主體內容的寬度
            mContent.getLayoutParams().width=mScreenWidth;
            leftEdge=menuWidth;//設置左邊界
            once=true;
        }
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        //調用創建速度跟蹤器
        createVelocityTracker(event);
        switch (event.getAction()){
            //手指按下
            case MotionEvent.ACTION_DOWN:
                xDown=event.getRawX();
                break;
            //手指移動
            case MotionEvent.ACTION_MOVE:
                xMove=event.getRawX();
                //計算移動距離
                int distanceX= (int) (xMove-xDown);
                if(isShowMenu){
                    contentParams.leftMargin=distanceX;
                    contentParams.rightMargin=-distanceX;
                }else{
                    contentParams.leftMargin=leftEdge+distanceX;
                }

                if(contentParams.leftMargin>leftEdge){
                    contentParams.leftMargin=leftEdge;
                    contentParams.rightMargin=-leftEdge;
                }

                if(contentParams.leftMargin0&&!isShowMenu){
                        if(upDistanceX>menuWidth/2||getScrollVelocity()>SNAP_VELOCITY){
                            scrollToMenu();
                        }else{
                            scrollToContent();
                        }
                }else if(upDistanceX<0&&isShowMenu){
                    if(Math.abs(upDistanceX)>menuWidth/2||getScrollVelocity()>SNAP_VELOCITY){
                        scrollToContent();
                    }else{
                        scrollToMenu();
                    }
                    //手指抬起時銷毀
                    recycleVelocityTracker();
                }
                break;
        }
        return true;
    }

    /**
     * 滾動菜單
     */
    private void scrollToMenu(){
        new ScrollTask().execute(-30);
    }

    /**
     * 滾動內容
     */
    private void scrollToContent(){
        new ScrollTask().execute(30);
    }

    /**
     * 獲取速度
     * @return
     */
    private int getScrollVelocity(){
        velocityTracker.computeCurrentVelocity(1000);
        int velocity= (int) velocityTracker.getXVelocity();
        return Math.abs(velocity);
    }

    /**
     * 銷毀速度跟蹤器
     */
    private void recycleVelocityTracker(){
        if (null != velocityTracker) {
            velocityTracker.recycle();
            velocityTracker = null;
        }
    }


    /**
     * 創建速度跟蹤器
     */
    private void createVelocityTracker(MotionEvent event){
        if(null==velocityTracker){
            velocityTracker=velocityTracker.obtain();
        }
        velocityTracker.addMovement(event);
    }

    /**
     * 創建異步滾動任務類
     */
    class ScrollTask extends AsyncTask{

        @Override
        protected Integer doInBackground(Integer... params) {
            int leftMargin=contentParams.leftMargin;
            while(true){
                leftMargin=leftMargin+params[0];
                if(leftMargin>leftEdge){
                    leftMargin=leftEdge;
                    break;
                }

                if(leftMargin
布局文件:



    

    

        
            

菜單布局文件:




    

        

            

            
        

        

            

            
        

        

            

            
        

        

            

            
        

        

            

            
        

    


這裡的菜單,可以是用ListView來布局,做測試就沒有那樣做了,所有代碼全部在這裡了,可以看出,兩種效果只是繼承了不通的布局,感覺第二種效果在設置背景時有點問題,就是在這裡


        
            
如果將背景設置到第一層的LinearLayout上,那麼自定義側滑菜單那裡設置背景就顯示不出來,設置到第二層就可以,不知道是腫麼回事,如果各位大師找到了,麻煩告訴小弟。

  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved