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

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

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

时间: 2024-10-22 05:42:49

分别用ToolBar和自定义导航栏实现沉浸式状态栏的相关文章

ios-iOS隐藏系统导航栏用自定义导航栏

问题描述 iOS隐藏系统导航栏用自定义导航栏 前提:1.navigationBarHidden = YES; 2.不要在每个ViewController中addSubView一次,继承父类的方法也不行. 就是想做一个绝对灵活的导航栏,高度不是44,样式也不是只有左右中三个部分.我听一个大神说这是iOS常识,让我查百度,可是我真的查不到,求助啊. 解决方案 iOS系统导航栏的自定义化 解决方案二: 给一个你想要视图作为导航栏不就行了? 解决方案三: 你自定义一个导航栏 隐藏系统的 再添加到UINa

ios开发碰到自定义导航栏leftBarButtonItems导致滑动返回失效问题解决方法

通常使用导航控制器 navigationController 跳转到另一页面时,除了可以点击左上角的返回按钮,还可以通过在屏幕左侧向右滑动来返回到上一层.但如果自定义了 self.navigationItem.leftBarButtonItems 后会发现,滑动返回(swipe back)失效了. (如何自定义导航栏左侧按钮可以看这篇文章:Swift - 修改导航栏"返回"按钮文字,图标) 开发碰到自定义导航栏leftBarButtonItems导致滑动返回失效问题解决方法-leftb

React Native自定义导航栏

之前我们学习了可触摸组件和页面导航的使用的使用: 从零学React Native之09可触摸组件 - 从零学React Native之03页面导航 - 经过之前的学习, 我们可以完成一个自定义导航栏了, 效果如下: 我们需要创建一个 NaviBar.js 用来显示顶部的导航栏, 还需要四个界面(Page1.js,Page2.js,Page3.js,Page4.js). 当然还需要修改index.android.js或者index.ios.js 用来处理4个界面的切换. 导航栏NaviBar 实现

Android 沉浸式状态栏与隐藏导航栏实例详解

1 前言 一般我们在Android的APP开发中,APP的界面如下: 可以看到,有状态栏.ActionBar(ToolBar).导航栏等,一般来说,APP实现沉浸式有三种需求:沉浸式状态栏,隐藏导航栏,APP全屏 沉浸式状态栏是指状态栏与ActionBar颜色相匹配, 隐藏导航栏不用多说,就是将导航栏隐藏,去掉下面的黑条. APP全屏是指将状态栏与导航栏都隐藏,例如很多游戏界面,都是APP全屏. 所以,在做这一步时,关键要问清楚产品狗的需求,免得白费功夫. 下面,分别来介绍这三种方式的实现. 2

百度应用 android客户端(一)自定义导航栏

title布局activity_main_title.xml     <?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height=

Android自定义View实现字母导航栏的代码_Android

思路分析: 1.自定义View实现字母导航栏 2.ListView实现联系人列表 3.字母导航栏滑动事件处理 4.字母导航栏与中间字母的联动 5.字母导航栏与ListView的联动 效果图: 首先,我们先甩出主布局文件,方便后面代码的说明 <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/re

Android自定义View实现字母导航栏_Android

很多的Android入门程序猿来说对于Android自定义View,可能都是比较恐惧的,但是这又是高手进阶的必经之路,所有准备在自定义View上面花一些功夫,多写一些文章. 思路分析: 1.自定义View实现字母导航栏 2.ListView实现联系人列表 3.字母导航栏滑动事件处理 4.字母导航栏与中间字母的联动 5.字母导航栏与ListView的联动 效果图: 首先,我们先甩出主布局文件,方便后面代码的说明 <!--?xml version="1.0" encoding=&qu

关于iOS导航栏返回按钮问题的解决方法_IOS

最近遇到一个关于导航栏返回按钮的问题,因为之前项目里面都是用的系统默认的返回按钮样式所以没有想过要去更改,后来有需要将返回按钮箭头旁边的文字去掉,同时将该返回按钮的点击事件重新定义.一开始尝试自定义按钮然后设置为leftBarButtonItem,但是这样图片可能跟系统自带的不一样,还有就是返回按钮的位置跟系统自带的不一样.后来找了一些资料,发现将文字去掉比较简单,一般做法是控制器中添加如下代码,然后他的下一级控制就有一个只有箭头没有文字返回按钮: 复制代码 代码如下: UIBarButtonI

iOS实现知乎和途家导航栏渐变的文字动画效果_IOS

效果图如下 分析如下:      1.导航栏一开始是隐藏的,随着scrollView滚动而渐变      2.导航栏左右两边的navigationItem是一直显示的      3.导航栏参考了途家app,使用了毛玻璃效果,背景是一张图片      4.下拉放大图片效果      5.title文字动画效果 通过简单分析,系统的导航栏实现以上效果有点困难,直接自定义一个假的导航栏更容易点 分布拆解实现以上效果 一.下拉放大header图片 - (void)viewDidLoad { [super