前言
Google最新推出规范式设计中的NavigationView和DrawerLayout结合实现侧滑菜单效果,NavigationView是android-support-design包下的一个控件,NavigationView是为规范侧滑菜单样式而生,侧滑作为常见的导航交互控件,最开始在没有android官方控件的时候,很多时候都是使用开源的SlidingMenu,现在使用DrawerLayout可以轻松使用抽屉的效果。
Part 1、侧滑DrawerLayout控件应用
DrawerLayout经常和ToolBar和Toggle结合使用,布局文件如下
<RelativeLayout
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">
<android.support.v7.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?android:attr/actionBarSize">
</android.support.v7.widget.Toolbar>
<android.support.v4.widget.DrawerLayout
android:id="@+id/mDrawerLayout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_below="@+id/toolbar">
<FrameLayout
android:id="@+id/content"
android:layout_width="match_parent"
android:layout_height="match_parent">
<android.support.v7.widget.RecyclerView
android:id="@+id/rv"
android:layout_width="match_parent"
android:layout_height="match_parent">
</android.support.v7.widget.RecyclerView>
</FrameLayout>
<FrameLayout
android:id="@+id/menu"
android:layout_width="200dp"
android:layout_height="match_parent"
android:layout_gravity="start"
android:background="#A3CCDF">
<android.support.v7.widget.LinearLayoutCompat
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
app:divider="@drawable/divider_vertical_holo_light"
app:showDividers="middle">
......
</android.support.v7.widget.LinearLayoutCompat>
</FrameLayout>
</android.support.v4.widget.DrawerLayout>
</RelativeLayout>
代码实现也很简单,就直接贴出来了
mToolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(mToolbar);
mDrawerLayout = (DrawerLayout) findViewById(R.id.mDrawerLayout);
ActionBarDrawerToggle toggle = new ActionBarDrawerToggle(this, mDrawerLayout,mToolbar, R.string.open, R.string.close);
//同步状态
toggle.syncState();
//给侧滑控件设置监听
mDrawerLayout.addDrawerListener(toggle);
效果~
tips:
1、使用ToolBar要在主题添加
<item name="windowActionBar">false</item>
<item name="windowNoTitle">true</item>
2、ActionBarDrawerToggle类其实就是控制DrawerArrowDrawable类的绘制,而DrawerArrowDrawable其实就是一个自定义Drawable
public class DrawerArrowDrawable extends Drawable {
绘制过程在该类的onDraw方法里面,对于相应的变化值是
/**
* Set the progress of the arrow.
*
* <p>A value of {@code 0.0} indicates that the arrow should be drawn in it's starting
* position. A value of {@code 1.0} indicates that the arrow should be drawn in it's ending
* position.</p>
*/
public void setProgress(@FloatRange(from = 0.0, to = 1.0) float progress) {
if (mProgress != progress) {
mProgress = progress;
invalidateSelf();
}
}
通过DrawArrowDrawable类的,ActionBarDrawerToggle通过不断调用此方法实现动画效果的。
这里我们可以自定义一个Drawable继承DrawArrowDrawable,在onDraw实现自己的动画效果,这里自己实现了简易的动画
效果~
这样就实现了自己的动画~
Part 2、实现DrawerLayout的监听
mDrawerLayout.addDrawerListener(new DrawerLayout.DrawerListener() {
@Override
public void onDrawerSlide(View drawerView, float slideOffset) {
}
@Override
public void onDrawerOpened(View drawerView) {
// 打开
}
@Override
public void onDrawerClosed(View drawerView) {
// 关闭
}
@Override
public void onDrawerStateChanged(int newState) {
// 状态发生改变
}
});
只需要在onDrawerSlide方法里面进行动画即可,slideOffset从0-1
// 滑动的过程当中不断地回调 slideOffset:0~1
View content = mDrawerLayout.getChildAt(0);
View menu = drawerView;
float scale = 1-slideOffset;//1~0
float leftScale = (float) (1-0.3*scale);
float rightScale = (float) (0.7f+0.3*scale);
menu.setScaleX(leftScale);//0.7 ~ 1.0
menu.setScaleY(leftScale);//0.7 ~ 1.0
content.setScaleX(rightScale);
content.setScaleY(rightScale);
content.setTranslationX(menu.getMeasuredWidth()*(1-scale));//0~width
效果~
Part 3、NavigationView为规范侧滑标准而来
由于侧滑的样式各种各样,Google为了统一侧滑的标准提供了NavigationView控件
<!-- 菜单部分 -->
<android.support.design.widget.NavigationView
android:layout_width="wrap_content"
android:layout_height="fill_parent"
android:layout_gravity="start"
app:headerLayout="@layout/navigation_headerlayout"
app:menu="@menu/navigation_menu"
/>
效果~
使用NavigationView实现的效果要美观的多,但是由于使用到了Menu,要处理各个MenuItem边距就不是很容易了,没有DrawerLayout内部用FrameLayout实现扩展性好。
为NavigationView的Menu增加监听事件
navigationview.setNavigationItemSelectedListener(new NavigationView.OnNavigationItemSelectedListener() {
@Override
public boolean onNavigationItemSelected(@NonNull MenuItem item) {
return false;
}
});