Android 側滑選單實踐(部分)
此為第一個製作側滑選單的實踐 。
此部分僅僅為部分實踐 :
僅缺menu的字串佈局,以及需要修改的MainActivity.java檔案,也是需要主要修改的地方。
從使用MD設計-進行側滑選單的製作(activity_main.xml部分)仍然可看。
當中為了向前相容以及使用Material Design,參考了約10個連結。
檔案路徑、參考連結為文章末尾,為了更好的閱讀體驗,增加了檔案原始碼展示(部分程式碼有刪改)。
使用MD設計
設定向前相容
進行4.0系統的一些工作
參考連結-向前相容-1
首先準備新增MD設計包,但考慮到Android Icecream(4.0)僅為14,參考連結中得知Appcomat為21,所以先做以下調整:
- 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檔案
- 新建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>
- 新建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
- 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>
- 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
- 設定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可能不需要兩行程式碼。
- 新增Framelayout
此處連結為開發者文件。
<FrameLayout android:layout_width="match_parent" android:layout_height="match_parent" android:id="@+id/decor_content_frame"> <!--主內容檢視必須為第一個檢視,抽屜式導航必須位於內容頂部--> <android.support.v7.widget.Toolbar ... /> </FrameLayout>
選單頭部佈局
navigation_header.xml
參考連結:側滑選單-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
- 初始化抽屜導航欄列表
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());//呼叫接收點選事件,設定點選監聽器 } ... } }
- 處理導航點選事件
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); } }
- 通過應用圖示開啟和關閉
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' }