欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  移动技术

分别用ToolBar和自定义导航栏实现沉浸式状态栏

程序员文章站 2024-02-18 18:21:40
一、toolbar 1、在build.gradle中添加依赖,例如: compile 'com.android.support:appcompat-v7:23.4.0'...

一、toolbar

1、在build.gradle中添加依赖,例如:

compile 'com.android.support:appcompat-v7:23.4.0'

2、去掉应用的actionbar。可以是修改主题theme为“noactionbar”,例如:

<style name="apptheme" parent="theme.appcompat.light.noactionbar">

或者不修改主题为"noactionbar",而在主题的style下,添加:

 <item name="windownotitle">true</item>
 <item name="windowactionbar">false</item>

第二个属性代表是否用actionbar代替titlebar。

其实,刚学的时候,感觉很纳闷,怎么又多了个titlebar?后来查了很久才发现,3.0以前,状态栏下面的是标题栏(只能显示标题等少量信息),3.0以后就变成了应用栏,也就是actionbar。

另外,我测试的时候,activity是继承于appcompatactivity,主题是appcompat类型的。这种情况下,必须要像上面那样写才有效果,少写或值不同的话,要么没效果,要么报错。

最后,上面两个属性的说明可在android.r.attr这个类中查看。

3、在xml中为toolbar添加属性

 android:fitssystemwindows="true"
 android:minheight="?attr/actionbarsize"

fitssystemwindows是toolbar实现沉浸式状态栏的关键,其大概情况是,如果设为true,就会调整这个view去留一些空间给系统窗口,如果不设置或设为false,toolbar就会和状态栏重叠在一起。

而第二个属性中,它的值全写是"?android:attr/actionbarsize",其意思是引用当前主题中的actionbarsize这个属性。更多相关说明可查看官方文档中accessing resources的部分。

上面两个属性可在android.view.view这个类中查看。

4、在java中添加判断sdk版本的代码并在用户的系统是4.4及以上时设置状态栏为透明

if (build.version.sdk_int >= build.version_codes.kitkat) {
 getwindow().addflags(windowmanager.layoutparams.flag_translucent_status);
}

无论是toolbar,还是自定义导航栏,这个操作都是实现沉浸式状态栏的关键。

因为设置状态栏为透明的这个属性,要4.4以上才能使用,所以4.4以下的系统是不能够实现沉浸式状态栏的。而在4.4到5.0的系统中,状态栏是全透明的,也就是它的颜色会跟你的toolbar和自定义导航栏的颜色一样。而在5.0以上的系统中,则是半透明的,也就看起来会比较深暗。

而我在6.0的系统上测试时,发现这一步没设置和设置了的,从效果上看,区别就是没设置时状态栏颜色浅一点,而且toolbar的padding top为0,而设置了的颜色就深一点,padding top为状态栏的高度。具体有什么影响,还不清楚。但这会让自定义导航的外观变形,它会增加状态栏的高度,但又没有让这部分与状态栏重叠,就导致效果变形。

5、最后在java中添加

setsupportactionbar(mtoolbar);

toolbar的布局代码:

<?xml version="1.0" encoding="utf-8"?>
<android.support.v7.widget.toolbar
 xmlns:android="http://schemas.android.com/apk/res/android"
 xmlns:app="http://schemas.android.com/apk/res-auto"
 android:id="@+id/tool_bar"
 android:layout_width="match_parent"
 android:layout_height="wrap_content"
 android:background="@color/colorprimary"
 android:elevation="4dp"
 android:fitssystemwindows="true"
 android:minheight="?android:attr/actionbarsize"
 app:title="toolbar"
 app:subtitle="toolbar"/>

 效果图(android 6.0):

分别用ToolBar和自定义导航栏实现沉浸式状态栏

二、自定义导航栏topbar

1、设置窗口为无标题,上面第2步中的两个方法都可以实现,或者是在java中添加如下代码:

requestwindowfeature(window.feature_no_title);

注意在添加这句代码时,确保是在加载布局内容之前,也就是oncreate的setcontentview之前。在《android群英传》“android控件架构”,这一节中解释了为什么requestwindowfeature()需要在setcontentview()之前。

另外,我发现如果该activity是继承appcompatactivity的话,只写上面的这句代码是没有变化的,显示的还是actionbar。但如果是继承fragmentactivity的话,就有效果,也就说上面第2步中的第二个方法,只添加其中任意一个属性都是可以的。至于是什么原因,我还没弄清楚。

2、同上面第4步,判断系统版本并按需设置状态栏为透明

3、获取状态栏的高度

protected int getstatusheight() {
 try {
 class<?> c = class.forname("com.android.internal.r$dimen"); // 获得与字符串对应的class对象
 object object = c.newinstance(); // 创建这个class的实例对象
 field field = c.getfield("status_bar_height"); // 拿到字符串对应的变量
 int x = integer.parseint(field.get(object).tostring()); // 通过这个实例对象拿到这个变量的值,再转换类型,最后转为整型,变为一个资源id
 return getresources().getdimensionpixelsize(x);
 } catch (exception e) {
 e.printstacktrace();
 }
 return 0;
}

这部分代码是利用java的反射机制来实现的,因为这个internal包默认会被sdk/platforms/android-version中的android.jar给移除掉,所以无法直接调用或查看这个包中的类。如果要使用的话,可以借助这个开源项目。

4、获取自定义topbar的高度并修改布局参数

protected void setstatusbar() {
 if (build.version.sdk_int >= build.version_codes.kitkat) {
 final viewgroup viewgroup = (viewgroup) findviewbyid(r.id.top_bar);
 final int statusheight = getstatusheight();
 viewgroup.post(new runnable() {
  @override
  public void run() {
  int topbarheight = viewgroup.getheight();
  linearlayout.layoutparams layoutparams = (linearlayout.layoutparams) viewgroup.getlayoutparams();
  layoutparams.height = statusheight + topbarheight;
  viewgroup.setlayoutparams(layoutparams);
  }
 });
 }
}

因为在include这个topbar的布局文件中,其父布局是linearlayout,而topbar的父布局是relativelayout,所以这里先要转成viewgroup,等getlayoutparams时,再转成linearlayout.layoutparams。

topbar的布局:

<?xml version="1.0" encoding="utf-8"?>
<relativelayout xmlns:android="http://schemas.android.com/apk/res/android"
 android:id="@+id/top_bar"
 android:layout_width="match_parent"
 android:layout_height="49dp"
 android:background="@color/colorprimary"
 android:gravity="bottom">
 <relativelayout
 android:layout_width="match_parent"
 android:layout_height="49dp">
 <textview
  android:layout_width="wrap_content"
  android:layout_height="wrap_content"
  android:layout_centerinparent="true"
  android:text="@string/app_name"
  android:textsize="24sp"
  android:textcolor="#ffffff"/>
 </relativelayout>
</relativelayout>

因为这个布局的高度会在代码中动态地修改,即49dp加上状态栏的高度,所以只有一个层级的结构的话,那导航栏的内容就会往上偏。所以要嵌套多一层来维持导航栏的高度,同时在最外层的布局中,添加android:gravity="bottom"这个属性来保证导航栏不往上偏。

效果图(android 6.0):

分别用ToolBar和自定义导航栏实现沉浸式状态栏

以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,同时也希望多多支持!