需求描述:
PM来一句,做成美团首页顶通的效果。
实现效果要做的事情有:
- 沉浸式状态栏
- 标题栏变色(从透明变成白色再渐变成红色)
- 无Banner时不沉浸(有状态栏有标题栏)
实现效果如下所示。
方法有很多,我的解决方法如下:
状态栏
4.4之前,状态栏一值是黑色的,4.4中windowTransluentStatus可以给状态栏设置颜色。4.4及以上都是可以实现沉浸式状态栏效果,**5.0及其以上,可以直接在主题中设置颜色,或者直接调用Window类中的setStatusBarColor(int)来实现;
沉浸式的实现原理,就是将整个activity布局延伸到整个屏幕,然后使状态栏变成透明色。所以沉浸式状态栏又可以叫做Translucent Bar。
解决思路
- 先将状态栏设置为透明属性
- Toolbar代替ActionBar,获得更好的控制
- 根布局设置成RelativeLayout,方便调整View的位置
Activity的布局
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/page"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<FrameLayout
android:id="@+id/content"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_below="@id/toolbar">
</FrameLayout>
<include android:id="@id/toolbar"
layout="@layout/activity_search_toolbar"/>
</RelativeLayout>
activity_search_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"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="48dp"
android:layout_marginTop="0dp"
app:contentInsetStart="0dp">
<LinearLayout
android:id="@+id/title_bar"
android:layout_width="match_parent"
android:layout_height="48dp"
android:gravity="center_vertical"
android:orientation="horizontal">
<ImageView
android:id="@+id/toolbar_back"
android:layout_width="48dp"
android:layout_height="match_parent"
android:scaleType="centerInside"
android:src="@drawable/arrow_left"/>
<TextView
android:id="@+id/search_edit"
android:layout_width="0dp"
android:layout_height="34dp"
android:layout_weight="1" android:drawableLeft="@drawable/search"
android:drawablePadding="3dp"
android:ellipsize="end"
android:gravity="center_vertical"
android:hint="目的地/景点/关键词"
android:maxLines="1"
android:paddingBottom="6dp"
android:paddingLeft="10dp"
android:paddingRight="5dp"
android:paddingTop="5dp"
android:textColor="@color/black"
android:textSize="14sp"/>
<TextView
android:id="@+id/change_city"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_gravity="center_vertical"
android:drawablePadding="3dp"
android:drawableRight="@drawable/arrow_red"
android:gravity="center_vertical"
android:paddingLeft="12dp"
android:paddingRight="12dp"
android:textColor="#FF0"
android:textSize="14sp"/>
</LinearLayout>
</android.support.v7.widget.Toolbar>
设置透明状态栏
//沉浸式状态栏
public void immersiveStatusBar(Window window) {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT) {
return;
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
window.clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
window.setStatusBarColor(Color.TRANSPARENT);
int systemUiVisibility = window.getDecorView().getSystemUiVisibility();
//Activity全屏显示,状态栏不会被隐藏覆盖,状态栏依然可见,Activity顶端布局部分会被状态栏遮住。
systemUiVisibility |= View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN;
//防止系统栏隐藏时内容区域大小发生变化
systemUiVisibility |= View.SYSTEM_UI_FLAG_LAYOUT_STABLE;
window.getDecorView().setSystemUiVisibility(systemUiVisibility);
} else {
window.addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
}
immersive = true;
}
根据有无Banner,设置content(内容Fragment的位置)
- 如果有Banner,状态栏设置为透明,toolbar的topMargin=状态栏高度,RelativeLayout不动,监听滚动,设置状态栏和toolbar的颜色
- 如果没有Banner,设置content在toolbar的下面,toolbar的topMargin=状态栏高度
- 因为在滚动过程中,还要更改状态栏的颜色和透明度,干脆做一个假的状态栏,方便控制。
private void setNoBannerToolbarStyle() {
if (toolbar == null) {
return;
}
//content的布局参数
RelativeLayout.LayoutParams contentLayoutParams = (RelativeLayout.LayoutParams) contentLayout.getLayoutParams();
contentLayoutParams.addRule(RelativeLayout.BELOW, R.id.toolbar);
RelativeLayout.LayoutParams toolbarLayoutParams = (RelativeLayout.LayoutParams) toolbar.getLayoutParams();
if (immersive) {
toolbarLayoutParams.topMargin = getStatusBarHeight(getContext());
} else {
toolbarLayoutParams.topMargin = 0;
}
}
private void setToolbarStyle() {
if (toolbar == null) {
return;
}
RelativeLayout.LayoutParams contentLayoutParams = (RelativeLayout.LayoutParams) contentLayout.getLayoutParams();
contentLayoutParams.addRule(RelativeLayout.BELOW, 0);
if (immersive) {
RelativeLayout.LayoutParams toolbarLayoutParams = (RelativeLayout.LayoutParams) toolbar.getLayoutParams();
toolbarLayoutParams.topMargin = statusBarHeight;
.......
}
//添加假的状态栏
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT && Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP && statusBarView == null) {
ViewGroup contentView = (ViewGroup) getActivity().findViewById(R.id.page);
statusBarView = new View(getContext());
ViewGroup.LayoutParams lp = new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
getStatusBarHeight(getActivity()));
statusBarView.setBackgroundColor(Color.TRANSPARENT);
contentView.addView(statusBarView, lp);
}