(三十五)沉浸式设计以及兼容
来源:互联网 发布:淘宝高仿男鞋店铺 编辑:程序博客网 时间:2024/05/22 07:43
版权声明:本文为博主原创文章,未经博主允许不得转载。
本文纯个人学习笔记,由于水平有限,难免有所出错,有发现的可以交流一下。
一、沉浸式介绍
沉浸式状态栏
Google 从 Android kitkat(android 4.4) 开始,给我们开发者提供了一套能透明的系统 UI 样式给状态栏和导航栏,这样的话就可以调整状态栏和导航栏跟 Activity 一样的样式,形成一个完整的主题。
优点:
1.这样设计的好处就是用户可以沉浸到设计的 App 中,没有其他因素可以影响到用户。
2.更符合整体设计风格,用户所看到的一屏 包含 App 内容 状态栏 内容区,导航栏。
3.内容区为开发者所控制,导航栏与状态栏 为本身系统拥有,沉浸式设计就是为导航栏和状态栏展开。
沉浸式设计的目的就是让 App 的效果其能够与手机整体的状态融为一体。不会因为看到其他不和谐的因素而影响用户。
现在实现沉浸式设计主要是修改状态栏和导航栏的背景颜色。
平台版本 API 级别 Android7.0 24 N 平台亮点 Android6.0 23 M 平台亮点 Android 5.1 22 LOLLIPOP_MR1 平台亮点 Android 5.0 21 LOLLIPOP Android 4.4W 20 KITKAT_WATCH 仅限 KitKat for Wearables Android 4.4 19 KITKAT 平台亮点 Android 4.3 18 JELLY_BEAN_MR2 平台亮点 Android 4.2、4.2.2 17 JELLY_BEAN_MR1 平台亮点 Android 4.1、4.1.1 16 JELLY_BEAN 平台亮点 Android 4.0.3、4.0.4 15 ICE_CREAM_SANDWICH_MR1 平台亮点 Android 4.0、4.0.1、4.0.2 14 ICE_CREAM_SANDWICH
可以发现,安卓 5.0 以上、安卓 4.4 到 安卓 5.0、安卓 4.4 以下是各不相同的。
1.安卓 5.0 以上
安卓 5.0 以上的版本,要进行状态栏的修改有两种方式。
一种是在 style.xml 中设置主题,通过设置 colorPrimaryDark 可以设置状态栏颜色。
style.xml
<resources> <!-- Base application theme. --> <style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar"> <!-- Customize your theme here. --> <item name="colorPrimary">@color/colorPrimary</item> <!-- 设置状态栏颜色 --> <item name="colorPrimaryDark">@color/colorPrimaryDark</item> <item name="colorAccent">@color/colorAccent</item> </style></resources>
另一种是安卓在 5.0 以上提供了 setStatusBarColor、setNavigationBarColor 方法分别进行状态栏与导航栏颜色设置,方法使用这个要注意添加版本判断。
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP){ //设置状态栏颜色 getWindow().setStatusBarColor(Color.GREEN); //设置导航栏颜色 getWindow().setNavigationBarColor(Color.GREEN); }
注:上面方式虽然很方便,但是只能在 5.0 以上使用。
未设置:
设置后:
2.安卓 4.4 以下
除个别手机厂商对 API 进行修改外,4.4以下是不支持的,所以还是放弃吧。
3.安卓 4.4 到 5.0
在安卓 4.4 上,按 5.0 那要进行主题的设置一样是没有效果的。针对这种情况, 4.4 在 style.xml 中也有对应的属性可以设置。
// 将导航栏编程透明 <item name="android:windowTranslucentNavigation">true</item> //将状态栏设置成透明 <item name="android:windowTranslucentStatus">true</item>
对应的使用代码进行设置的方法:
//必须在 setContentView 之前 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT){ getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS); getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION); }
效果:
但是,这种方式只能设置是否透明。
二、安卓 4.4 到 5.0 的解决方案
1.使用 ToolBar
MainActivity :
public class MainActivity extends AppCompatActivity { Toolbar toolbar; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT){ getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS); getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION); } setContentView(R.layout.activity_main); toolbar = findViewById(R.id.toolbar); toolbar.setTitle("首页"); setSupportActionBar(toolbar); }}
activity_main.xml:
<?xml version="1.0" encoding="utf-8"?><android.support.constraint.ConstraintLayout 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="com.xiaoyue.statusbar.MainActivity"> <android.support.v7.widget.Toolbar android:id="@+id/toolbar" android:background="@color/colorPrimary" android:layout_width="match_parent" android:layout_height="wrap_content"> </android.support.v7.widget.Toolbar></android.support.constraint.ConstraintLayout>
style.xml:
<resources> <!-- Base application theme. --> <style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar"> <!-- Customize your theme here. --> <item name="colorPrimary">@color/colorPrimary</item> <item name="colorPrimaryDark">@color/colorPrimaryDark</item> <item name="colorAccent">@color/colorAccent</item> </style></resources>
效果:
单纯的使用 ToolBar,会让 ToolBar 的高度包括了状态栏的高度(ToolBar 中整体高度变大)。状态栏设为透明的时候,是不占空间的。
2.fitsSystemWindows
在布局文件添加 fitsSystemWindows 属性。
activity_main.xml:
<?xml version="1.0" encoding="utf-8"?><android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:fitsSystemWindows="true" tools:context="com.xiaoyue.statusbar.MainActivity"> <android.support.v7.widget.Toolbar android:id="@+id/toolbar" android:background="@color/colorPrimary" android:layout_width="match_parent" android:layout_height="wrap_content"> </android.support.v7.widget.Toolbar></android.support.constraint.ConstraintLayout>
这个一个 boolean 值的内部属性,让 view 可以根据系统窗口(如 StatusBar)来调整自己的布局,如果值为true,就会调整 view 的 paingding 属性来给 system windows 留出空间。
实际效果:
当 StatusBar 为透明或半透明时(4.4以上),系统会设置 view 的 paddingTop 值为一个适合的值( status bar的高度)让 view 的内容不被上拉到状态栏,当在不占据 StatusBar 的情况下(4.4以下)会设置 paddingTop 值为0(因为没有占据 StatusBar 所以不用留出空间)。
这种处理方式不仅每个布局都要进行这个属性设置,而且在某些情况下会导致布局异常,特别是在使用 ScrollView 的时候。我们可以根据这个思路来换一种解决方式。
3.添加 View
在 ToolBar 上面添加一个状态栏高度的 View。
MainActivity :
public class MainActivity extends BaseActivity { Toolbar toolbar; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); toolbar = findViewById(R.id.toolbar); toolbar.setTitle("首页"); setSupportActionBar(toolbar); View view = findViewById(R.id.nav); setToolBarStyle(toolbar, view, Color.GREEN); }}
把对状态栏的处理写在 BaseActivity 中,这样所有的 Activity 直接继承即可。
BaseActivity :
public class BaseActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT){ getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS); getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION); } } public void setToolBarStyle(Toolbar toolbar, View topView, int styleColor) { // 4.4 到 5.0 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT && Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) { if (toolbar != null) { int statusHeight=getStatusHeight(); Log.i("tuch", " statusHeight " + statusHeight); //第一种方式// ViewGroup.LayoutParams layoutParams = topView.getLayoutParams();// layoutParams.height = statusHeight;// topView.setBackgroundColor(styleColor); //第二种 toolbar.setPadding(0,toolbar.getPaddingTop()+statusHeight,0,0) } //5.0 以上 }else if(Build.VERSION.SDK_INT >=Build.VERSION_CODES.LOLLIPOP) { }else { //没救了 } } /** * 通过反射获取状态栏高度 * @return */ private int getStatusHeight() { int height = -1; try { Class<?> clazz = Class.forName("com.android.internal.R$dimen"); Object object = clazz.newInstance(); String heightStr = clazz.getField("status_bar_height").get(object).toString(); height = Integer.parseInt(heightStr); //dp--px height = getResources().getDimensionPixelSize(height); } catch (ClassNotFoundException e) { e.printStackTrace(); } catch (InstantiationException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } catch (NoSuchFieldException e) { e.printStackTrace(); } return height; }}
这里有两种方式,第一种是在 ToolBar 上方添加一个 View,通过设置 View 来控制状态栏,包括背景颜色(推荐这种方式)。第二种是按 fitsSystemWindows 的原理,添加 Padding。
activity_main.xml:
<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" tools:context="com.xiaoyue.statusbar.MainActivity"> <View android:id="@+id/nav" android:layout_width="match_parent" android:layout_height="1dp"/> <android.support.v7.widget.Toolbar android:id="@+id/toolbar" android:background="@color/colorPrimary" android:layout_width="match_parent" android:layout_height="wrap_content"> </android.support.v7.widget.Toolbar> <TextView android:layout_width="match_parent" android:layout_height="match_parent" android:text="Hello World"/></LinearLayout>
第一种:
第二种:
4.导航栏的处理
导航栏处理思路跟 状态栏一样,不过有些手机是没有导航栏的,直接是物理按键,所以需要先判断是否有导航栏存在。
BaseActivity :
public class BaseActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT){ getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS); getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION); } } public void setToolBarStyle(Toolbar toolbar,View topView, View bottomView, int styleColor) { // 4.4 到 5.0 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT && Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) { if (toolbar != null) { int statusHeight=getStatusHeight(); Log.i("tuch", " statusHeight " + statusHeight); //第一种方式 ViewGroup.LayoutParams layoutParams = topView.getLayoutParams(); layoutParams.height = statusHeight; topView.setBackgroundColor(styleColor); //第二种// toolbar.setPadding(0,toolbar.getPaddingTop()+statusHeight,0,0) //下面的导航栏 if (haveNavgtion()) { ViewGroup.LayoutParams layoutParamsBottom = bottomView.getLayoutParams(); layoutParamsBottom.height = getNavigationHeight(); Log.i("tuch", "getNavigationHeight " + getNavigationHeight()); bottomView.setBackgroundColor(styleColor); } } //5.0 以上 }else if(Build.VERSION.SDK_INT >=Build.VERSION_CODES.LOLLIPOP) { }else { //没救了 } } /** * 通过反射获取状态栏高度 * @return */ private int getStatusHeight() { int height = -1; try { Class<?> clazz = Class.forName("com.android.internal.R$dimen"); Object object = clazz.newInstance(); String heightStr = clazz.getField("status_bar_height").get(object).toString(); height = Integer.parseInt(heightStr); //dp--px height = getResources().getDimensionPixelSize(height); } catch (ClassNotFoundException e) { e.printStackTrace(); } catch (InstantiationException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } catch (NoSuchFieldException e) { e.printStackTrace(); } return height; } /** * 判断是否有导航栏(API 17 以后才可以) * @return */ @RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN_MR1) private boolean haveNavgtion() { //屏幕的高度,真实物理的屏幕 Display display = getWindowManager().getDefaultDisplay(); DisplayMetrics displayMetrics = new DisplayMetrics(); display.getRealMetrics(displayMetrics); int heightDisplay = displayMetrics.heightPixels; //为了防止横屏 int widthDisplay = displayMetrics.widthPixels; //显示内容的高度 DisplayMetrics contentDisplaymetrics = new DisplayMetrics(); display.getMetrics(contentDisplaymetrics); int contentDisplay = contentDisplaymetrics.heightPixels; int contentDisplayWidth = contentDisplaymetrics.widthPixels; //屏幕内容高度 显示内容的屏幕 int w = widthDisplay - contentDisplayWidth; //哪一方大于0 就有导航栏 int h = heightDisplay - contentDisplay; return w>0||h>0; } private int getNavigationHeight() { int height=-1; try { Class<?> clazz=Class.forName("com.android.internal.R$dimen"); Object object=clazz.newInstance(); String heightStr=clazz.getField("navigation_bar_height").get(object).toString(); height = Integer.parseInt(heightStr); //dp--px height = getResources().getDimensionPixelSize(height); } catch (ClassNotFoundException e) { e.printStackTrace(); } catch (InstantiationException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } catch (NoSuchFieldException e) { e.printStackTrace(); } return height; }}
activity_main.xml:
<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" tools:context="com.xiaoyue.statusbar.MainActivity"> <View android:id="@+id/nav" android:layout_width="match_parent" android:layout_height="1dp"/> <android.support.v7.widget.Toolbar android:id="@+id/toolbar" android:background="@color/colorPrimary" android:layout_width="match_parent" android:layout_height="wrap_content"> </android.support.v7.widget.Toolbar> <TextView android:layout_width="match_parent" android:layout_height="0dp" android:layout_weight="1" android:text="Hello World"/> <View android:id="@+id/bottom" android:layout_gravity="bottom" android:layout_width="match_parent" android:layout_height="1dp"/></LinearLayout>
效果:
- (三十五)沉浸式设计以及兼容
- Android 沉浸式设计兼容基础类
- 实现状态栏全沉浸以及兼容低版本半透明沉浸
- 沉浸式状态栏上下兼容
- Android 沉浸式状态栏设计以及ContentView获取
- MaterialDesign-沉浸式设计
- 沉浸式设计
- ToolBar沉浸式状态栏的兼容实现
- 如何动态兼容沉浸式状态栏模式
- Android沉浸式状态栏设计
- android状态栏一体化、沉浸式状态栏(兼容低版本)
- android状态栏一体化、沉浸式状态栏(兼容低版本)
- android状态栏一体化、沉浸式状态栏(兼容低版本)
- Android沉浸式状态栏兼容4.4手机的实现
- 沉浸式状态栏的实现和版本兼容
- android状态栏一体化、沉浸式状态栏(兼容低版本)
- android状态栏一体化、沉浸式状态栏(兼容低版本)
- android沉浸式状态栏兼容4.4-5.0均有效
- 从零开始:在树莓派上构建tensorflow——详细至极
- 我的学习记录47
- leetcode解题方案--048--Rotate Image
- Mycat 安装
- 纯干货,Spring-data-jpa详解,全方位介绍。
- (三十五)沉浸式设计以及兼容
- java多线程(5)死锁
- Jdbc连接数据库(JDBC读取propertites属性文件)
- myeclipse2017CI的SVNE170001错误
- 3D打印技术与应用
- ML--SVM学习小结(一)
- 一起Talk Android吧(第五十二回:Android中的Fragment交互续)
- 【java】--后台实现打印
- JavaScript 谷歌地图demo