上星期我们说了MaterialDesign中的Toolbar来代替传统的ActionBar,今天我们来说一下MaterialDesign中的侧滑菜单(所谓侧滑菜单,就是侧滑,菜单才会显示出来,如果不侧滑就不显示在主屏幕,这样就节省了主屏幕的空间,同时又能有很好的效果),我们先来看一下布局怎么写,如下:
<android.support.v4.widget.DrawerLayout
android:id="@+id/main_drawer_layout"
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="android.lgt.materialdesigndemo.MainActivity">
********** 省略Toolbar的布局代码 **********
<TextView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:text="这是一个菜单"
android:background="#fff"
android:layout_gravity="start"
android:gravity="center"
/>
</android.support.v4.widget.DrawerLayout>
让我们来看看上面的代码,会发现,最外层布局不是LinearLayout了而是换成了一个DrawerLayout(这是support.v4库提供的),还多了一个TextView控件,同时包裹Toolbar的LinearLayout也成为了DrawerLayout的子控件。也就是说DrawerLayout有两个直接子控件,那么,DrawerLayout怎么区分哪个是滑动菜单应该显示的,哪个是Activity的菜单呢?请看TextView中一个很重要的属性,也是滑动菜单中必须要指定的属性:android:layout_gravity 这个属性的作用是用来指定滑动菜单在屏幕左边还是屏幕右边的,同时也是DrawerLayout用来哪个是判断滑动菜单的。如果在属性中指定left值表示滑动菜单在左边,如果指定right值表示滑动菜单在右边,我们这里指定的start值表示根据系统语言判断滑动菜单所在的位置(像是汉语,英语滑动菜单则在左边。如果是阿拉伯语,则滑动菜单则在右边。一般我们都是指定start值)。
这样,我们的滑动菜单就搞定了,是不是很简单,让我们来看看效果。
。。。。看到这个效果大家是不是很想吐槽一下,且慢,要是效果只是这样Google直接就把它删了- -。让我们接着往下看。假如我们需要的是一个较为复杂的侧滑菜单界面时,怎么办呢?有人可能会说,我们把TextView换成LinearLayout或者RelativeLayout来包裹需要实现的菜单效果不就好了吗?这样当然可以,但是弄起来太复杂了,Google给我们配套了一个控件NavigationView。它是Design Support库中提供的控件,它使得我们要实现复杂的菜单页面变得简单。下面我们来看看如何使用NavigationView。
<android.support.v4.widget.DrawerLayout
android:id="@+id/main_drawer_layout"
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="android.lgt.materialdesigndemo.MainActivity">
********** 这里省略Toolbar的布局代码 **********
<android.support.design.widget.NavigationView
android:id="@+id/main_navigation_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:headerLayout="@layout/navigation_header"
android:layout_gravity="start"
app:menu="@menu/navigation_item"
/>
</android.support.v4.widget.DrawerLayout>
我们看看上面的代码,很明显我们抛弃了TextView,使用了NavigationView。那么NavigationView是怎么让我们实现复杂UI变得简单的呢。我们来看看其中的两个属性,app:headerLayout和app:menu。
1.app:headerLayout:用来指定NavigationView的头部布局。
2.app:menu:用来指定NavigationView中显示的具体菜单项。
这里我们先来看看效果,看看什么是头部布局什么菜单项:
怎么样用NavigationView是不是比TextView的效果要好太多。言归正传,图片中的蓝色部分就是headerLayout所指定的,下面的剩余部分就是菜单项。这样就很明显了。我们再回去看布局文件。看看这两个属性指定的值:
1.app:headerLayout指定的是一个我们自己定义的布局文件navigation_header。
2.app:menu 指定的是一个我们自己定义的menu文件navigation_item。
下面我们先来看看navigation_header的布局文件:
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="250dp"
android:background="@color/colorPrimary">
<ImageView
android:id="@+id/header_image_view"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:src="@drawable/music"/>
<TextView
android:id="@+id/header_text_view"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@id/header_image_view"
android:layout_centerInParent="true"
android:gravity="center"
android:textColor="#fff"
android:text="@string/user_name"/>
</RelativeLayout>
代码如上,很简单就是一个RelativeLayout包裹一个ImageView和一个TextView(这个可以自己定义自己需要的UI效果,只需要在NavigationView中的headerLayout属性中关联一下),布局文件就是那么简单。下面我们来看看navigation_item该怎么写(大家都记得Toolbar中我们特地在res目录下创建的menu文件夹,navigation_item也是创建在这个文件夹下),让我们来看看具体的代码:
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<group
android:checkableBehavior="single">
<item
android:id="@+id/item_home"
android:title="首页"/>
<item
android:id="@+id/item_message"
android:title="消息"/>
<item
android:id="@+id/item_matter"
android:title="事项"/>
</group>
</menu>
从代码我们可以看出,一个item表示一个菜单选项,这里总共有三个,item中是可以使用android:icon属性来指定图标的,这里因为懒得去照图片,所以没有指定,大家可以自己在item中增加android:icon属性来添加图标(图标显示在一条菜单项的最左端)。还需要注意的是item标签外嵌套了一个group标签,里面指定了一个属性:android:checkableBehavior 这里指定的是single,表示这里只能单选,即是只能同时点击一个菜单项。
说到点击,菜单都是可以点击的,那么我们的NavigationView怎么来响应点击事件呢?这就需要我们再Java代码中来定义了,话不多说,上菜~,哦,不。上代码:
public class MainActivity extends AppCompatActivity {
********** 省略Toolbar中定义过的代码 **********
private DrawerLayout mDrawerLayout;
private NavigationView mNavigationView;
private void initView() {
//获取我们需要的控件
mDrawerLayout = findViewById(R.id.main_drawer_layout);
mNavigationView = findViewById(R.id.main_navigation_view);
//这里获取ActionBar来设置滑动菜单的导航图标
ActionBar actionBar = getSupportActionBar();
if (actionBar != null){
//这里设置显示滑动菜单导航图标
actionBar.setDisplayHomeAsUpEnabled(true);
//这句用来设置你要显示的图标,老规矩,这里我没设置了,如果没有设置则显示默认的图标
//actionBar.setHomeAsUpIndicator();
}
//这里设置NavigationView中item被选中的监听
mNavigationView.setNavigationItemSelectedListener(new NavigationView.OnNavigationItemSelectedListener() {
@Override
//重写其中方法,这里只是简单的弹出Toast告诉用户点击的是哪个item,并关闭滑动菜单
public boolean onNavigationItemSelected(@NonNull MenuItem item) {
String itemName = (String) item.getTitle();
Toast.makeText(MainActivity.this,"you click "+itemName,Toast.LENGTH_SHORT).show();
//使用DrawerLayout的方法来关闭滑动菜单
mDrawerLayout.closeDrawers();
return true;
}
});
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()){
//这里同样,通过id来分辨用户点击的按钮是哪一个,需要注意的是滑动菜单的导航按钮的id是固定的就是android.R.id.home,这里省略了Toolbar中其他按钮的点击事件
case android.R.id.home:
//使用DrawerLayout中的方法打开滑动菜单
mDrawerLayout.openDrawer(Gravity.START);
break;
}
return super.onOptionsItemSelected(item);
}
}
代码如上所示,我们增加了滑动菜单的导航图标,防止用户不知道有一个滑动菜单,并且在onOptionsItemSelected中写了点击点航按钮的逻辑,就是打开滑动菜单。同时我们获取到NavigationView的引用并调用setNavigationItemSelectedListener来设置Item的点击事件。
点击事件我们只是简单的弹出Toast并关闭滑动菜单。
ok,以上就是滑动菜单的实现。下次我们将会进入正题,说说TabLayout和ViewPage的嵌套使用实现网易新闻客户端的UI效果。
本人菜鸟,欢迎各路大神指正。