[仿南航app開發日記3]側滑菜單實現

前言

這個是接着上面兩篇開發的日記,上面兩篇的日記:

[仿南航app開發日記1]開篇-總體佈局分析
[仿南航app開發日記2]主界面完成

糾正

因爲我看到南航app側滑的時候是內容菜單整個滑動,如果使用ActionBar的話。那麼ActionBar是不會移動的,所以要達到這種效果就只有取消ActionBar,因爲我的開發環境是android 5.0,所以取消ActionBar依然是在AndroidMenifest.xml文件裏面修改主題:

android:theme="@style/Theme.AppCompat.DayNight.NoActionBar"

完整的AndroidMenifest.xml文件如下:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="cn.karent.nanhang">

    <application
        android:allowBackup="true"
        android:name=".util.MyApplication"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:supportsRtl="true"
        android:theme="@style/Theme.AppCompat.DayNight.NoActionBar">

        <activity android:name=".MainActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>

</manifest>

分析

既然要加入側滑,那麼首先先編寫側滑菜單的佈局:

<?xml version="1.0" encoding="utf-8"?>
<!--側滑菜單的佈局-->
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical" android:layout_width="300dp"
    android:layout_marginRight="-150dp"
    android:layout_alignParentRight="true"
    android:layout_height="match_parent">
    <!--顯示頭像和一個背景-->
    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="200dp"
        android:clipChildren="false"
        android:background="@drawable/me_bg">
        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="80dp"
            android:gravity="left"
            android:orientation="vertical"
            android:layout_alignParentBottom="true">
            <ImageView
                android:layout_width="60dp"
                android:layout_height="60dp"
                android:layout_marginTop="-20dp"
                android:layout_marginLeft="30dp"
                android:src="@drawable/userhead_dealfut"/>
            <ImageView
                android:layout_width="60dp"
                android:layout_height="40dp"
                android:layout_marginTop="5dp"
                android:layout_marginLeft="30dp"
                android:src="@drawable/wujiaoxing"/>
        </LinearLayout>

    </RelativeLayout>
    <!--我的資料-->
    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="62dp"
        android:gravity="center"
        android:divider="@drawable/under_line"
        android:showDividers="end"
        android:background="@color/menuColor"
        android:orientation="horizontal">
        <ImageView
            android:layout_width="25dp"
            android:layout_height="25dp"
            android:layout_marginLeft="20dp"
            android:src="@drawable/user_icon1"/>
        <TextView
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:gravity="center"
            android:textSize="20sp"
            android:textColor="@android:color/black"
            android:text="@string/menu_home"/>
        <ImageView
            android:layout_width="25dp"
            android:layout_marginLeft="10dp"
            android:layout_height="wrap_content"
            android:layout_marginRight="20dp"
            android:src="@drawable/btn_icon_arrow"/>
    </LinearLayout>
    <!--修改密碼-->
    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="62dp"
        android:gravity="center"
        android:divider="@drawable/under_line"
        android:background="@color/menuColor"
        android:showDividers="end"
        android:orientation="horizontal">
        <ImageView
            android:layout_width="25dp"
            android:layout_height="25dp"
            android:layout_marginLeft="20dp"
            android:src="@drawable/pwd_icon1"/>
        <TextView
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:gravity="center"
            android:textSize="20sp"
            android:textColor="@android:color/black"
            android:text="@string/menu_modify_pwd"/>
        <ImageView
            android:layout_width="25dp"
            android:layout_marginLeft="10dp"
            android:layout_marginRight="20dp"
            android:layout_height="wrap_content"
            android:src="@drawable/btn_icon_arrow"/>
    </LinearLayout>
    <!--關於-->
    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="62dp"
        android:gravity="center"
        android:divider="@drawable/under_line"
        android:background="@color/menuColor"
        android:showDividers="end"
        android:orientation="horizontal">
        <ImageView
            android:layout_width="25dp"
            android:layout_height="25dp"
            android:layout_marginLeft="20dp"
            android:src="@drawable/question"/>
        <TextView
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:textSize="20sp"
            android:gravity="center"
            android:textColor="@android:color/black"
            android:layout_marginLeft="20dp"
            android:text="@string/menu_abount"/>
        <ImageView
            android:layout_width="25dp"
            android:layout_marginLeft="10dp"
            android:layout_height="wrap_content"
            android:layout_marginRight="20dp"
            android:src="@drawable/btn_icon_arrow"/>
    </LinearLayout>
    <!--我的二維碼-->
    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="62dp"
        android:gravity="center"
        android:divider="@drawable/under_line"
        android:background="@color/menuColor"
        android:showDividers="end"
        android:orientation="horizontal">
        <ImageView
            android:layout_width="25dp"
            android:layout_height="25dp"
            android:layout_marginLeft="20dp"
            android:src="@drawable/qcode"/>
        <TextView
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:layout_marginLeft="20dp"
            android:gravity="center"
            android:textSize="20sp"
            android:textColor="@android:color/black"
            android:text="@string/menu_qcode"/>
        <ImageView
            android:layout_width="25dp"
            android:layout_marginLeft="10dp"
            android:layout_height="wrap_content"
            android:layout_marginRight="20dp"
            android:src="@drawable/btn_icon_arrow"/>
    </LinearLayout>

    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:background="@color/menuColor"
        android:layout_weight="1">
        <Button
            android:layout_width="230dp"
            android:layout_height="wrap_content"
            android:text="登錄"
            android:background="@drawable/login_btn_shape"
            android:textColor="@android:color/white"
            android:layout_centerInParent="true"/>
    </RelativeLayout>

</LinearLayout>

上面也沒什麼好說的,也是堆出來的佈局,然後自定義一個側滑菜單Layout,具體可以參考我的博客:

http://blog.csdn.net/supervictim/article/details/53821577

我上面寫的不完全,感興趣的可以自己修改下,增加Touch事件監聽,如果用我上面的代碼會屏蔽掉Banner的滾動,而且原南航app好像也沒有滑動側滑,而是點擊右上角的頭像側滑,所以我直接取消了滑動側滑,修改後的源碼如下:

package cn.karent.nanhang.UI;

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

import cn.karent.nanhang.R;
import cn.karent.nanhang.util.ScreenUtil;

/**
 * Created by wan on 2016/12/6.
 * 側滑菜單,內容會偏移
 */
public class SlideLayout extends RelativeLayout {

    private Context mContext;

    private static final int MOTION_VELOCITY = 300;

    /*
        是否是第一次調用onLayout方法
     */
    private boolean mLoadOnece = false;

    /*
        左邊側滑菜單的佈局參數
     */
    private MarginLayoutParams mLeftParams;

    /*
        右邊內容的佈局參數
     */
    private MarginLayoutParams mMenuParams;

    /*
        左邊的側滑View
     */
    private View mLeftView;

    /*
        中間的內容View
     */
    private View mMenuView;

    private float mOldX;

    private float mOldY;

    /*
     * 屏幕的寬度
     */
    private int mScreenWidth;

    /**
     * 控件能夠移動到的左邊界
     */
    private int mLeftEdge = 300;

    public SlideLayout(Context context) {
        super(context);
        mContext = context;
    }

    public SlideLayout(Context context, AttributeSet attrs) {
        super(context, attrs);
        mContext = context;
    }

    /**
     * 佈局
     */
    public void onLayout(boolean change, int l, int t, int r, int b) {
        super.onLayout(change, l, t, r, b);
        if( change && !mLoadOnece) {
            mLeftEdge = ScreenUtil.dp2px(300);
            mLeftView = findViewById(R.id.slide_content);
            mMenuView = findViewById(R.id.slide_menu);
            mLeftParams =  (MarginLayoutParams) mLeftView.getLayoutParams();
            mMenuParams = (MarginLayoutParams)mMenuView.getLayoutParams();
            DisplayMetrics dm = getResources().getDisplayMetrics();
            mScreenWidth = dm.widthPixels;
            mLoadOnece = true;
        }
    }

    /**
     * 切換菜單的顯示和隱藏
     */
    public void switchMenu() {
        if( mLeftParams.leftMargin == 0) {
            showMenu();
        } else {
            hideMenu();
        }
    }

    /**
     * 顯示菜單
     */
    public void showMenu() {
        new SmoothScrollTack().execute(-mLeftEdge, mLeftParams.leftMargin);
    }

    /**
     * 隱藏菜單
     */
    public void hideMenu() {
        new SmoothScrollTack().execute(0, mLeftParams.leftMargin);
    }


    /**
     * 修改View的邊距來達到移動的效果
     * @param leftMargin
     */
    private void modifyLeftMargin(int leftMargin) {
        //如果左邊距大於0代表將要向右變壓縮,應該禁止
        if( leftMargin > 0 ) {
            mLeftParams.leftMargin = 0;
            mMenuView.setTranslationX(0);
            //控制左邊界滑動
        } else if( leftMargin < -mLeftEdge) {
            mLeftParams.leftMargin = -mLeftEdge;
            mMenuView.setTranslationX(-mLeftEdge / 2);
        } else {
            mLeftParams.leftMargin = leftMargin;
            mMenuView.setTranslationX(leftMargin / 2);
        }
        mLeftParams.width = mScreenWidth;
        mLeftView.setLayoutParams(mLeftParams);
    }

    /**
     * 當側滑停止的時候來出來接下來的滑動
     */
    private class SmoothScrollTack extends AsyncTask<Integer, Integer, Integer> {

        @Override
        protected void onProgressUpdate(Integer... values) {
            int leftMargin = values[0];
            modifyLeftMargin(leftMargin);
        }

        /**
         * 計算下一個leftMargin值,第一個參數的目標值
         * 第二個參數是當前的邊距
         * @param params
         * @return
         */
        @Override
        protected Integer doInBackground(Integer... params) {
            int targetLeftMargin = params[0];
            int currentLeftMargin = params[1];
            int leftMargin = currentLeftMargin;
            int step = targetLeftMargin == 0 ? 10 : -10;
            while(true) {
                leftMargin += step;
                //判斷是否滑動完成
                if( leftMargin < -mLeftEdge ) {
                    leftMargin = -mLeftEdge;
                    break;
                }
                if( leftMargin > 0 ) {
                    leftMargin = 0;
                    break;
                }
                publishProgress(leftMargin);
                try {
                    Thread.sleep(5);
                } catch( InterruptedException e) {
                    e.printStackTrace();
                }
            }
            publishProgress(leftMargin);
            return leftMargin;
        }
    }

}

我在裏面添加了三個函數並刪除了onTouchEvent事件:

 /**
     * 切換菜單的顯示和隱藏
     */
    public void switchMenu() {
        if( mLeftParams.leftMargin == 0) {
            showMenu();
        } else {
            hideMenu();
        }
    }

    /**
     * 顯示菜單
     */
    public void showMenu() {
        new SmoothScrollTack().execute(-mLeftEdge, mLeftParams.leftMargin);
    }

    /**
     * 隱藏菜單
     */
    public void hideMenu() {
        new SmoothScrollTack().execute(0, mLeftParams.leftMargin);
    }

具體的代碼邏輯我就不羅嗦了,我前面的博客有講,下面就是主佈局了:

<?xml version="1.0" encoding="utf-8"?>
<!--側滑菜單-->
<cn.karent.nanhang.UI.SlideLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/slide"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
    <!--菜單佈局-->
    <include android:id="@+id/slide_menu" layout="@layout/main_menu_layout"/>
    <!--內容佈局-->
    <include android:id="@+id/slide_content" layout="@layout/content_layout"/>
</cn.karent.nanhang.UI.SlideLayout>

這裏使用include標籤包含了兩個佈局,@layout/main_menu_layout這個是前面剛講的策劃菜單佈局,@layout/content_layout是上篇博客講的主界面佈局,然後修改MainActvity:

package cn.karent.nanhang;

import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.transition.Slide;
import android.view.View;
import android.widget.ImageView;

import cn.karent.nanhang.UI.NewsUI;
import cn.karent.nanhang.UI.SlideLayout;

public class MainActivity extends AppCompatActivity {
    /**
     * 封裝跟新聞有關的UI
     */
    private NewsUI mNewsUI;

    private ImageView headUser;

    private SlideLayout slide;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
//        setContentView(R.layout.content_layout);
        setContentView(R.layout.main);
        headUser = (ImageView)findViewById(R.id.head_user);
        slide = (SlideLayout)findViewById(R.id.slide);
        //設置titile
        mNewsUI = new NewsUI(this);
        headUser.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                slide.switchMenu();
            }
        });
    }



}

這裏將加載ActionBar的那一段代碼刪掉了,給右上角的ImageView添加點擊事件,點擊一下開始切換菜單

效果

這裏寫圖片描述
再上一張原app的界面:
這裏寫圖片描述
這就是今天的代碼了!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章