当我将 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 效果。极其简单的使用方式

ViewPage第二课为ViewPage加入标题

侧滑SilidingMenu ,ViewPager 和,PagerIndicator 冲突

自定义ViewPager的导航indecator(非常实用和主流)