Android 使用Material Design实现滑动菜单
- 前言
- DrawerLayout布局
- NavigationView控件
前言
Android Material Design库提供了统一的UI设计和个性化界面风格,这其中,侧边滑动菜单可谓是一大亮点,Material Design提供了DrawerLayout布局和NavigationView控件实现了这一特性,两者珠联璧合,使开发者能够轻松的实现比较酷炫的滑动菜单效果。本文是对《Android第一行代码》第十二章的学习记录,以及滑动菜单的实现的总结。
DrawerLayout布局
DrawerLayout是Design库中实现滑动菜单效果的支撑性布局,它允许放入两个直接子控件,第一个子控件是主屏幕中的内容,第二个子控件是滑动菜单中显示的内容。我们在activity_main.xml文件中使用DrawerLayout布局如下:
<?xml version="1.0" encoding="utf-8"?><androidx.drawerlayout.widget.DrawerLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" android:id="@+id/drawer_layout" android:layout_width="match_parent" android:layout_height="match_parent"> <FrameLayout android:layout_width="match_parent" android:layout_height="match_parent"> <androidx.appcompat.widget.Toolbar android:id="@+id/toolbar" android:background="?attr/colorPrimary" android:layout_width="match_parent" android:layout_height="?attr/actionBarSize" android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar" android:popupTheme="@style/ThemeOverlay.AppCompat.Light"> androidx.appcompat.widget.Toolbar> FrameLayout> <TextView android:layout_gravity="start" android:text="This is menu" android:textSize="30sp" android:background="#FFF" android:layout_width="match_parent" android:layout_height="match_parent" />androidx.drawerlayout.widget.DrawerLayout>
实现效果如下:
我们在标题栏添加一个侧边栏按钮,这样可以使得滑动菜单更加人性化,修改MainActivity.java代码如下:
public class MainActivity extends AppCompatActivity { private DrawerLayout mDrawerLayout; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); Toolbar toolbar = findViewById(R.id.toolbar); setSupportActionBar(toolbar); // 获取DrawerLayout布局 mDrawerLayout = findViewById(R.id.drawer_layout); ActionBar actionBar = getSupportActionBar(); if(actionBar!=null){ actionBar.setDisplayHomeAsUpEnabled(true); actionBar.setHomeAsUpIndicator(R.drawable.ic_menu); } } @Override public boolean onCreateOptionsMenu(Menu menu) { getMenuInflater().inflate(R.menu.toolbar, menu); return true; } @Override public boolean onOptionsItemSelected(@NonNull MenuItem item) { switch(item.getItemId()){ case android.R.id.home: mDrawerLayout.openDrawer(GravityCompat.START); break; case R.id.backup: Toast.makeText(this,"You clicked Backup!", Toast.LENGTH_SHORT).show(); break; case R.id.delete: Toast.makeText(this,"You clicked Delete!", Toast.LENGTH_SHORT).show(); break; case R.id.settings: Toast.makeText(this,"You clicked Settings", Toast.LENGTH_SHORT).show(); break; default: break; } return true; }}
首先用findViewId
方法获取DrawerLayout
的实例,然后用getSupportActionBar
方法获取了ActionBar
的实例,在这里ActionBar
是由Toolbar
来充当,然后调用了ActionBar
方法的setDisplayHomeAsUpEnabled
方法和setHomeAsUpIndicator
方法让导航按钮显示出来并设置对应的图标。实际上,Toolbar左侧的按钮叫做HomeAsup按钮 。
然后在onOptionsItemSelected
方法中对HomeAsup
点击事件进行处理,HomeAsup按钮的值永远是android.R.id.home
,然后openDrawer
方法将滑动菜单显示出来,具体效果如下:
显然,这个滑动菜单比较原始而低级,我们下面通过NavigationView控件来美化我们的滑动菜单。
NavigationView控件
NavigationView是Design Support中提供的一个控件,它不仅严格按照Material Design要求进行设计,还可以将滑动菜单变得非常简单。我们简单了解一下NavigationView的用法——
首先,在build.gradle文件的dependencies添加依赖——
dependencies { ... implementation 'com.android.support:design:28.0.0-alpha3' implementation 'de.hdodenhof:circleimageview:2.1.0' ...}
其中,第二行是CircleImageView第三方库,它能够轻松实现图片圆形化。
然后,为了方便显示菜单优化效果,我们添加一个menu文件nav_menu.xml负责显示菜单栏部分,内容如下:
<?xml version="1.0" encoding="utf-8"?><menu xmlns:android="http://schemas.android.com/apk/res/android"><group android:checkableBehavior="single"> <item android:icon="@drawable/ic_call" android:title="Call" android:id="@+id/nav_call"/> <item android:icon="@drawable/ic_friends" android:title="Friends" android:id="@+id/nav_friends"/> <item android:id="@+id/nav_mail" android:title="Mail" android:icon="@drawable/ic_mail"/> <item android:icon="@drawable/ic_task" android:title="Task" android:id="@+id/nav_task" />group>menu>
同时,添加对应的图标文件。
然后再添加头像布局文件nav_header.xml,负责优化头像区域 ,内容如下:
<?xml version="1.0" encoding="utf-8"?><RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="180dp" android:padding="10dp" android:background="?attr/colorPrimary"> <de.hdodenhof.circleimageview.CircleImageView android:id="@+id/icon_image" android:layout_width="70dp" android:layout_height="70dp" android:src="@drawable/ic_header" android:layout_centerInParent="true"/> <TextView android:id="@+id/username" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="[email protected]" android:textSize="14sp" android:textColor="#FFF"/> <TextView android:id="@+id/mail" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_above="@id/username" android:text="Jason" android:textSize="14sp" android:textColor="#FFF"/>RelativeLayout>
其中,CircleImageView是用来将头像圆形化。然后在activity_main.xml文件中修改NavigationView区域的代码:
<?xml version="1.0" encoding="utf-8"?><androidx.drawerlayout.widget.DrawerLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" android:id="@+id/drawer_layout" android:layout_width="match_parent" android:layout_height="match_parent"> <FrameLayout android:layout_width="match_parent" android:layout_height="match_parent"> <androidx.appcompat.widget.Toolbar android:id="@+id/toolbar" android:background="?attr/colorPrimary" android:layout_width="match_parent" android:layout_height="?attr/actionBarSize" android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar" android:popupTheme="@style/ThemeOverlay.AppCompat.Light"> androidx.appcompat.widget.Toolbar> FrameLayout> <com.google.android.material.navigation.NavigationView android:id="@+id/nav_view" android:layout_gravity="start" android:layout_width="match_parent" android:layout_height="match_parent" app:menu="@menu/nav_menu" app:headerLayout="@layout/nav_header"/>androidx.drawerlayout.widget.DrawerLayout>
可以看到,在NavigationView中,分别有一个menu和headerLayout,即刚才设置的菜单栏和头像区域
对应的,修改MainActivity代码如下:
public class MainActivity extends AppCompatActivity { private DrawerLayout mDrawerLayout; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); Toolbar toolbar = findViewById(R.id.toolbar); setSupportActionBar(toolbar); mDrawerLayout = findViewById(R.id.drawer_layout); NavigationView navView = findViewById(R.id.nav_view); ActionBar actionBar = getSupportActionBar(); if(actionBar!=null){ actionBar.setDisplayHomeAsUpEnabled(true); actionBar.setHomeAsUpIndicator(R.drawable.ic_menu); } navView.setCheckedItem(R.id.nav_call); navView.setNavigationItemSelectedListener((v)->{ mDrawerLayout.closeDrawers(); return true; }); } @Override public boolean onCreateOptionsMenu(Menu menu) { getMenuInflater().inflate(R.menu.toolbar, menu); return true; } @Override public boolean onOptionsItemSelected(@NonNull MenuItem item) { switch(item.getItemId()){ case android.R.id.home: mDrawerLayout.openDrawer(GravityCompat.START); break; case R.id.backup: Toast.makeText(this,"You clicked Backup!", Toast.LENGTH_SHORT).show(); break; case R.id.delete: Toast.makeText(this,"You clicked Delete!", Toast.LENGTH_SHORT).show(); break; case R.id.settings: Toast.makeText(this,"You clicked Settings", Toast.LENGTH_SHORT).show(); break; default: break; } return true; }}
最终实现效果如下:
可以看到,相比于之前的滑动菜单界面,已经变得比较美观了。