Android Material Design库提供了统一的UI设计和个性化界面风格,这其中,侧边滑动菜单可谓是一大亮点,Material Design提供了DrawerLayout布局和NavigationView控件实现了这一特性,两者珠联璧合,使开发者能够轻松的实现比较酷炫的滑动菜单效果。本文是对《Android第一行代码》第十二章的学习记录,以及滑动菜单的实现的总结。
DrawerLayout是Design库中实现滑动菜单效果的支撑性布局,它允许放入两个直接子控件,第一个子控件是主屏幕中的内容,第二个子控件是滑动菜单中显示的内容。我们在activity_main.xml文件中使用DrawerLayout布局如下:
<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是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负责显示菜单栏部分,内容如下:
<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,负责优化头像区域 ,内容如下:
<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区域的代码:
<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;
}
}
可以看到,相比于之前的滑动菜单界面,已经变得比较美观了。