1.前言
上篇文章讲了如何把ToolBar封装到基类Activity中和如何在android4.4及以上系统中实现沉浸式状态栏、如何更改状态栏字体颜色。接下来这篇文章介绍Fragment的简单封装和如何将内容布局延伸到状态栏当中。
2.实现步骤
先看一下实现的效果图:
如图这个Activity中有四个Fragment,每个Fragment状态栏颜色不一样并且首页那个Fragment将内容布局延伸到状态栏中了。
2.1简单封装Fragment
上一章介绍了如何在基类Activity中封装ToolBar,以便于可以动态的显示或隐藏ToolBar。在这一节里我们也来简单封装个Fragment的,以便于在每个Fragment中的标题栏都可以自定义和跟随状态栏的颜色。
public abstract class BaseFragment extends Fragment {
private static final String TAG=BaseFragment.class.getSimpleName();
protected Context mContext;
protected View baseView;
@Override
public void onAttach(Context context) {
super.onAttach(context);
mContext=context;
Log.d(TAG,"==onAttach");
}
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Log.d(TAG,"==onCreate");
}
@Nullable
@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
Log.d(TAG,"==onCreateView");
if(baseView!=null){
//避免重复设置,如果父控件已经添加了baseView,再添加会报错,需要先移除
ViewGroup viewGroup= (ViewGroup) baseView.getParent();
if(viewGroup!=null){
viewGroup.removeAllViews();
}
}else {
baseView = getLayoutInflater(savedInstanceState).inflate(getLayoutId(), null)
baseView.setPadding(0,topHeight(),0,0);
initView();
}
return baseView;
}
@Override
public void onActivityCreated(@Nullable Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
Log.d(TAG,"==onActivityCreated");
}
@Override
public void setUserVisibleHint(boolean isVisibleToUser) {
super.setUserVisibleHint(isVisibleToUser);
Log.d(TAG,"==isVisibleToUser");
}
@Override
public void onStart() {
super.onStart();
Log.d(TAG,"==onStart");
}
@Override
public void onResume() {
super.onResume();
Log.d(TAG,"==onResume");
}
@Override
public void onPause() {
super.onPause();
Log.d(TAG,"==onPause");
}
@Override
public void onStop() {
super.onStop();
Log.d(TAG,"==onStop");
}
@Override
public void onDestroyView() {
super.onDestroyView();
Log.d(TAG,"==onDestoryView");
}
@Override
public void onDestroy() {
super.onDestroy();
Log.d(TAG,"==onDestory");
}
/**
* 解决首页fragment切换
* java.lang.IllegalStateException: No activity异常
*/
@Override
public void onDetach() {
super.onDetach();
Log.d(TAG,"==onDetach");
//通过反射找到mChildFragmentManager置null
try {
Field mChildFragmentManage=Fragment.class.getDeclaredField("mChildFragmentManager");
mChildFragmentManage.setAccessible(true);
mChildFragmentManage.set(this,null);
} catch (NoSuchFieldException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
/**
*如果Fragment不需要把布局延伸到状态栏
*可以重写这个方法,设置高度为状态栏高度。
*如果需要延伸到状态栏,可以不必重写
*/
protected int topHeight(){
return 0;
}
protected abstract int getLayoutId();
protected abstract void initView();
}
接下来只需要继承这个BaseFragment,并实现getLayoutId()、initView()两个方法,getLayoutId()设置Fragment的布局文件,initView()初始化View。topHeight()根据需求判断是否重写
2.2 将内容布局延伸到状态栏(适合Activity 4.4及以上版本)
首先需要隐藏掉ActionBar,可以以下的style隐藏掉ActionBar
<style name="AppBaseTheme" parent="Theme.AppCompat.Light.DarkActionBar">
<item name="windowActionBar">false</item>
<item name="windowNoTitle">true</item>
</style>
在Activity的onCreate方法中,在setContentView之前调用如下代码:
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
getWindow().getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN | View.SYSTEM_UI_FLAG_LAYOUT_STABLE);
}
//还需要以下代码设置透明状态栏:
setTransparentForWindow(this);
public static void setTransparentForWindow(Activity activity) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
activity.getWindow().setStatusBarColor(Color.TRANSPARENT);
} else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
activity.getWindow()
.setFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS, WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
}
}
通过以上代码就可以实现将内容布局延伸到状态栏了。将内容布局延伸到状态栏大致两种情况:一种是不嵌套Fragment的Activity ; 另一种是嵌套Fragment的Activity,有的Fragment中可能需要延伸到状态栏,有的不需要延伸到状态栏。对于第一种情况。直接用上面代码就可以了。对于第二种情况除了对上面设置外,还需要在Fragment单独设置。对于需要延伸到状态栏,由于内容延伸到状态栏中,要注意布局(对于android 4.4以下的布局和android 4.4及以上的布局相差一个状态栏的高度),对于不需要延伸到状态栏的Fragment.可以重写topHeight()方法,如下:
@Override
protected int topHeight() {
if(Build.VERSION.SDK_INT>=Build.VERSION_CODES.KITKAT){
return StatusBarUtil.getStatusBarHeight(getContext());
}
return super.topHeight();
}
但这种方法只适合状态栏颜色为白色或透明的情况,状态栏颜色为其他颜色的可以在Fragment中添加一个和状态栏高度一样的View并设置颜色,这样就解决了,如下代码:
@Override
protected void initView() {
//view_status为状态栏一样高度的View
view_status=baseView.findViewById(R.id.view_status);
if(Build.VERSION.SDK_INT>=Build.VERSION_CODES.KITKAT){
view_status.setVisibility(View.VISIBLE);
ViewGroup.LayoutParams layoutParams=view_status.getLayoutParams();
layoutParams.height=StatusBarUtil.getStatusBarHeight(getContext());
}else {
view_status.setVisibility(View.GONE);
}
}