El tema inmersivo de la barra de estado de Android cambia automáticamente el tema siguiendo el color de fondo de la barra de estado, y el tema de la barra de estado sigue el color de fondo de la barra de estado de forma adaptativa.

1. Introducción al modo de visualización de la barra de estado

El sistema Android proporciona dos modos de visualización: modo brillante y modo oscuro.

Modelo claro: el color general es brillante, es decir, el fondo es brillante y el texto y otros contenidos son oscuros.

Modelo oscuro: el color general es más oscuro, es decir, el fondo es oscuro y el texto y otros contenidos son brillantes.

2. Defectos de la barra de estado de Android

El color del contenido de la barra de estado de Android (sin color de fondo) es solo blanco y negro. Cuando está en modo brillante, es un tema negro y cuando está en modo oscuro, es un tema blanco. Por supuesto, tener sólo dos colores no es un defecto.

Cuando el color de fondo de la barra de estado cambia, debemos configurar manualmente el modo de visualización para cambiar el color de su contenido. Esto es extremadamente inconveniente, especialmente cuando el color de fondo de la barra de estado es degradado.

Por ejemplo:

Cuando se despliega WeChat, el color de fondo de la barra de estado sigue cambiando, pero el color del contenido no cambia con el tiempo, como se muestra en el cuadro rojo de la figura.

3. Ideación de soluciones 

De hecho, el color del contenido de la barra de estado es completamente adaptable. La lógica es muy simple. Cuando el fondo es oscuro, el contenido de la barra de estado será brillante; cuando el fondo es brillante, el contenido de la barra de estado será oscuro. Así que hay Es una idea general. Cada vez que se dibuja la interfaz:

  1. Obtener píxeles de la barra de estado

  2. Calcular su valor de color promedio.

  3. Determinar si es un color brillante.

  4. Si es un color brillante, configúrelo en modo brillante; de ​​lo contrario, configúrelo en modo oscuro.

4. Implementación de lógica de código específica

/**
     * 获取状态栏像素
     */
    private fun getStatusBarPixels(activity:Activity) = activity.window.decorView.let {
        it.isDrawingCacheEnabled = true
        it.buildDrawingCache()
        // 截屏
        val screenBitmap = it.getDrawingCache()
        val width = screenBitmap.width
        val height = BarUtils.getStatusBarHeight()
        val pixels = IntArray(width * height)
        // 获取状态栏区域像素
        screenBitmap.getPixels(pixels, 0, width, 0, 0, width, height)
        it.destroyDrawingCache()
        pixels
    }

    /**
     * 获取平均色值
     */
    fun getAvgColor(pixels: IntArray): Int {
        var r = 0L
        var g = 0L
        var b = 0L
        pixels.forEach {
            r += Color.red(it)
            g += Color.green(it)
            b += Color.blue(it)
        }
        r /= pixels.size
        g /= pixels.size
        b /= pixels.size
        return Color.rgb(r.toInt(), g.toInt(), b.toInt())
    }

El código anterior obtiene automáticamente el valor del color de la barra de estado del teléfono móvil y calcula el valor promedio.

Luego, el siguiente método puede pasar directamente el valor del color para cambiar dinámicamente el color del tema de la barra de estado.

/**
     * 是否为亮色
     * 可以单独传入 色值 判断是否为亮色
     */
    fun isLightColor(@ColorInt color: Int) =
        (computeLuminance(color) + 0.05).pow(2.0) > 0.15

    /**
     * 是否为亮色
     * 自动获取状态栏的色纸 判断是否为亮色
     */
    fun isLightColor(activity:Activity):Boolean{
        val pixels = getStatusBarPixels(activity)
        val color = getAvgColor(pixels)
        val computeColor = computeLuminance(color) + 0.05
        return (computeColor.pow(2.0) > 0.15)
    }

    /**
     * 颜色亮度
     */
    private fun computeLuminance(@ColorInt color: Int) =
        0.2126 * linearizeColorComponent(Color.red(color)) +
                0.7152 * linearizeColorComponent(Color.green(color)) +
                0.0722 * linearizeColorComponent(Color.blue(color))

    /**
     * 线性化颜色分量
     */
    private fun linearizeColorComponent(colorComponent: Int) = (colorComponent / 255.0).let {
        if (it <= 0.03928) it / 12.92 else ((it + 0.055) / 1.055).pow(2.4)
    }

5.Optimización del rendimiento durante la aplicación.

/**
     * 性能优化:单线程池,更新阻塞时只做最后一次更新
     */
    private val executor by lazy {
        object : ThreadPoolExecutor(1, 1, 0, TimeUnit.MILLISECONDS, ArrayBlockingQueue(1)) {
            override fun execute(command: Runnable?) {
                queue.clear()
                super.execute(command)
            }
        }
    }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        BarUtils.transparentStatusBar(this) // 需要沉浸状态栏,才能截屏至状态栏
        window.decorView.viewTreeObserver.addOnDrawListener(this)
    }

    override fun onDestroy() {
        window.decorView.viewTreeObserver.removeOnDrawListener(this)
        super.onDestroy()
    }

    override fun onDraw() {
        executor.execute {
            try {
                // 获取状态栏像素
                val pixels = getStatusBarPixels()
                // 计算平均色值
                val avgColor = getAvgColor(pixels)
                // 判断是否为亮色
                val isLight = isLightColor(avgColor)
                runOnUiThread {
                    // 设置 LightModel
                    if (!isDestroyed) BarUtils.setStatusBarLightMode(this, isLight)
                }
            } catch (_: Exception) {
            }
        }
    }

6. Ejemplo de uso general del código

class MainActivity : AppCompatActivity(), ViewTreeObserver.OnDrawListener {

    /**
     * 性能优化:单线程池,更新阻塞时只做最后一次更新
     */
    private val executor by lazy {
        object : ThreadPoolExecutor(1, 1, 0, TimeUnit.MILLISECONDS, ArrayBlockingQueue(1)) {
            override fun execute(command: Runnable?) {
                queue.clear()
                super.execute(command)
            }
        }
    }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        BarUtils.transparentStatusBar(this) // 需要沉浸状态栏,才能截屏至状态栏
        window.decorView.viewTreeObserver.addOnDrawListener(this)
    }

    override fun onDestroy() {
        window.decorView.viewTreeObserver.removeOnDrawListener(this)
        super.onDestroy()
    }

    override fun onDraw() {
        executor.execute {
            try {
                // 获取状态栏像素
                val pixels = getStatusBarPixels()
                // 计算平均色值
                val avgColor = getAvgColor(pixels)
                // 判断是否为亮色
                val isLight = isLightColor(avgColor)
                runOnUiThread {
                    // 设置 LightModel
                    if (!isDestroyed) BarUtils.setStatusBarLightMode(this, isLight)
                }
            } catch (_: Exception) {
            }
        }
    }

    /**
     * 获取状态栏像素
     */
    private fun getStatusBarPixels() = window.decorView.let {
        it.isDrawingCacheEnabled = true
        it.buildDrawingCache()
        // 截屏
        val screenBitmap = it.getDrawingCache()
        val width = screenBitmap.width
        val height = BarUtils.getStatusBarHeight()
        val pixels = IntArray(width * height)
        // 获取状态栏区域像素
        screenBitmap.getPixels(pixels, 0, width, 0, 0, width, height)
        it.destroyDrawingCache()
        pixels
    }

    /**
     * 获取平均色值
     */
    private fun getAvgColor(pixels: IntArray): Int {
        var r = 0L
        var g = 0L
        var b = 0L
        pixels.forEach {
            r += Color.red(it)
            g += Color.green(it)
            b += Color.blue(it)
        }
        r /= pixels.size
        g /= pixels.size
        b /= pixels.size
        return Color.rgb(r.toInt(), g.toInt(), b.toInt())
    }

    /**
     * 是否为亮色
     * 可以单独传入 色值 判断是否为亮色
     */
    fun isLightColor(@ColorInt color: Int) =
        (computeLuminance(color) + 0.05).pow(2.0) > 0.15

    /**
     * 是否为亮色
     * 自动获取状态栏的色纸 判断是否为亮色
     */
    fun isLightColor(activity:Activity):Boolean{
        val pixels = getStatusBarPixels(activity)
        val color = getAvgColor(pixels)
        val computeColor = computeLuminance(color) + 0.05
        return (computeColor.pow(2.0) > 0.15)
    }

    /**
     * 颜色亮度
     */
    private fun computeLuminance(@ColorInt color: Int) =
        0.2126 * linearizeColorComponent(Color.red(color)) +
                0.7152 * linearizeColorComponent(Color.green(color)) +
                0.0722 * linearizeColorComponent(Color.blue(color))

    /**
     * 线性化颜色分量
     */
    private fun linearizeColorComponent(colorComponent: Int) = (colorComponent / 255.0).let {
        if (it <= 0.03928) it / 12.92 else ((it + 0.055) / 1.055).pow(2.4)
    }
}

Lo anterior es que el tema de la barra de estado cambia automáticamente de acuerdo con el color de fondo de la barra de estado. También puede pasar el valor del color usted mismo para determinar si es un color brillante y configurar el tema de la barra de estado.

Supongo que te gusta

Origin blog.csdn.net/weitao_666/article/details/132105650
Recomendado
Clasificación