一、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):

二、自定义导航栏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给移除掉,所以无法直接调用或查看这个包中的类。如果要使用的话,可以借助这个开源项目https://github.com/anggrayudi/android-hidden-api。

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和自定义导航栏实现沉浸式状态栏的更多相关文章

  1. iOS 自定义导航栏 和状态栏

    一.更改状态栏颜色 (StatusBar) 就是比如导航栏是红色的状态栏是绿色的. 要实现这样的效果其实很简单,就是添加一个背景view. 简单的实现过程如下: 1 // 设置导航颜色 可用 2 [s ...

  2. swift 自定义导航栏颜色

    func setNavigationApperance(){ //自定义导航栏颜色 [self.navigationController?.navigationBar.barTintColor = U ...

  3. ios7以上自定义导航栏标题的字体大小及颜色的方法

    自定义导航栏的字体和颜色,只需要自定义一个lable,然后将lable添加到导航栏的titleview中就可以了 代码如下 UILabel *label = [[UILabel alloc] init ...

  4. iOS 自定义导航栏笔记

    一.UINavigationBar的结构 导航栏几乎是每个页面都会碰到的问题,一般两种处理方式:1.隐藏掉不显示 2.自定义 1. 添加导航栏 TestViewController * mainVC ...

  5. 微信小程序自定义导航栏

    微信小程序需要自定义导航栏,特别是左上角的自定义设置,可以设置返回按钮,菜单按钮,配置如下: 1.在app.json的window属性中增加: navigationStyle:custom 顶部导航栏 ...

  6. iOS:自定义导航栏,随着tableView滚动显示和隐藏

    自定义导航栏,随着tableView滚动显示和隐藏 一.介绍 自定义导航栏是APP中很常用的一个功能,通过自定义可以灵活的实现动画隐藏和显示效果.虽然处理系统的导航栏也可以实现,但是这个是有弊端的,因 ...

  7. 微信小程序 - 自定义导航栏(提示)

    点击下载: 自定义导航栏示例

  8. 微信小程序——自定义导航栏

    微信头部导航栏可能通过json配置: 但是有时候我们项目需求可能需要自定义头部导航栏,如下图所示: 现在具体说一下实现步骤及方法: 步骤: 1.在 app.json 里面把 "navigat ...

  9. 微信小程序-如何自定义导航栏(navigationStyle)?

    小程序是越来越开放了,微信版本 6.6.0可以自定义导航? 先了解下app.json中window配置navigationStyle属性,即导航栏样式,仅支持 default/custom.custo ...

随机推荐

  1. BZOJ 3626: [LNOI2014]LCA [树链剖分 离线|主席树]

    3626: [LNOI2014]LCA Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 2050  Solved: 817[Submit][Status ...

  2. Linux学习日记-MVC的部署(三)

    一.Mvc与wcf 相对WCF的部署MVC还是有点麻烦,我们要考虑哪些dll是不需要的,哪些是要拷贝到本地的. 而WCF因为有些配置文件不支持,我们只需要在配置wcf时不使用配置文件而直接使用代码就行 ...

  3. Visual Studio Code v0.9.1 发布

    微软的跨平台编辑器 Visual Studio Code v0.9.1 已经发布,官方博客上发布文章Visual Studio Code – October Update (0.9.1):http:/ ...

  4. EQueue 2.0 性能测试报告

    前言 最近用了几个月的时间,一直在对EQueue做性能优化.到现在总算告一段落了,现在把一些优化的结果分享给大家.EQueue是一个分布式的消息队列,设计思路基本和阿里的RocketMQ一致,只是是用 ...

  5. 酷酷的CSS3三角形运用

    概述 在早期的前端Web设计开发年代,完成一些页面元素时,我们必须要有专业的PS美工爸爸,由PS美工爸爸来切图,做一些圆角.阴影.锯齿或者一些小图标. 在CSS3出现后,借助一些具有魔力的CSS3属性 ...

  6. 2000条你应知的WPF小姿势 基础篇<8-14>

    在正文开始之前需要介绍一个人:Sean Sexton. 来自明尼苏达双城的软件工程师,对C#和WPF有着极深的热情.最为出色的是他维护了两个博客:2,000Things You Should Know ...

  7. 关于百度编辑器UEditor的一点说明

    大家在使用的时候要特别注意editor_config.js中的“URL”这个参数 我的理解:1.这个参数是editor整个结构的总路径          2.首先要把这个路径配置好了.才能正常的显示, ...

  8. iOS--碎片知识锦集

    知识锦集day01 1.UIView的两个方法: sizeThatFits和 sizeToFit 官方文档上说: - (CGSize)sizeThatFits:(CGSize)size;     // ...

  9. ★Kali信息收集~★7.FPing :ip段扫描

    参数: 使用方法: fping [选项] [目标...] -a显示是活着的目标 -A 显示目标地址 -b n 大量 ping 数据要发送,以字节为单位 (默认 56) -B f 将指数退避算法因子设置 ...

  10. 前端学HTTP之代理

    前面的话 Web代理(proxy)服务器是网络的中间实体,位于客户端和服务器之间,扮演“中间人”的角色,在各端点之间来回传送HTTP报文.本文将介绍HTTP代理服务器相关内容 中间实体 Web上的代理 ...