Android下的沉浸式状态栏+折叠TitleBar(CoordinatorLayout+CollapsingToolbarLayout)+ViewPager切换实现
最终效果以及过程中出现的问题如下:(简单解决在ViewPager+Fragment的组合中实现该效果时出现有页面视图偏移一个状态栏高度问题)
一:实现沉浸式的状态栏
沉浸式状态栏的实现是从android版本KITKAT开始,从KITKAT开始谷歌开始支持状态栏的背景色设置为透明,但在Lollipop版本(5.0)之后概念有所不同。
设置状态栏透明的步骤:
1.实现当前activity的theme样式为无Tilte的,否则会有系统的titlebar显示在屏幕上方影响效果。
即在Style.xml文件里面自定义一个主题样式:AppNoTitleTheme,
主要添加条目属性字段:windowNoTitle为true。并把要实现沉浸样式的Activity或整个应用的theme设置为该style
android:theme="@style/AppNoTitleTheme"
AppNoTitleTheme
对应如下:
<style name="AppNoTitleTheme" parent="Theme.AppCompat.Light.DarkActionBar">
<!-- Customize your theme here. -->
<item name="colorPrimary">@color/colorPrimary</item>
<item name="windowNoTitle">true</item>
<item name="colorPrimaryDark">@color/colorPrimaryDark</item>
<item name="colorAccent">@color/colorAccent</item>
</style>
当然也可以直接引用系统预定义的
样式:
android:theme="@style/Theme.AppCompat.Light.NoActionBar"
2.是实现状态栏的背景为透明背景,实现可以看到状态栏下方的视图内容,该实现一般在Activity中代码添加FLAG实现
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
this.getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
//此FLAG可使状态栏透明,且当前视图在绘制时,从屏幕顶端开始即top = 0开始绘制,这也是实现沉浸效果的基础this.getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION);//可不加
}
setContentView(R.layout.activity_main);//在此之前添加以上FLAG
initView();
initEvent();
}
tip:该FLAG需要在Activity 的setContentView(R.layout.activity_main)方法之前添加
加上此段代码之后在KITKAT及之上的版本即可实现状态栏透明,并且当前要展示的视图view从top为0的地方开始绘制。
至此状态栏已经实现透明,且当前的Activity视图已经可以延伸到状态栏下方
效果如下:
该效果实现之后有如下问题:此时标题会随整个试图的延伸一起延伸到状态栏的下方,致使状态栏遮挡了部分自定义的标题
解决该问题,也很简单android原生已经提供了相关实现:
要想实现标题栏不被遮挡,可以在在根节点的布局文件中添加fitsSystemWindows 和clipToPadding的标志位即可。代码如下:
<RelativeLayout
android:fitsSystemWindows="true"
android:clipToPadding="false"
android:layout_width="match_parent"
android:layout_height="match_parent"></RelativeLayout>
fitsSystemWindows:该属性值表示系统布局过程中是否会为该view自动适应系统窗口(状态栏/导航栏),为true时系统会在设置了该属性的view的布局中,自动为其添加状态栏的高度的paddingtop值,使其实际布内容不被状态栏遮挡;为false时,则不会为其添加该padding值。默认不设的值为false。
clipToPadding:该属性值为在绘制的时候是否可以在其padding区域内绘制。当为true时可以在其padding区域内绘制,否则不可绘制。
》》但此时效果如下:虽然视图沉了一个状态栏的高度,但是同时状态栏的颜色是透明的,显示出了原有的底色。
此时,需要解决的是让状态栏下的颜色为自定义的,在版本为Lollipop及之后s状态栏可以设置背景色,但是KITKAT版本并没有此方法,这也是KITKAT只是设置状态栏背景为透明是相关的。所以KITKAT版本相比Lollipop及更高版本的沉浸实现是有一定差别。对此常用的解决方法就是
不再添加fitSystemwindows属性,而是手动添加一个占位布局,设置其高度为statusbar的高度,背景为设置为自己想要的颜色即可。
进一步,如果要实现底层背景是整张图片,并以该图片为背景色,需要其整个延伸至状态栏下方,则可做如下布局,同样在自定义的titlebar的布局上添加占位控件。设置其高度,同时设置其颜色为透明即可。
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<ImageView
android:id="@+id/textdemo_image"
android:src="@drawable/bg3"
android:layout_width="match_parent"
android:layout_height="match_parent" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<!-- textdemo_titleholderview 此控件为占位控件设置其高度为状态栏的高度-->
<View
android:id="@+id/textdemo_titleholderview"
android:layout_width="match_parent"
android:layout_height="0dp" />
<!-- titlebar_view此控件为自定义的标题栏titlebar-->
<include layout="@layout/titlebar_view"></include>
<View
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<include layout="@layout/line_mode_view"></include>
<include layout="@layout/line_mode_view"></include>
</LinearLayout>
</LinearLayout>
</RelativeLayout>
占位控件代码实现如下:
ViewGroup.LayoutParams layoutParams = titlebarHolder.getLayoutParams();//
titlebarHolder为添加的顶部的(标题栏上方)占位控件layoutParams.height = getStatueBarHeight();
titlebarHolder.setLayoutParams(layoutParams);