学习目的
- 学会使用
DrawerLayout
- 学会使用
NavigationView
- 学会使用ToolBar+DrawerLayout+NavigationView实现侧滑抽屉效果
- 学会实现Toolbar在顶部以及Toolbar被遮挡的两种效果
效果展示
侧滑控件我们在开发的过程中经常用到,废话不多说,先上图:
实现过程
如果要实现上图的展示效果,需要先创建个BaseActivit类,这个类里面包含Toolbar的初始化,然后再创建DrawerLayout相关的Activity
创建BaseActivity及相关XML文件
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32
| <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical">
<LinearLayout android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical">
<android.support.v7.widget.Toolbar android:id="@+id/toolbar" android:layout_width="match_parent" android:layout_height="wrap_content" android:background="@color/colorPrimary" app:contentInsetStartWithNavigation="0dp" android:theme="@style/ToolBarStyle" app:titleTextColor="@color/white">
</android.support.v7.widget.Toolbar>
<FrameLayout android:id="@+id/frameLayout" android:layout_width="match_parent" android:layout_height="match_parent">
</FrameLayout> </LinearLayout>
</LinearLayout>
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79
| package com.vv.drawerlayout.ui.base;
import android.os.Bundle; import android.support.annotation.Nullable; import android.support.v7.app.AppCompatActivity; import android.support.v7.widget.Toolbar; import android.view.LayoutInflater; import android.view.View; import android.widget.FrameLayout;
import com.vv.drawerlayout.R;
import butterknife.ButterKnife;
public abstract class BaseActivity extends AppCompatActivity { protected Toolbar mToolbar; protected FrameLayout mContainerLayout;
@Override protected void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_base);
mToolbar = findViewById(R.id.toolbar); mContainerLayout = findViewById(R.id.frameLayout); boolean isToobar = initToolbar(); if (isToobar) { setSupportActionBar(mToolbar); getSupportActionBar().setDisplayHomeAsUpEnabled(true); mToolbar.setNavigationOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { onNavigationClick(); } }); } else { mToolbar.setVisibility(View.GONE); }
initContent(getLayoutId()); }
private void initContent(int layoutId) { if (layoutId != 0) { View contentView = LayoutInflater.from(this).inflate(layoutId, mContainerLayout, false); mContainerLayout.addView(contentView); ButterKnife.bind(this); initViews(); } }
protected abstract void initViews();
protected abstract int getLayoutId();
private void onNavigationClick() { finish(); }
protected abstract boolean initToolbar(); }
|
创建DrawerLayout相关的Activity以及相关的XML文件
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| <?xml version="1.0" encoding="utf-8"?> <android.support.v4.widget.DrawerLayout 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:id="@+id/drawer_layout" android:layout_width="match_parent" android:layout_height="match_parent" tools:context=".ui.MainActivity">
<android.support.design.widget.NavigationView android:layout_width="match_parent" android:layout_height="match_parent" android:id="@+id/navigation_view" android:layout_gravity="left|start" app:headerLayout="@layout/header_layout" app:menu="@menu/navigation_menu">
</android.support.design.widget.NavigationView>
</android.support.v4.widget.DrawerLayout>
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| <?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="200dp" android:gravity="center" android:background="@color/_0091ea" android:orientation="vertical" > <ImageView android:id="@+id/img_avatar" android:layout_width="wrap_content" android:layout_height="wrap_content" android:src="@mipmap/ic_launcher_round" />
<TextView android:id="@+id/tv_name" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginTop="10dp" android:textColor="@color/white" android:text="" />
</LinearLayout>
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| <?xml version="1.0" encoding="utf-8"?> <menu xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto">
<item android:id="@+id/menu_favorite_article" android:icon="@drawable/ic_favorite_gray_24dp" android:title="@string/favorite_article" app:showAsAction="ifRoom" /> <item android:id="@+id/menu_about" android:icon="@drawable/ic_about_us_gray_24dp" android:title="@string/about_us" app:showAsAction="ifRoom" /> <item android:id="@+id/menu_exit" android:icon="@drawable/ic_exit_to_app_gray_24dp" android:title="@string/exit" app:showAsAction="ifRoom" />
</menu>
|
- 如果使用Toolbar,那么需要把系统的主题换成没有ActionBar的主题,修改
style.xml
文件
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| <resources>
<style name="AppTheme.Base" parent="Theme.AppCompat.Light.NoActionBar"> <item name="colorPrimary">@color/colorPrimary</item> <item name="colorPrimaryDark">@color/colorPrimaryDark</item> <item name="colorAccent">@color/colorAccent</item> </style>
<style name="AppTheme" parent="AppTheme.Base"></style>
<style name="ToolBarStyle" parent="@style/BaseToolBarStyle"></style>
</resources>
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61
| package com.vv.drawerlayout.ui;
import android.os.Bundle; import android.support.annotation.NonNull; import android.support.design.widget.NavigationView; import android.support.v4.widget.DrawerLayout; import android.support.v7.app.ActionBarDrawerToggle; import android.view.MenuItem;
import com.vv.drawerlayout.R; import com.vv.drawerlayout.ui.base.BaseActivity;
import butterknife.Bind;
public class MainActivity extends BaseActivity {
@Bind(R.id.navigation_view) NavigationView mNavigationView; @Bind(R.id.drawer_layout) DrawerLayout mDrawerLayout;
@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState);
ActionBarDrawerToggle mToggle = new ActionBarDrawerToggle(this,mDrawerLayout,mToolbar, R.string.navigation_drawer_open, R.string.navigation_drawer_close); mToggle.syncState(); mDrawerLayout.addDrawerListener(mToggle); mNavigationView.setItemIconTintList(null); mNavigationView.setNavigationItemSelectedListener(new NavigationView.OnNavigationItemSelectedListener() { @Override public boolean onNavigationItemSelected(@NonNull MenuItem item) { return false; } }); }
@Override protected void initViews() {
}
@Override protected int getLayoutId() { return R.layout.activity_main; }
@Override protected boolean initToolbar() { mToolbar.setTitle(R.string.home); mToolbar.setNavigationIcon(R.drawable.ic_menu_black_24dp); return true; }
}
|
优化
但是现在我们发现侧边栏是没有选中状态的,如效果图所示,
我们怎么才能是左边的导航栏有选择状态呢?
给左边的导航栏加上选中效果
- 首先在布局文件中,
NavigationView
的控件的meun
中注明一个behavior
1 2 3 4 5 6 7
| <group android:checkableBehavior="single"> <item android:title="@string/home">
</item> </group>
|
1
| android:checkableBehavior="single"
|
表示每一项都是单选,如果不标明的话,NavigationView不会有选中效果.
1
| mNavigationView.setNavigationItemSelectedListener(onNavigationItemSelectedListener);
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| NavigationView.OnNavigationItemSelectedListener onNavigationItemSelectedListener = new NavigationView.OnNavigationItemSelectedListener() { @Override public boolean onNavigationItemSelected(@NonNull MenuItem item) { switch (item.getItemId()) { case R.id.menu_favorite_article: break; case R.id.menu_about: break; case R.id.menu_exit: break; case R.id.menu_home: break; default: break; } mDrawerLayout.closeDrawers(); return true; } };
|
改变图标的颜色
我们给刚刚增加的NavigationView
的控件的meun
的Item增加一个icon
1 2 3 4 5 6 7 8 9
| <group android:checkableBehavior="single"> <item android:id="@+id/menu_home" android:icon="@mipmap/ic_launcher" android:title="@string/home">
</item> </group>
|
ok看下现在的效果:
5我们发现首页
旁边的图标变成了黑色.这并不是我们想要的.
我们怎么去更改Icon的颜色呢,有两种方法:
- 在NavigationView的布局xml文件里增加
app:itemIconTint="@color/xxx"
属性,可以设置Icon的图片颜色为统一的一种颜色
activity_main.xml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| <?xml version="1.0" encoding="utf-8"?> <android.support.v4.widget.DrawerLayout 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:id="@+id/drawer_layout" android:layout_width="match_parent" android:layout_height="match_parent" tools:context=".ui.MainActivity">
<android.support.design.widget.NavigationView android:layout_width="match_parent" android:layout_height="match_parent" android:id="@+id/navigation_view" android:layout_gravity="left|start" app:headerLayout="@layout/header_layout" app:menu="@menu/navigation_menu" app:itemIconTint="@color/_0091ea">
</android.support.design.widget.NavigationView>
</android.support.v4.widget.DrawerLayout>
|
运行效果如下:
我们可以看到所有的Icon的图片颜色全部换成了统一的蓝色.但是首页旁边的Icon仍不是我们想要的图标颜色.这就得需要第二种方法了.
- 我们如果想让Icon显示本省的颜色,就得在java文件里面调用以下方法:
1
| mNavigationView.setItemIconTintList(null);
|
MainActivity
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77
| package com.vv.drawerlayout.ui;
import android.os.Bundle; import android.support.annotation.NonNull; import android.support.design.widget.NavigationView; import android.support.v4.widget.DrawerLayout; import android.support.v7.app.ActionBarDrawerToggle; import android.view.MenuItem;
import com.vv.drawerlayout.R; import com.vv.drawerlayout.ui.base.BaseActivity;
import butterknife.Bind;
public class MainActivity extends BaseActivity {
@Bind(R.id.navigation_view) NavigationView mNavigationView; @Bind(R.id.drawer_layout) DrawerLayout mDrawerLayout;
@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState);
ActionBarDrawerToggle mToggle = new ActionBarDrawerToggle(this,mDrawerLayout,mToolbar, R.string.navigation_drawer_open, R.string.navigation_drawer_close); mToggle.syncState(); mDrawerLayout.addDrawerListener(mToggle); mNavigationView.setItemIconTintList(null); mNavigationView.setNavigationItemSelectedListener(onNavigationItemSelectedListener); }
@Override protected void initViews() {
}
@Override protected int getLayoutId() { return R.layout.activity_main; }
@Override protected boolean initToolbar() { mToolbar.setTitle(R.string.home); mToolbar.setNavigationIcon(R.drawable.ic_menu_black_24dp); return true; }
NavigationView.OnNavigationItemSelectedListener onNavigationItemSelectedListener = new NavigationView.OnNavigationItemSelectedListener() { @Override public boolean onNavigationItemSelected(@NonNull MenuItem item) { switch (item.getItemId()) { case R.id.menu_favorite_article: break; case R.id.menu_about: break; case R.id.menu_exit: break; case R.id.menu_home: break; default: break; } mDrawerLayout.closeDrawers(); return true; } };
}
|
运行效果:
可以看到,这个效果就是我们想要的~
改变Item的背景,改变Item的TextColor
- 如果要改变Item的背景,我们需要用到
NavigationView
的.app:itemBackground=""
方法
- 如果要改变Item的TextColor,我们需要用到
NavigationView
的app:itemTextColor=""
方法
activity_main.xml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| <?xml version="1.0" encoding="utf-8"?> <android.support.v4.widget.DrawerLayout 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:id="@+id/drawer_layout" android:layout_width="match_parent" android:layout_height="match_parent" tools:context=".ui.MainActivity">
<android.support.design.widget.NavigationView android:layout_width="match_parent" android:layout_height="match_parent" android:id="@+id/navigation_view" android:layout_gravity="left|start" app:headerLayout="@layout/header_layout" app:menu="@menu/navigation_menu" app:itemBackground="@color/_0091ea" app:itemTextColor="@color/white" app:itemIconTint="@color/_0091ea">
</android.support.design.widget.NavigationView>
</android.support.v4.widget.DrawerLayout>
|
效果如下:
给Item之间增加分割线
我们只需要在以上基础上增加一个group_id即可.即:讲menu先放入到group组中,然后再给这个group赋上id的值,就能实现分割线效果.
navigation_menu.xml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36
| <?xml version="1.0" encoding="utf-8"?> <menu xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" >
<item android:id="@+id/menu_favorite_article" android:icon="@drawable/ic_favorite_gray_24dp" android:title="@string/favorite_article" app:showAsAction="ifRoom" app:itemIconTint="@color/_0091ea"/> <item android:id="@+id/menu_about" android:icon="@drawable/ic_about_us_gray_24dp" android:title="@string/about_us" app:showAsAction="ifRoom" /> <item android:id="@+id/menu_exit" android:icon="@drawable/ic_exit_to_app_gray_24dp" android:title="@string/exit" app:showAsAction="ifRoom" />
<group android:id="@+id/group_home" android:checkableBehavior="single" > <item android:id="@+id/menu_home" android:icon="@mipmap/ic_launcher_round"
android:title="@string/home">
</item> </group> </menu>
|
运行效果
我们常见的应用,像网易云音乐,QQ等都是Toolbar被遮挡的侧滑效果.
我们实现这种效果就得让DrawerLayout
包含在Toolbar
外面
activity_drawer_layout.xml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54
| <?xml version="1.0" encoding="utf-8"?> <android.support.v4.widget.DrawerLayout 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:id="@+id/drawer_layout" android:layout_width="match_parent" android:layout_height="match_parent" android:fitsSystemWindows="true">
<LinearLayout android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical"> <android.support.design.widget.AppBarLayout android:id="@+id/appBarLayout" android:layout_width="match_parent" android:layout_height="wrap_content" android:theme="@style/AppTheme.AppBarOverlay">
<android.support.v7.widget.Toolbar android:id="@+id/toolbar" android:layout_width="match_parent" android:layout_height="?attr/actionBarSize" android:background="?attr/colorPrimary" app:popupTheme="@style/AppTheme.PopupOverlay" />
</android.support.design.widget.AppBarLayout>
<LinearLayout android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical"> <TextView android:layout_width="match_parent" android:layout_height="match_parent" android:text="@string/home" android:gravity="center"/> </LinearLayout>
</LinearLayout>
<android.support.design.widget.NavigationView android:id="@+id/navigation_view" android:layout_width="wrap_content" android:layout_height="match_parent" android:layout_gravity="start" android:fitsSystemWindows="true" app:headerLayout="@layout/header_layout" app:itemIconTint="@color/colorAccent" app:menu="@menu/navigation_menu">
</android.support.design.widget.NavigationView> </android.support.v4.widget.DrawerLayout>
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71
| package com.vv.drawerlayout.ui;
import android.os.Bundle; import android.support.annotation.NonNull; import android.support.annotation.Nullable; import android.support.design.widget.NavigationView; import android.support.v4.widget.DrawerLayout; import android.support.v7.app.ActionBarDrawerToggle; import android.support.v7.app.AppCompatActivity; import android.support.v7.widget.Toolbar; import android.view.MenuItem;
import com.vv.drawerlayout.R;
import butterknife.Bind; import butterknife.ButterKnife;
public class DrawerLayoutActivity extends AppCompatActivity { @Bind(R.id.toolbar) Toolbar mToolbar; @Bind(R.id.navigation_view) NavigationView mNavigationView; @Bind(R.id.drawer_layout) DrawerLayout mDrawerLayout;
private ActionBarDrawerToggle mToggle;
@Override protected void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_drawer_layout); ButterKnife.bind(this); setToolbar();
setDrawerToggle();
setListener(); }
private void setListener() { mNavigationView.setNavigationItemSelectedListener(new NavigationView.OnNavigationItemSelectedListener() { @Override public boolean onNavigationItemSelected(@NonNull MenuItem item) { mDrawerLayout.closeDrawers(); return true; } }); }
private void setDrawerToggle() { mToggle=new ActionBarDrawerToggle(this,mDrawerLayout,mToolbar, R.string.navigation_drawer_open, R.string.navigation_drawer_close); mDrawerLayout.addDrawerListener(mToggle); mToggle.syncState(); }
private void setToolbar() { setSupportActionBar(mToolbar); getSupportActionBar().setDisplayHomeAsUpEnabled(true); } }
|
注意:
setSupportActionBar(mToolbar);
一定要写在mDrawerLayout.addDrawerListener(mToggle);
之前,否则将无法响应Home页面上的Icon点击事件.
运行效果:
代码
为了方便,代码已经上传GitHub,敬请下载~