DrawerLayout 在 Android 4.4 和 Android 5.0 以上实现沉浸状态栏和导航栏的方法
2017-03-15 21:03
681 查看
DrawerLayout 在实现沉浸状态栏的方法相对复杂,尤其在 Android 4.4 和 Android 5.0 以上的实现方法区别很大,本人在通过一段时间的研究,总结出比较完美的实现方法,现在这里分享。
首先需要针对 Android 5.0 以上和一下设置不同的 style,如图所示:
style的内容分别是:
value:
value-v21:
可以看出,v21 以上的 style 中的 AppTheme 多了一个 android:navigationBarColor 属性,该属性是设置状态栏颜色用的,是 android 5.0 新增加的属性,这里为了保持导航栏和状态栏的颜色一致,我们把它的颜色设置为和状态栏颜色一致,即 colorPrimaryDark 。
接下来写布局文件:
activity_drawer:
app_bar_drawer:
content_drawer:
这里有几点需要注意:
1、app_bar_drawer 的最外层布局必须设置 android:fitsSystemWindows="true" ,否则 ToolBar 会被顶到状态栏的位置;
2、由于 app_bar_drawer 的最外层布局为 CoordinatorLayout ,因而 content_drawer 的最外层布局必须设置 app:layout_behavior="@string/appbar_scrolling_view_behavior" 属性,否则 content_drawer 中的内容会被顶到 ToolBar 的位置。
最后就是 Activity 中的代码了:
分析一下上面的代码,沉浸状态栏和导航栏主要靠 immersionBar() 方法实现的,该方法接收一个 int 类型的参数,用来设置状态栏和导航栏的颜色,然后需要根据系统版本分两种情况,即 Android 5.0 以上和 Android 4.4,Android 4.4 以下,由于不支持透明状态栏和导航栏,这里不做讨论。
在 Android 4.4 上,首先设置透明状态栏和导航栏,然后分别在状态栏和导航栏的位置添加一个 View 用于设置颜色,而在 Android 5.0 以上,由于系统默认已经给 DrawerLayout 设置了透明状态栏,为了让抽屉能够显示在状态栏和导航栏上,我们需要把状态栏和导航栏的颜色设置为透明,此时,状态栏会默认使用 ToolBar 的颜色,不需要再手动设置,但是导航栏还是透明的,因此,我们同样需要在导航栏的位置添加一个‘ View 用于设置导航栏的颜色,这样,沉浸状态栏和导航栏就设置成功了。
最后看一下在 Android 4.4 和 Android 5.0 以上手机上的运行效果:
Android 4.4:
Android 5.0 以上:
首先需要针对 Android 5.0 以上和一下设置不同的 style,如图所示:
style的内容分别是:
value:
<resources> <style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar"> <item name="colorPrimary">@color/colorPrimary</item> <item name="colorPrimaryDark">@color/colorPrimary</item> <item name="colorAccent">@color/colorAccent</item> </style> <style name="AppTheme.AppBarOverlay" parent="ThemeOverlay.AppCompat.Dark.ActionBar" /> <style name="AppTheme.PopupOverlay" parent="ThemeOverlay.AppCompat.Light" /> </resources>
value-v21:
<resources> <style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar"> <item name="colorPrimary">@color/colorPrimary</item> <item name="colorPrimaryDark">@color/colorPrimary</item> <item name="colorAccent">@color/colorAccent</item> <item name="android:navigationBarColor">@color/colorPrimaryDark</item> </style> <style name="AppTheme.AppBarOverlay" parent="ThemeOverlay.AppCompat.Dark.ActionBar" /> <style name="AppTheme.PopupOverlay" parent="ThemeOverlay.AppCompat.Light" /> </resources>
可以看出,v21 以上的 style 中的 AppTheme 多了一个 android:navigationBarColor 属性,该属性是设置状态栏颜色用的,是 android 5.0 新增加的属性,这里为了保持导航栏和状态栏的颜色一致,我们把它的颜色设置为和状态栏颜色一致,即 colorPrimaryDark 。
接下来写布局文件:
activity_drawer:
<?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:openDrawer="start"> <include layout="@layout/app_bar_drawer"/> <FrameLayout android:layout_width="match_parent" android:layout_height="match_parent" android:background="@drawable/side_nav_bar" android:layout_gravity="start"> </FrameLayout> </android.support.v4.widget.DrawerLayout>
app_bar_drawer:
<?xml version="1.0" encoding="utf-8"?> <android.support.design.widget.CoordinatorLayout 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:fitsSystemWindows="true" tools:context="com.example.ivy.myapplication.DrawerLayout.DrawerActivity"> <android.support.design.widget.AppBarLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:theme="@style/AppTheme.AppBarOverlay" app:elevation="0dp"> <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> <include layout="@layout/content_drawer" /> <android.support.design.widget.FloatingActionButton android:id="@+id/fab" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="bottom|end" android:layout_margin="@dimen/fab_margin" app:srcCompat="@android:drawable/ic_dialog_email" /> </android.support.design.widget.CoordinatorLayout>
content_drawer:
<?xml version="1.0" encoding="utf-8"?> <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:id="@+id/content_drawer" android:layout_width="match_parent" android:layout_height="match_parent" android:paddingBottom="@dimen/activity_vertical_margin" android:paddingLeft="@dimen/activity_horizontal_margin" android:paddingRight="@dimen/activity_horizontal_margin" android:paddingTop="@dimen/activity_vertical_margin" app:layout_behavior="@string/appbar_scrolling_view_behavior" tools:context="com.example.ivy.myapplication.DrawerLayout.DrawerActivity" tools:showIn="@layout/app_bar_drawer"> </RelativeLayout>
这里有几点需要注意:
1、app_bar_drawer 的最外层布局必须设置 android:fitsSystemWindows="true" ,否则 ToolBar 会被顶到状态栏的位置;
2、由于 app_bar_drawer 的最外层布局为 CoordinatorLayout ,因而 content_drawer 的最外层布局必须设置 app:layout_behavior="@string/appbar_scrolling_view_behavior" 属性,否则 content_drawer 中的内容会被顶到 ToolBar 的位置。
最后就是 Activity 中的代码了:
public class DrawerActivity extends AppCompatActivity implements NavigationView.OnNavigationItemSelectedListener { private static final String TAG = "DrawerActivity"; public static Intent newIntent(Context context) { return new Intent(context, DrawerActivity.class); } @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_drawer); immersionBar(ContextCompat.getColor(this, R.color.colorPrimaryDark)); Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar); setSupportActionBar(toolbar); FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab); fab.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { Snackbar.make(view, "Replace with your own action", Snackbar.LENGTH_LONG) .setAction("Action", null).show(); } }); DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout); ActionBarDrawerToggle toggle = new ActionBarDrawerToggle( this, drawer, toolbar, R.string.navigation_drawer_open, R.string.navigation_drawer_close); drawer.setDrawerListener(toggle); toggle.syncState(); } //沉浸状态栏和导航栏 @TargetApi(19) private void immersionBar(int color) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { Window window = getWindow(); ViewGroup decorView = (ViewGroup) window.getDecorView(); int option = View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN | View.SYSTEM_UI_FLAG_LAYOUT_STABLE; decorView.setSystemUiVisibility(option); window.setNavigationBarColor(Color.TRANSPARENT); window.setStatusBarColor(Color.TRANSPARENT); decorView.addView(createBarView(getNavigationBarHeight(), color, Gravity.BOTTOM), 0); } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { Window window = getWindow(); window.addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS); window.addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION); ViewGroup decorView = (ViewGroup) window.getDecorView(); decorView.addView(createBarView(getStatusBarHeight(), color, Gravity.TOP), 0); decorView.addView(createBarView(getNavigationBarHeight(), color, Gravity.BOTTOM), 1); } } //创建一个View,用于设置状态栏或导航栏的颜色 private View createBarView(int height, int color, int gravity) { View view = new View(this); view.setBackgroundColor(color); FrameLayout.LayoutParams params = new FrameLayout.LayoutParams (ViewGroup.LayoutParams.MATCH_PARENT, height, gravity); view.setLayoutParams(params); return view; } //获取状态栏高度 private int getStatusBarHeight(){ int statusBarHeight = 0; int resourceId = getResources().getIdentifier("status_bar_height", "dimen", "android"); if (resourceId > 0) { statusBarHeight = getResources().getDimensionPixelSize(resourceId); } return statusBarHeight; } //获取导航栏高度 private int getNavigationBarHeight() { int navigationBarHeight = 0; int resourceId = getResources().getIdentifier("navigation_bar_height", "dimen", "android"); if (resourceId > 0) { navigationBarHeight = getResources().getDimensionPixelOffset(resourceId); } return navigationBarHeight; } @Override public void onBackPressed() { DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout); if (drawer.isDrawerOpen(GravityCompat.START)) { drawer.closeDrawer(GravityCompat.START); } else { super.onBackPressed(); } } @Override public boolean onCreateOptionsMenu(Menu menu) { // Inflate the menu; this adds items to the action bar if it is present. getMenuInflater().inflate(R.menu.drawer, menu); return true; } @Override public boolean onOptionsItemSelected(MenuItem item) { // Handle action bar item clicks here. The action bar will // automatically handle clicks on the Home/Up button, so long // as you specify a parent activity in AndroidManifest.xml. int id = item.getItemId(); //noinspection SimplifiableIfStatement if (id == R.id.action_settings) { return true; } return super.onOptionsItemSelected(item); } @SuppressWarnings("StatementWithEmptyBody") @Override public boolean onNavigationItemSelected(MenuItem item) { // Handle navigation view item clicks here. int id = item.getItemId(); if (id == R.id.nav_camera) { // Handle the camera action } else if (id == R.id.nav_gallery) { } else if (id == R.id.nav_slideshow) { } else if (id == R.id.nav_manage) { } else if (id == R.id.nav_share) { } else if (id == R.id.nav_send) { } DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout); drawer.closeDrawer(GravityCompat.START); return true; } }
分析一下上面的代码,沉浸状态栏和导航栏主要靠 immersionBar() 方法实现的,该方法接收一个 int 类型的参数,用来设置状态栏和导航栏的颜色,然后需要根据系统版本分两种情况,即 Android 5.0 以上和 Android 4.4,Android 4.4 以下,由于不支持透明状态栏和导航栏,这里不做讨论。
在 Android 4.4 上,首先设置透明状态栏和导航栏,然后分别在状态栏和导航栏的位置添加一个 View 用于设置颜色,而在 Android 5.0 以上,由于系统默认已经给 DrawerLayout 设置了透明状态栏,为了让抽屉能够显示在状态栏和导航栏上,我们需要把状态栏和导航栏的颜色设置为透明,此时,状态栏会默认使用 ToolBar 的颜色,不需要再手动设置,但是导航栏还是透明的,因此,我们同样需要在导航栏的位置添加一个‘ View 用于设置导航栏的颜色,这样,沉浸状态栏和导航栏就设置成功了。
最后看一下在 Android 4.4 和 Android 5.0 以上手机上的运行效果:
Android 4.4:
Android 5.0 以上:
相关文章推荐
- Android 4.4 以上实现透明导航栏和状态栏 Translucent system bar
- Android 4.4 以上分分钟实现状态栏伪沉浸(状态栏透明)
- Android沉浸状态栏的实现,支持4.4以上
- Android沉浸状态栏的实现,支持4.4以上
- Android 4.4以上"沉浸式"状态栏效果的实现方法
- Android4.4系统以上实现沉浸式状态栏
- Android 5.0及以上编程实现屏幕截图功能的方法
- Android之4.4版本以上沉浸式状态栏实现
- Android 4.4 上实现透明导航栏和状态栏 Translucent system bar
- android 4.4以上可以实现的沉浸式状态栏效果
- Android DrawerLayout+ToolBar+NavigationView实现侧滑菜单效果,沉浸式状态栏
- android 4.4版本以上透明状态栏的简单实现
- Android 4.4 上实现透明导航栏和状态栏 Translucent system bar
- android开发(50) Android透明状态栏。适用于 4.4 以上及 5.0以上设备
- 两句话,实现android 4.4以上实现沉浸式状态栏
- coordinatelayout android:fitsSystemWindows 沉浸式状态栏在android4.4 和 4.4以上版本的坑
- Android沉浸式状态栏的实现在4.4及以上的系统中
- API 19即android4.4以上,设置一体化状态栏背景颜色的方法
- Android实战之 4.4版本及以上透明状态栏,兼容5.0及以上
- 沉浸状态栏的实现(5.0以上方案)