内容简介:看过上篇文章的演示,就应该能看到我们在滑动返回的时候,顶部的状态栏其实是没和我们的页面一起滑动的,本篇就此问题进行适配,让标题栏沉浸到状态栏中,而且还是能够适配现在市面上所见的异形屏。我们要实现下面这样的一个标题栏,支持沉浸图片或者纯色,还需要提供 helper,为以后需求变更做准备。
引言
看过上篇文章的演示,就应该能看到我们在滑动返回的时候,顶部的状态栏其实是没和我们的页面一起滑动的,本篇就此问题进行适配,让标题栏沉浸到状态栏中,而且还是能够适配现在市面上所见的异形屏。
正文
我们要实现下面这样的一个标题栏,支持沉浸图片或者纯色,还需要提供 helper,为以后需求变更做准备。
分析
首先来分析一下我们的布局,在默认的情况下,我们的整个屏幕分为三部分(没有考虑虚拟状态栏):状态栏、标题栏、内容区域。对于状态栏来说我们只能设置颜色,而像我们上面的需求他应该是一个 Drawable 或者是一张纯图片。
然后在我们的实现中其实是用 AppBarLayout
包裹着 Toolbar
,我们操作的也是 AppBarLayout
, Toolbar
保持原状。
实现思路
我们的实现思路也很简单,很多时候是没有一个思路的开头,导致无法进行。
1. 设置状态栏的颜色为透明和让整个布局沉浸到状态栏中
关于状态栏操作的开源库的话,之前已经引入过 StatusBarUtil ,操作简单也方便,有兴趣的可以去看一下。
我们就用 第九篇 文章中的模板, 先新建一个Activity,不记得的朋友可以倒回去看看。看一下运行起来的页面吧,默认状态下什么都没有。
xml
<?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" tools:context=".module.example.StatusToolBarActivity"> <android.support.design.widget.AppBarLayout style="@style/BaseAppBarLayoutStyle"> <android.support.v7.widget.Toolbar style="@style/BaseToolbarStyle" app:popupTheme="@style/AppTheme.PopupOverlay"> <TextView style="@style/ToolBarNavTextStyle" android:text="@string/nav_call_back" /> <TextView style="@style/ToolBarTitleStyle" android:text="@string/title_activity_status_tool_bar" /> </android.support.v7.widget.Toolbar> </android.support.design.widget.AppBarLayout> <include layout="@layout/content_status_tool_bar" /> </android.support.design.widget.CoordinatorLayout>
运行效果
然后在我们的 Activity的onCreate 中加上这段代码:
// 设置沉浸和状态栏的颜色为透明 StatusBarUtil.setTranslucentForImageView(this, 0, null);
看一下效果吧:
从上图可以看出,我们的 AppBarLayout 已经沉浸到状态栏中了,而且在滑动返回的时候也显示的十分自然、符合直觉。但是能看到 AppBarLayout 的位置和内容明显有点偏了,接下来就是对此进行适配。
2. 更改AppBarLayout的高度和Padding
这里适配起来也是比较简单的,因为我们是直接把 AppBarLayout 沉浸到了状态栏中,所以我们只需要在 Activity 中获取到 AppBarLayout,将 AppBarLayout 的高度更改为 原本的高度+状态栏的高度
,且把 PaddingTo
设置为 状态栏的高度
,将 ToolBar
背景颜色的更改为完全透明,其它属性爆出不变。
关于获取 AppBarLayout ,在上一篇中我们封装过 BaseAppBarLayoutStyle ,里面有id/base_appbar。具体看代码吧。
/** * 初始化标题栏 */ private void initBaseToolBar() { // 设置为透明色 mToolBar 已经在base中获取过了 mToolBar.setBackgroundColor(0x00000000); mToolBar.setTitle(""); // 设置全透明 mToolBar.getBackground().setAlpha(0); // appbar AppBarLayout mAppBarLayout = findViewById(R.id.base_appbar); // 状态栏高度 getStatusBarHeight只是一个获取高度的方法 int statusBarHeight = getStatusBarHeight(mActivity); //大于 19 设置沉浸和padding if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { if (mAppBarLayout != null) { ViewGroup.MarginLayoutParams appbarLayoutParam = (ViewGroup.MarginLayoutParams) mAppBarLayout.getLayoutParams(); // 更改高度 toolbar_height 的高度是可配置的 appbarLayoutParam.height = (int) (getResources().getDimension(R.dimen.toolbar_height) + statusBarHeight); // 设置padding mAppBarLayout.setPadding(mAppBarLayout.getPaddingLeft(), statusBarHeight, mAppBarLayout.getPaddingRight(), mAppBarLayout.getPaddingBottom()); //重新设置回去 mAppBarLayout.setLayoutParams(appbarLayoutParam); } } // 设置沉浸和状态栏的颜色为透明 StatusBarUtil.setTranslucentForImageView(this, 0, null); } /** * 获取状态栏高度 * * @param context context * @return 状态栏高度 */ private int getStatusBarHeight(Context context) { // 获得状态栏高度 int resourceId = context.getResources().getIdentifier("status_bar_height", "dimen", "android"); return context.getResources().getDimensionPixelSize(resourceId); }
运行起来看看效果吧。
看上去我们已经完美,接下来我们就尝试直接将背景颜色更改为 Drawable
,为了更显眼,我特地选了一个鲜艳的颜色写了一个 shape
,代码如下:
<?xml version="1.0" encoding="utf-8"?> <shape xmlns:android="http://schemas.android.com/apk/res/android"> <gradient android:angle="45" android:endColor="#03a4f9" android:startColor="#ff76D2" /> </shape>
然后为设置为 AppBarLayout
的背景即可,运行起来看看吧(Gif 看上去颜色有点失真,但是实际上是很圆滑的)。
从图中基本可以看到,基本上已经实现了最开始提的需求。其实到了这一步,我们的ToolBar已经能够满足绝大多数需求了,五彩斑斓的标题栏就此诞生~~
4. 预埋相关设置
接下来就是将初始化 ToolBar 的代码和原本 CandyBaseActivity
的合并在一起,并增加一些其它的设置,方便后续的使用。
在封装到 CandyBaseActivity
需要注意以下情况:
- 并不是每个 Activity 都需要底层初始化 ToolBar 的,类似于图片沉浸和特殊效果的页面。
- 所以 initToolbar
这个方法应该是 protected
,让子类可覆写。
- 基类不应该直接操作 AppBarLayout
的背景颜色,就应该像我们写的列子中一样,子类只做相关初始化,背景颜色让子类在xml中定义。
- NavigationIcon
可以让子类自己设置,在没有的情况下才使用基类中定义的icon,icon的替换只需要命名为相同的名字,放到 module
下相同的文件夹中,最终打包将会以 module
为主。
CandyBaseActivity
的代码量有点多,以下为主要核心代码:
/** * 初始化toolbar<p> * 如果子页面不需要初始化ToolBar,请直接覆写本方法做空操作即可 * </p> */ protected void initToolbar() { mToolBar = findViewById(R.id.base_toolbar); if (null != mToolBar) { // 设置为透明色 mToolBar.setBackgroundColor(0x00000000); // 设置全透明 mToolBar.getBackground().setAlpha(0); // 清除标题 mToolBar.setTitle(""); setSupportActionBar(mToolBar); // 子类中没有设置过返回按钮的情况下 if (mToolBar.getNavigationIcon() == null) { //设置返回按钮 mToolBar.setNavigationIcon(getNavigationIcon()); } mToolBar.setNavigationOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { onNavigationOnClickListener(); } }); isInitToolbar = true; //返回文字按钮 View navText = findViewById(R.id.toolbar_nav_text); if (null != navText) { navText.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { onNavigationOnClickListener(); } }); } } // appbar AppBarLayout mAppBarLayout = findViewById(R.id.base_appbar); // 状态栏高度 getStatusBarHeight只是一个获取高度的方法 int statusBarHeight = getStatusBarHeight(mActivity); //大于 19 设置沉浸和padding if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { if (mAppBarLayout != null) { ViewGroup.MarginLayoutParams appbarLayoutParam = (ViewGroup.MarginLayoutParams) mAppBarLayout.getLayoutParams(); // 更改高度 toolbar_height 的高度是可配置的 appbarLayoutParam.height = (int) (getResources().getDimension(R.dimen.toolbar_height) + statusBarHeight); // 设置padding mAppBarLayout.setPadding(mAppBarLayout.getPaddingLeft(), statusBarHeight, mAppBarLayout.getPaddingRight(), mAppBarLayout.getPaddingBottom()); //重新设置回去 mAppBarLayout.setLayoutParams(appbarLayoutParam); } } // 设置沉浸和状态栏的颜色为透明 StatusBarUtil.setTranslucentForImageView(this, 0, null); } /** * 返回按钮 * 子类通过覆写本方法返回需要设置的返回按钮,也可以直接在xml中直接赋值 * @return */ protected int getNavigationIcon() { return R.drawable.ic_chevron_left_write_24dp; }
演示一下抽取封装以后的效果:
结束
总结
总得来说,实现并不是很困难,关键点在于实现思路。另外我们此次实现的这个ToolBar是能够适配 异形屏
和 全面屏
的,不信的可以试试。
如果我的文章和代码对你有了帮助,请给我一个star和关注~~
软广
来都来了,就给个关注吧,时不时会悄悄的推送一些小技巧的文章~~!
以上所述就是小编给大家介绍的《Android 之路 (11) - 对Toolbar的封装-实现渐变标题栏与沉浸适配》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!
猜你喜欢:- iOS WHGradientHelper(线性、径向渐变;渐变动画;Lable字体渐变及动画)
- Flutter 中渐变的高级用法
- 沉浸式渐变图片轮播器
- CSS3 渐变(Gradients)
- java – 不同dpi的径向渐变
- 简易的iOS导航栏颜色渐变方案
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。