当我将 viewpager 与 Indicator Android 一起使用时,将背景状态栏更改为背景 viewpager?
Posted
技术标签:
【中文标题】当我将 viewpager 与 Indicator Android 一起使用时,将背景状态栏更改为背景 viewpager?【英文标题】:Change background status bar like as background viewpager when I using viewpager with Indicator Android? 【发布时间】:2021-11-09 18:09:33 【问题描述】:当我滑动指示器时,我想像背景 Viewpager 一样设置背景状态栏 android, 像这样::::
enter image description here
【问题讨论】:
【参考方案1】:用这个对象改变状态栏颜色:
object StatusBarUtil
val DEFAULT_STATUS_BAR_ALPHA = 112
private val FAKE_STATUS_BAR_VIEW_ID = R.id.statusbarutil_fake_status_bar_view
private val FAKE_TRANSLUCENT_VIEW_ID = R.id.statusbarutil_translucent_view
private val TAG_KEY_HAVE_SET_OFFSET = -123
@JvmOverloads
fun setColor(
activity: Activity, @ColorInt color: Int, @IntRange(
from = 0,
to = 255
) statusBarAlpha: Int = DEFAULT_STATUS_BAR_ALPHA
)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP)
activity.window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS)
activity.window.clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS)
activity.window.statusBarColor = calculateStatusColor(color, statusBarAlpha)
else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT)
activity.window.addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS)
val decorView = activity.window.decorView as ViewGroup
val fakeStatusBarView = decorView.findViewById<View>(FAKE_STATUS_BAR_VIEW_ID)
if (fakeStatusBarView != null)
if (fakeStatusBarView.visibility == View.GONE)
fakeStatusBarView.visibility = View.VISIBLE
fakeStatusBarView.setBackgroundColor(calculateStatusColor(color, statusBarAlpha))
else
decorView.addView(createStatusBarView(activity, color, statusBarAlpha))
setRootView(activity)
@JvmOverloads
fun setColorForSwipeBack(
activity: Activity, @ColorInt color: Int,
@IntRange(from = 0, to = 255) statusBarAlpha: Int = DEFAULT_STATUS_BAR_ALPHA
)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT)
val contentView = activity.findViewById<View>(android.R.id.content) as ViewGroup
val rootView = contentView.getChildAt(0)
val statusBarHeight = getStatusBarHeight(activity)
if (rootView != null && rootView is CoordinatorLayout)
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP)
rootView.fitsSystemWindows = false
contentView.setBackgroundColor(calculateStatusColor(color, statusBarAlpha))
val isNeedRequestLayout = contentView.paddingTop < statusBarHeight
if (isNeedRequestLayout)
contentView.setPadding(0, statusBarHeight, 0, 0)
rootView.post rootView.requestLayout()
else
rootView.setStatusBarBackgroundColor(
calculateStatusColor(
color,
statusBarAlpha
)
)
else
contentView.setPadding(0, statusBarHeight, 0, 0)
contentView.setBackgroundColor(calculateStatusColor(color, statusBarAlpha))
setTransparentForWindow(activity)
fun setColorNoTranslucent(activity: Activity, @ColorInt color: Int)
setColor(activity, color, 0)
@Deprecated("")
fun setColorDiff(activity: Activity, @ColorInt color: Int)
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT)
return
transparentStatusBar(activity)
val contentView = activity.findViewById<View>(android.R.id.content) as ViewGroup
val fakeStatusBarView = contentView.findViewById<View>(FAKE_STATUS_BAR_VIEW_ID)
if (fakeStatusBarView != null)
if (fakeStatusBarView.visibility == View.GONE)
fakeStatusBarView.visibility = View.VISIBLE
fakeStatusBarView.setBackgroundColor(color)
else
contentView.addView(createStatusBarView(activity, color))
setRootView(activity)
@JvmOverloads
fun setTranslucent(
activity: Activity, @IntRange(
from = 0,
to = 255
) statusBarAlpha: Int = DEFAULT_STATUS_BAR_ALPHA
)
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT)
return
setTransparent(activity)
addTranslucentView(activity, statusBarAlpha)
fun setTranslucentForCoordinatorLayout(
activity: Activity,
@IntRange(from = 0, to = 255) statusBarAlpha: Int
)
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT)
return
transparentStatusBar(activity)
addTranslucentView(activity, statusBarAlpha)
fun setTransparent(activity: Activity)
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT)
return
transparentStatusBar(activity)
setRootView(activity)
@Deprecated("")
fun setTranslucentDiff(activity: Activity)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT)
activity.window.addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS)
setRootView(activity)
fun setColorNoTranslucentForDrawerLayout(
activity: Activity,
drawerLayout: DrawerLayout,
@ColorInt color: Int
)
setColorForDrawerLayout(activity, drawerLayout, color, 0)
@JvmOverloads
fun setColorForDrawerLayout(
activity: Activity, drawerLayout: DrawerLayout, @ColorInt color: Int,
@IntRange(from = 0, to = 255) statusBarAlpha: Int = DEFAULT_STATUS_BAR_ALPHA
)
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT)
return
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP)
activity.window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS)
activity.window.clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS)
activity.window.statusBarColor = Color.TRANSPARENT
else
activity.window.addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS)
val contentLayout = drawerLayout.getChildAt(0) as ViewGroup
val fakeStatusBarView = contentLayout.findViewById<View>(FAKE_STATUS_BAR_VIEW_ID)
if (fakeStatusBarView != null)
if (fakeStatusBarView.visibility == View.GONE)
fakeStatusBarView.visibility = View.VISIBLE
fakeStatusBarView.setBackgroundColor(color)
else
contentLayout.addView(createStatusBarView(activity, color), 0)
if (contentLayout !is LinearLayout && contentLayout.getChildAt(1) != null)
contentLayout.getChildAt(1)
.setPadding(
contentLayout.paddingLeft,
getStatusBarHeight(activity) + contentLayout.paddingTop,
contentLayout.paddingRight,
contentLayout.paddingBottom
)
setDrawerLayoutProperty(drawerLayout, contentLayout)
addTranslucentView(activity, statusBarAlpha)
private fun setDrawerLayoutProperty(
drawerLayout: DrawerLayout,
drawerLayoutContentLayout: ViewGroup
)
val drawer = drawerLayout.getChildAt(1) as ViewGroup
drawerLayout.fitsSystemWindows = false
drawerLayoutContentLayout.fitsSystemWindows = false
drawerLayoutContentLayout.clipToPadding = true
drawer.fitsSystemWindows = false
@Deprecated("")
fun setColorForDrawerLayoutDiff(
activity: Activity,
drawerLayout: DrawerLayout,
@ColorInt color: Int
)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT)
activity.window.addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS)
val contentLayout = drawerLayout.getChildAt(0) as ViewGroup
val fakeStatusBarView = contentLayout.findViewById<View>(FAKE_STATUS_BAR_VIEW_ID)
if (fakeStatusBarView != null)
if (fakeStatusBarView.visibility == View.GONE)
fakeStatusBarView.visibility = View.VISIBLE
fakeStatusBarView.setBackgroundColor(
calculateStatusColor(
color,
DEFAULT_STATUS_BAR_ALPHA
)
)
else
contentLayout.addView(createStatusBarView(activity, color), 0)
if (contentLayout !is LinearLayout && contentLayout.getChildAt(1) != null)
contentLayout.getChildAt(1).setPadding(0, getStatusBarHeight(activity), 0, 0)
setDrawerLayoutProperty(drawerLayout, contentLayout)
@JvmOverloads
fun setTranslucentForDrawerLayout(
activity: Activity, drawerLayout: DrawerLayout,
@IntRange(from = 0, to = 255) statusBarAlpha: Int = DEFAULT_STATUS_BAR_ALPHA
)
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT)
return
setTransparentForDrawerLayout(activity, drawerLayout)
addTranslucentView(activity, statusBarAlpha)
fun setTransparentForDrawerLayout(activity: Activity, drawerLayout: DrawerLayout)
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT)
return
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP)
activity.window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS)
activity.window.clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS)
activity.window.statusBarColor = Color.TRANSPARENT
else
activity.window.addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS)
val contentLayout = drawerLayout.getChildAt(0) as ViewGroup
if (contentLayout !is LinearLayout && contentLayout.getChildAt(1) != null)
contentLayout.getChildAt(1).setPadding(0, getStatusBarHeight(activity), 0, 0)
setDrawerLayoutProperty(drawerLayout, contentLayout)
@Deprecated("")
fun setTranslucentForDrawerLayoutDiff(activity: Activity, drawerLayout: DrawerLayout)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT)
activity.window.addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS)
val contentLayout = drawerLayout.getChildAt(0) as ViewGroup
contentLayout.fitsSystemWindows = true
contentLayout.clipToPadding = true
val vg = drawerLayout.getChildAt(1) as ViewGroup
vg.fitsSystemWindows = false
drawerLayout.fitsSystemWindows = false
fun setTransparentForImageView(activity: Activity, needOffsetView: View)
setTranslucentForImageView(activity, 0, needOffsetView)
fun setTranslucentForImageView(activity: Activity, needOffsetView: View)
setTranslucentForImageView(activity, DEFAULT_STATUS_BAR_ALPHA, needOffsetView)
fun setTranslucentForImageView(
activity: Activity, @IntRange(from = 0, to = 255) statusBarAlpha: Int,
needOffsetView: View?
)
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT)
return
setTransparentForWindow(activity)
addTranslucentView(activity, statusBarAlpha)
if (needOffsetView != null)
val haveSetOffset = needOffsetView.getTag(TAG_KEY_HAVE_SET_OFFSET)
if (haveSetOffset != null && haveSetOffset as Boolean)
return
val layoutParams = needOffsetView.layoutParams as ViewGroup.MarginLayoutParams
layoutParams.setMargins(
layoutParams.leftMargin, layoutParams.topMargin + getStatusBarHeight(activity),
layoutParams.rightMargin, layoutParams.bottomMargin
)
needOffsetView.setTag(TAG_KEY_HAVE_SET_OFFSET, true)
fun setTranslucentForImageViewInFragment(activity: Activity, needOffsetView: View)
setTranslucentForImageViewInFragment(activity, DEFAULT_STATUS_BAR_ALPHA, needOffsetView)
fun setTransparentForImageViewInFragment(activity: Activity, needOffsetView: View)
setTranslucentForImageViewInFragment(activity, 0, needOffsetView)
fun setTranslucentForImageViewInFragment(
activity: Activity, @IntRange(from = 0, to = 255) statusBarAlpha: Int,
needOffsetView: View
)
setTranslucentForImageView(activity, statusBarAlpha, needOffsetView)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT && Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP)
clearPreviousSetting(activity)
fun hideFakeStatusBarView(activity: Activity)
val decorView = activity.window.decorView as ViewGroup
val fakeStatusBarView = decorView.findViewById<View>(FAKE_STATUS_BAR_VIEW_ID)
if (fakeStatusBarView != null)
fakeStatusBarView.visibility = View.GONE
val fakeTranslucentView = decorView.findViewById<View>(FAKE_TRANSLUCENT_VIEW_ID)
if (fakeTranslucentView != null)
fakeTranslucentView.visibility = View.GONE
@TargetApi(Build.VERSION_CODES.M)
fun setLightMode(activity: Activity)
setMIUIStatusBarDarkIcon(activity, true)
setMeizuStatusBarDarkIcon(activity, true)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M)
activity.window.decorView.systemUiVisibility = View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR or
View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
@TargetApi(Build.VERSION_CODES.M)
fun setDarkMode(activity: Activity)
setMIUIStatusBarDarkIcon(activity, false)
setMeizuStatusBarDarkIcon(activity, false)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M)
activity.window.decorView.systemUiVisibility = View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
private fun setMIUIStatusBarDarkIcon(activity: Activity, darkIcon: Boolean)
val clazz = activity.window.javaClass
try
val layoutParams = Class.forName("android.view.MiuiWindowManager\$LayoutParams")
val field = layoutParams.getField("EXTRA_FLAG_STATUS_BAR_DARK_MODE")
val darkModeFlag = field.getInt(layoutParams)
val extraFlagField =
clazz.getMethod(
"setExtraFlags",
Int::class.javaPrimitiveType,
Int::class.javaPrimitiveType
)
extraFlagField.invoke(activity.window, if (darkIcon) darkModeFlag else 0, darkModeFlag)
catch (e: Exception)
//e.printStackTrace();
private fun setMeizuStatusBarDarkIcon(activity: Activity, darkIcon: Boolean)
try
val lp = activity.window.attributes
val darkFlag =
WindowManager.LayoutParams::class.java.getDeclaredField("MEIZU_FLAG_DARK_STATUS_BAR_ICON")
val meizuFlags = WindowManager.LayoutParams::class.java.getDeclaredField("meizuFlags")
darkFlag.isAccessible = true
meizuFlags.isAccessible = true
val bit = darkFlag.getInt(null)
var value = meizuFlags.getInt(lp)
if (darkIcon)
value = value or bit
else
value = value and bit.inv()
meizuFlags.setInt(lp, value)
activity.window.attributes = lp
catch (e: Exception)
//e.printStackTrace();
///////////////////////////////////////////////////////////////////////////////////
@TargetApi(Build.VERSION_CODES.KITKAT)
private fun clearPreviousSetting(activity: Activity)
val decorView = activity.window.decorView as ViewGroup
val fakeStatusBarView = decorView.findViewById<View>(FAKE_STATUS_BAR_VIEW_ID)
if (fakeStatusBarView != null)
decorView.removeView(fakeStatusBarView)
val rootView =
(activity.findViewById<View>(android.R.id.content) as ViewGroup).getChildAt(0) as ViewGroup
rootView.setPadding(0, 0, 0, 0)
private fun addTranslucentView(
activity: Activity,
@IntRange(from = 0, to = 255) statusBarAlpha: Int
)
val contentView = activity.findViewById<View>(android.R.id.content) as ViewGroup
val fakeTranslucentView = contentView.findViewById<View>(FAKE_TRANSLUCENT_VIEW_ID)
if (fakeTranslucentView != null)
if (fakeTranslucentView.visibility == View.GONE)
fakeTranslucentView.visibility = View.VISIBLE
fakeTranslucentView.setBackgroundColor(Color.argb(statusBarAlpha, 0, 0, 0))
else
contentView.addView(createTranslucentStatusBarView(activity, statusBarAlpha))
private fun createStatusBarView(
activity: Activity,
@ColorInt color: Int,
alpha: Int = 0
): View
val statusBarView = View(activity)
val params = LinearLayout.LayoutParams(
ViewGroup.LayoutParams.MATCH_PARENT,
getStatusBarHeight(activity)
)
statusBarView.layoutParams = params
statusBarView.setBackgroundColor(calculateStatusColor(color, alpha))
statusBarView.id = FAKE_STATUS_BAR_VIEW_ID
return statusBarView
private fun setRootView(activity: Activity)
val parent = activity.findViewById<View>(android.R.id.content) as ViewGroup
var i = 0
val count = parent.childCount
while (i < count)
val childView = parent.getChildAt(i)
if (childView is ViewGroup)
childView.setFitsSystemWindows(true)
childView.clipToPadding = true
i++
private fun setTransparentForWindow(activity: Activity)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP)
activity.window.statusBarColor = Color.TRANSPARENT
activity.window
.decorView.systemUiVisibility = View.SYSTEM_UI_FLAG_LAYOUT_STABLE or
View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT)
activity.window
.setFlags(
WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS,
WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS
)
@TargetApi(Build.VERSION_CODES.KITKAT)
private fun transparentStatusBar(activity: Activity)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP)
activity.window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS)
activity.window.clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS)
activity.window.addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION)
activity.window.statusBarColor = Color.TRANSPARENT
else
activity.window.addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS)
private fun createTranslucentStatusBarView(activity: Activity, alpha: Int): View
val statusBarView = View(activity)
val params = LinearLayout.LayoutParams(
ViewGroup.LayoutParams.MATCH_PARENT,
getStatusBarHeight(activity)
)
statusBarView.layoutParams = params
statusBarView.setBackgroundColor(Color.argb(alpha, 0, 0, 0))
statusBarView.id = FAKE_TRANSLUCENT_VIEW_ID
return statusBarView
private fun getStatusBarHeight(context: Context): Int
val resourceId = context.resources.getIdentifier("status_bar_height", "dimen", "android")
return context.resources.getDimensionPixelSize(resourceId)
private fun calculateStatusColor(@ColorInt color: Int, alpha: Int): Int
if (alpha == 0)
return color
val a = 1 - alpha / 255f
var red = color shr 16 and 0xff
var green = color shr 8 and 0xff
var blue = color and 0xff
red = (red * a + 0.5).toInt()
green = (green * a + 0.5).toInt()
blue = (blue * a + 0.5).toInt()
return 0xff shl 24 or (red shl 16) or (green shl 8) or blue
并使用:
StatusBarUtil.setColor(
requireActivity(),
Color.parseColor(
"this is background color Viewpager "
),
20
)
【讨论】:
以上是关于当我将 viewpager 与 Indicator Android 一起使用时,将背景状态栏更改为背景 viewpager?的主要内容,如果未能解决你的问题,请参考以下文章
一起Talk Android吧(第三百七十八回:给ViewPager添加indicator)
java ViewPager && Fragment Study && Dots Indicator
ViewPager,ViewPager2 无限轮播功能。自定义 Indicator,支持一屏三页,支持仿魅族 banner 效果。极其简单的使用方式