前言
所謂撕裂這里指的是側(cè)滑返回上一級頁面時(shí),狀態(tài)欄不隨內(nèi)容布局移動,造成狀態(tài)欄和內(nèi)容布局不聯(lián)動,相分離的問題。
小紅書APP設(shè)置頁面 | 微信APP頁面 |
---|---|
xhs.gif
|
wx.gif
|
問題分析
此處以小紅書APP設(shè)置頁面為例進(jìn)行分析,通過uiautomatorviewer
工具查看頁面布局,布局結(jié)構(gòu)如下:
小紅書設(shè)置頁面.png
- 頁面使用的是系統(tǒng)狀態(tài)欄(
id
為android:id/statusBarBackground
),狀態(tài)欄背景顏色為白色。 - 側(cè)滑布局不包含系統(tǒng)狀態(tài)欄,側(cè)滑返回時(shí),內(nèi)容布局在滑動,系統(tǒng)狀態(tài)欄固定不動。
解決辦法
要想使側(cè)滑時(shí)狀態(tài)欄和內(nèi)容布局一起滑動,一般的解決辦法如下:
- 設(shè)置系統(tǒng)狀態(tài)欄背景顏色為透明。
- 頁面布局延伸到狀態(tài)欄區(qū)域,由頁面負(fù)責(zé)狀態(tài)欄的繪制,側(cè)滑布局包含該狀態(tài)欄區(qū)域。
- 自定義View填充狀態(tài)欄區(qū)域或設(shè)置頁面的頂部布局如TitleBar的topPadding為狀態(tài)欄高度。
代碼實(shí)現(xiàn)
此處假設(shè)使用的側(cè)滑控件為SwipeBackLayout,此控件是在onPostCreate
方法里添加側(cè)滑布局,因此我們覆蓋onPostCreate
方法,在此方法里適配狀態(tài)欄即可。
- 基類
BaseActivity
繼承SwipeBackActivity
,定義一些狀態(tài)欄和導(dǎo)航欄相關(guān)的方法。
/**
* 獲取自定義的狀態(tài)欄View,如為null,則采用默認(rèn)的View填充狀態(tài)欄區(qū)域
*/
protected open fun getStatusBarView(): View? {
return null
}
/**
* 狀態(tài)欄顏色
*/
protected open fun statusBarColor(): Int {
return R.color.white
}
/**
* 導(dǎo)航欄顏色
*/
protected open fun navigationBarColor(): Int {
return R.color.white
}
/**
* 狀態(tài)欄字體顏色是否高亮
*/
protected open fun statusBarDarkFont(): Boolean {
return true
}
/**
* 導(dǎo)航欄字體顏色是否高亮
*/
protected open fun navigationBarDarkFont(): Boolean {
return true
}
- 覆蓋
onPostCreate
方法,設(shè)置狀態(tài)欄和導(dǎo)航欄背景和字體顏色。
@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)
/**
* 設(shè)置系統(tǒng)狀態(tài)欄背景顏色為透明
*/
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) {
/**
* 高亮狀態(tài)欄字體
*/
if(statusBarDarkFont()) {
uiFlags = uiFlags or View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR
}
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
/**
* 高亮導(dǎo)航欄字體
*/
if(navigationBarDarkFont()) {
uiFlags = uiFlags or View.SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR
}
}
window.decorView.systemUiVisibility = uiFlags
/**
* 獲取狀態(tài)欄高度
*/
val statusBarHeight = ScreenHelper.getStatusbarHeight(this)
/**
* 獲取狀態(tài)欄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
/**
* 設(shè)置Padding
*/
contentView.getChildAt(0).setPadding(0, statusBarHeight, 0, 0)
/**
* 添加狀態(tài)欄布局
*/
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())
}
/**
* 設(shè)置View高度為狀態(tài)欄高度
*/
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
}
}
實(shí)現(xiàn)效果
1 | 2 |
---|---|
1.gif
|
2.gif
|