原生Android 侧滑菜单实践(部分)

此为第一个制作侧滑菜单的实践 。

此部分仅仅为部分实践

仅缺menu的字符串布局,以及需要修改的MainActivity.java文件,也是需要主要修改的地方。

从使用MD设计-进行侧滑菜单的制作(activity_main.xml部分)仍然可看。

当中为了向前兼容以及使用Material Design,参考了约10个链接。

文件路径、参考链接为文章末尾,为了更好的阅读体验,增加了文件源代码展示(部分代码有删改)。

使用MD设计

设置向前兼容

进行4.0系统的一些工作

参考链接-向前兼容-1

首先准备添加MD设计包,但考虑到Android Icecream(4.0)仅为14,参考链接中得知Appcomat为21,所以先做以下调整:

  1. build.gradle:
android {
    compileSdkVersion 21
    defaultConfig {
        applicationId "product.felixxiong.com.MyPackgeName"
        minSdkVersion 14
        targetSdkVersion 21
        versionCode 1
        versionName "1.0"
        testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
    }
...
dependencies {
    implementation fileTree(dir: 'libs', include: ['*.jar'])
    implementation 'com.android.support:appcompat-v7:21.0.+'  //导入Appcompat依赖5.0的21并随时获取可用新版本
    implementation 'com.android.support.v7.widget.SwichCompat'//导入支持MD的switch控件
    implementation 'com.android.support:design.21'  //导入21设计库:参考链接:
   

values相关xml文件

  1. 新建values/themes.xml
<?xml version="1.0" encoding="utf-8"?>
<resources>
    <style name="AppTheme" parent="AppTheme.Base"/>
    <style name="AppTheme.Base" parent="Theme.AppCompat">
        <item name="colorPrimary">@color/colorPrimary</item>
        <item name="colorPrimaryDark">@color/colorPrimary</item>
        <item name="windowNoTitle">true</item>
        <item name="windowActionBar">false</item>
    </style>
</resources>
  1. 新建values-v21/themes.xml
<?xml version="1.0" encoding="utf-8"?>
<resources>
<style name="AppTheme" parent="AppTheme.Base">
    <item name="android:windowContentTransitions">true</item>
    <item name="android:windowAllowEnterTransitionOverlap">true</item>
    <item name="android:windowAllowReturnTransitionOverlap">true</item>
    <item name="android:windowSharedElementEnterTransition">@android:transition/move</item>
    <item name="android:windowSharedElementExitTransition">@android:transition/move</item>
</style>
</resources>

添加依赖

参考链接:向前兼容

apply plugin: 'com.android.application'

allprojects {
    repositories {
        google()
        jcenter()
    }
}
...
dependencies {
    implementation fileTree(dir: 'libs', include: ['*.jar'])
    implementation 'com.android.support:appcompat-v7:21.0.+'  //导入Appcompat依赖5.0的21并随时获取可用新版本
    implementation 'com.android.support.v7.widget.SwichCompat'//导入支持MD的switch控件
    implementation 'com.android.support:design.21'  //导入21设计库
    implementation 'com.android.support.constraint:constraint-layout:1.1.2'
    //implementation 'com.google.android.material:material:1.0.0-rc01'

使用Toolbar替换Action Bar

参考链接-向前兼容-1

  1. active_main.xml:
  <android.support.v7.widget.Toolbar xmlns:android="http://schemas.android.com/apk/res/android"
            android:id="@+id/toolbar"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:theme="@style/Theme.AppCompat.NoActionBar" /> 
            <!--参考链接:关于toolbar-4-->
            <!--android:background="?attr/colorPrimaryDark"-->
                android:background="#3F51B5">                     <!--Toolbar可自定义颜色-->
</android.support.v7.widget.Toolbar>
  1. MainActivity.java:
@Override
    protectedvoidonCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(getLayoutResource()); 
        //getLayoutResource()此处需要获取布局文件R.layout.……
        
        Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar); //主要关于Toolbar的代码
        if(toolbar != null) {
            setSupportActionBar(toolbar);
        }
    }

进行侧滑菜单的制作

布局文件

导航栏布局

activity_main.xml
  1. 设定material.navigation.NavigationView

参考链接:Material Design

<com.google.android.material.navigation.NavigationView

        android:id="@+id/left_navigation_drawer"
        android:layout_width="wrap_content"
        android:layout_height="match_parent"
        android:layout_gravity="start"                <!--layout_gravity指定重力-->
        app:headerLayout="@layout/navigation_header"  <!--设置navigation头布局-->
        app:menu="@menu/my_navigation_items">         <!--设置navigation导航布局-->
    <!--android:dividerHeight="0dp"
        android:background="#111"--/>

    </com.google.android.material.navigation.NavigationView>

</android.support.v4.widget.DrawerLayout>

设置布局,在相应目录下新建文件:

layout\navigation_header.xml

menu\my_navigation_items

        android:dividerHeight="0dp"

此处代码链接为开发者文档,MD可能不需要两行代码。

  1. 添加Framelayout

此处链接为开发者文档。

<FrameLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:id="@+id/decor_content_frame"> 
        <!--主内容视图必须为第一个视图,抽屉式导航必须位于内容顶部-->

        <android.support.v7.widget.Toolbar 
        ... />

    </FrameLayout>

菜单头部布局

参考链接:侧滑菜单-1

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="?attr/colorPrimary"
    android:gravity="center"
    android:orientation="vertical"
    android:paddingBottom="50dp"
    android:paddingTop="50dp"
    android:theme="@style/ThemeOverlay.AppCompat.Dark">

    <com.google.android.material.internal.VisibilityAwareImageButton 
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:src="@mipmap/ic_launcher"/>

    <android.support.v7.widget.AppCompatTextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="5dp"
        android:text="demo"/>


</LinearLayout>

菜单项布局

my_navigation_items

此处参考链接:侧滑菜单-1,因为开发者文档中使用Adpter方法实现填充,需要深入了解Adpter,故未加入。

JAVA文件()

Main Activity.java

参考链接:侧滑菜单-1

  1. 初始化抽屉导航栏列表
public class MainActivity extends AppCompatActivity {

    @Override
    protectedvoidonCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        }
    
    private Toolbar toolbar;   //此处Toolbar修改为自己习惯的写法,为变量
    private String[] mTitles;  //创建标题变量
    private DrawerLayout mDrawerLayout;  //创建抽屉视图变量
    private NavigationView mDrawerNavgation; //创建侧滑菜单视图变量
    //private ActionBarDrawerToggle mDrawerToggle;  在后文中出现
    //创建Toobar的子类作为监听器,需要在生命周期中调用togge
    //private CharSequence mDrawerTitle;
    //private CharSequence mTitle;

    ...
            @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

      //mTitles = R.layout.activity_main.getStringArray(R.array.Titles_array); //初始化界面
      //此处Toolbar修改为自己习惯的写法,实例化Toolbar写一起
        Toolbar toolbar = (Toolbar)findViewById(R.id.toolbar);
        onCreateOptionsMenu(R.layout.activity_main);
        toolbar.setTitle("My Title");
        setSupportActionBar(toolbar);

        mDrawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout);

        mDrawerNavgation = (NavigationView) findViewById(R.id.left_navigation_drawer);
        mDrawerNavgation.setAdapter(new ArrayAdapter<String>(this, R.layout.drawer_layout, mTitles));  //为列表视图设置适配器

        mDrawerNavgation.setOnItemClickListener(new DrawerItemClickListener());  //调用接收点击事件,设置点击监听器
    }
    ...
   }
}
  1. 处理导航点击事件
private class DrawerItemClickListener implements NavigationView.OnItemClickListener {   //开始处理导航事件:在用户选择某一项时实现接口更改内容视图
        @Override                                                  //这里开始调用onItemClick
        public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
            selectItem(position);
        }
    }

    private void selectItem(int position) {

        Fragment fragment = new Fragment();  //封装一个新片段并指定要根据位置显示的
        Bundle args = new Bundle();
        args.putInt(Fragment.ARG_LIST_NUMBER, position);
        fragment.setArguments(args);

        FragmentManager fragmentManager = getFragmentManager(); //通过替换任何现有片段插入片段
        fragmentManager.beginTransaction()                      
         //将不同的FrameLayout插入内容主视图
                .replace(R.id.decor_content_frame, fragment)
                .commit();

        // Highlight the selected item, update the title, and close the drawer
        mDrawerNavgation.setItemChecked(position, true);
        setTitle(mTitles[position]);
        mDrawerLayout.closeDrawer(mDrawerNavgation);
    }

    @Override
    public void setTitle(CharSequence title) {
        mTitle = title;
        getActionBar().setTitle(mTitle);
    }

3.侦听打开和关闭事件

public class MainActivity extends AppCompatActivity {
    private ActionBarDrawerToggle mDrawerToggle; 
    //创建Toobar的子类作为监听器,需要在生命周期中调用togge
    private CharSequence mDrawerTitle;
    private CharSequence mTitle;
    ...
     @Override
    protectedvoidonCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        }
...
        mTitle = mDrawerTitle = getTitle();
        mDrawerToggle = new ActionBarDrawerToggle(this, mDrawerLayout, R.drawable.ic_drawer, R.string.drawer_open, R.string.drawer_close) {

        /** Called when a drawer has settled in a completely closed state. */
        public void onDrawerClosed(View view) {
            super.onDrawerClosed(view);
            getActionBar().setTitle(mTitle);
            invalidateOptionsMenu(); // creates call to onPrepareOptionsMenu()
        }

        /** Called when a drawer has settled in a completely open state. */
        public void onDrawerOpened(View drawerView) {
            super.onDrawerOpened(drawerView);
            getActionBar().setTitle(mDrawerTitle);
            invalidateOptionsMenu(); // creates call to onPrepareOptionsMenu()
        }
    };

        mDrawerLayout.setDrawerListener(mDrawerToggle); //将抽屉切换设置为DrawerListener

        getActionBar().setDisplayHomeAsUpEnabled(true);
        getActionBar().setHomeButtonEnabled(true);
    }
    /* Called whenever we call invalidateOptionsMenu() */
    @Override
    public boolean onPrepareOptionsMenu(Menu menu) {
        // If the nav drawer is open, hide action items related to the content view
        boolean drawerOpen = mDrawerLayout.isDrawerOpen(mDrawerNavgation);
        menu.findItem(R.id.action_websearch).setVisible(!drawerOpen);
        return super.onPrepareOptionsMenu(menu);
    }
}
  1. 通过应用图标打开和关闭
 mDrawerLayout = (DrawerLayout)findViewById(R.id.drawer_layout);  
//通过应用图标打开或关闭抽屉导航栏
        mDrawerToggle = new ActionBarDrawerToggle(this,mDrawerLayout,         /* DrawerLayout object */
                R.drawable.ic_drawer,  /* nav drawer icon to replace 'Up' caret */
                R.string.drawer_open,  /* "open drawer" description */
                R.string.drawer_close  /* "close drawer" description */
        ) {

            public void onDrawerClosed(View view) { //当抽屉处于完全关闭状态时调用。
                super.onDrawerClosed(view);
                //getActionBar().setTitle(mTitle);  //设置标题
            }

            public void onDrawerOpened(View drawerView) { //当抽屉处于完全状态时调用。
                super.onDrawerOpened(drawerView);
                //getToolBar().setTitle(mDrawerTitle); //设置标题
            }
        };

        mDrawerLayout.setDrawerListener(mDrawerToggle); ////将抽屉切换设置为DrawerListener

        getActionBar().setDisplayHomeAsUpEnabled(true);
        getActionBar().setHomeButtonEnabled(true);
    }

    @Override
    public boolean onPrepareOptionsMenu(Menu menu) { 
    //每当我们调用invalidateOptionsMenu()时调用
        boolean drawerOpen = mDrawerLayout.isDrawerOpen(mDrawerNavgation); 
        //如果导航抽屉已打开,请隐藏与内容视图相关的操作项
        menu.findItem(R.id.action_websearch).setVisible(!drawerOpen);
        return super.onPrepareOptionsMenu(menu);
    }
}

    @Override
    protected void onPostCreate(Bundle savedInstanceState) { //在生命周期中调用ActionBarDrawerToggle
        super.onPostCreate(savedInstanceState);
        mDrawerToggle.syncState(); ////在onRestoreInstanceState发生后同步切换状态。
    }

    @Override
    public void onConfigurationChanged(Configuration newConfig) {
        super.onConfigurationChanged(newConfig);
        mDrawerToggle.onConfigurationChanged(newConfig);
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        // Pass the event to ActionBarDrawerToggle, if it returns
        // true, then it has handled the app icon touch event
        if (mDrawerToggle.onOptionsItemSelected(item)) {
            return true;
        }
        // Handle your other action bar items...

        return super.onOptionsItemSelected(item);
    }

文件全部代码

build.gradle

allprojects {
    repositories {
        google()
        jcenter()
    }
}

android {
    compileSdkVersion 21
    defaultConfig {
        applicationId "product.penghaoxiong.com.androidquickcheck"
        minSdkVersion 14
        targetSdkVersion 21
        versionCode 1
        versionName "1.0"
        testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
    }
    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }
}

dependencies {
    implementation fileTree(dir: 'libs', include: ['*.jar'])
    implementation 'com.android.support:appcompat-v7:21.0.+'  //导入Appcompat依赖5.0的21并随时获取可用新版本
    implementation 'com.android.support.v7.widget.SwichCompat'//导入支持MD的switch控件
    implementation 'com.android.support:design.21'  //导入21设计库
    implementation 'com.android.support.constraint:constraint-layout:1.1.2'
    //implementation 'com.google.android.material:material:1.0.0-rc01'
    testImplementation 'junit:junit:4.12'
    androidTestImplementation 'com.android.support.test:runner:1.0.2'
    androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
}

参考链接

关于向前兼容

  1. AppCompat 21实现低版本手机使用Material Design
  2. 在低版本Android上使用Material Design——AppCompat v21
  3. 如何选择 compileSdkVersion, minSdkVersion 和 targetSdkVersion

关于Toolbar

  1. android:ToolBar详解(手把手教程)
  2. 利用Toolbar替换ActionBar
  3. ToolBar替代ActionBar

Material Design

  1. Navigation Views

侧滑菜单

  1. Android 实现侧滑菜单-design

路径

  1. build.gradle:app\build.gradle

  2. MainActivity.java:app\src\main\java\product\felixxiong\com\check\MainActivity\MainActivity.java

  3. active_main.xml:app\src\main\res\layout\active_main.xml

  4. layout:

    layout\navigation_header.xml

  5. values:app\src\main\res\values

    values/themes.xml

    values-v21/themes.xml


同步发布:SegmentFault掘金CSDN

 wechat
产品北里,讲述产品和人性、涉及设计、技术和运营的公众号。
你们的赞赏是我更新的动力~