前言
所謂撕裂這里指的是側滑返回上一級頁面時,狀態欄不隨內容布局移動,造成狀態欄和內容布局不聯動,相分離的問題。
小紅書APP設置頁面 | 微信APP頁面 |
---|---|
xhs.gif
|
wx.gif
|
問題分析
此處以小紅書APP設置頁面為例進行分析,通過uiautomatorviewer
工具查看頁面布局,布局結構如下:
小紅書設置頁面.png
- 頁面使用的是系統狀態欄(
id
為android:id/statusBarBackground
),狀態欄背景顏色為白色。 - 側滑布局不包含系統狀態欄,側滑返回時,內容布局在滑動,系統狀態欄固定不動。
解決辦法
要想使側滑時狀態欄和內容布局一起滑動,一般的解決辦法如下:
- 設置系統狀態欄背景顏色為透明。
- 頁面布局延伸到狀態欄區域,由頁面負責狀態欄的繪制,側滑布局包含該狀態欄區域。
- 自定義View填充狀態欄區域或設置頁面的頂部布局如TitleBar的topPadding為狀態欄高度。
代碼實現
此處假設使用的側滑控件為SwipeBackLayout,此控件是在onPostCreate
方法里添加側滑布局,因此我們覆蓋onPostCreate
方法,在此方法里適配狀態欄即可。
- 基類
BaseActivity
繼承SwipeBackActivity
,定義一些狀態欄和導航欄相關的方法。
/**
* 獲取自定義的狀態欄View,如為null,則采用默認的View填充狀態欄區域
*/
protected open fun getStatusBarView(): View? {
return null
}
/**
* 狀態欄顏色
*/
protected open fun statusBarColor(): Int {
return R.color.white
}
/**
* 導航欄顏色
*/
protected open fun navigationBarColor(): Int {
return R.color.white
}
/**
* 狀態欄字體顏色是否高亮
*/
protected open fun statusBarDarkFont(): Boolean {
return true
}
/**
* 導航欄字體顏色是否高亮
*/
protected open fun navigationBarDarkFont(): Boolean {
return true
}
- 覆蓋
onPostCreate
方法,設置狀態欄和導航欄背景和字體顏色。
@Override
override fun onPostCreate(savedInstanceState: Bundle?) {
super.onPostCreate(savedInstanceState)
window.clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS)
window.clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION)
window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS)
/**
* 設置系統狀態欄背景顏色為透明
*/
window.statusBarColor = Color.TRANSPARENT
var uiFlags = View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN or View.SYSTEM_UI_FLAG_LAYOUT_STABLE
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
/**
* 高亮狀態欄字體
*/
if(statusBarDarkFont()) {
uiFlags = uiFlags or View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR
}
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
/**
* 高亮導航欄字體
*/
if(navigationBarDarkFont()) {
uiFlags = uiFlags or View.SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR
}
}
window.decorView.systemUiVisibility = uiFlags
/**
* 獲取狀態欄高度
*/
val statusBarHeight = ScreenHelper.getStatusbarHeight(this)
/**
* 獲取狀態欄View
*/
var statusBarView=getStatusBarView()
if(statusBarView==null) {
statusBarView = View(this)
statusBarView.id = R.id.status_bar_id
val contentView = window.decorView.findViewById(android.R.id.content) as ViewGroup
/**
* 設置Padding
*/
contentView.getChildAt(0).setPadding(0, statusBarHeight, 0, 0)
/**
* 添加狀態欄布局
*/
contentView.addView(statusBarView, ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, statusBarHeight))
}
else{
setStatusBarHeight(statusBarView)
}
statusBarView.setBackgroundColor(ContextCompat.getColor(applicationContext,statusBarColor()))
window.navigationBarColor = ContextCompat.getColor(applicationContext,navigationBarColor())
}
/**
* 設置View高度為狀態欄高度
*/
fun setStatusBarHeight(view:View?) {
if(view==null){
return
}
val fixHeight=ScreenHelper.getStatusbarHeight(this)
var layoutParams = view.layoutParams
if (layoutParams == null) {
layoutParams = ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT)
}
if (layoutParams.height == ViewGroup.LayoutParams.WRAP_CONTENT || layoutParams.height == ViewGroup.LayoutParams.MATCH_PARENT) {
val finalLayoutParams = layoutParams
view.post(Runnable {
finalLayoutParams.height = fixHeight
view.layoutParams = finalLayoutParams
})
} else {
layoutParams.height = fixHeight
view.layoutParams = layoutParams
}
}
實現效果
1 | 2 |
---|---|
1.gif
|
2.gif
|