Android TextView的颜色和字体自适应

发布于:2024-04-28 ⋅ 阅读:(19) ⋅ 点赞:(0)

前言

最近比较忙,没有时间去梳理一些硬核的东西,今天就来分享一些简单有意思的技巧。拿TextView来说,平时我们都会在特定的场景去设置它的字体颜色和字体大小。那么有没有一种办法能够一劳永逸不用每次都去设置,能让TextView自己去根据自身的控件属性去自适应颜色和大小呢?当然是有的,这里可以简单的分享一些思路。

1. 字体大小自适应

TextView可以根据让字体的大小随着宽高进行自适应。

设置大小自适应的方式很简单,只需要添加这3行代码即可

android:autoSizeMaxTextSize="22dp"  
android:autoSizeMinTextSize="8dp"  
android:autoSizeTextType="uniform"

我们可以来看看效果,我给宽高都设置不同的值,能看到字体大小变化的效果

android:layout_width="50dp"  
android:layout_height="20dp"

image.png

android:layout_width="50dp"  
android:layout_height="30dp"

image.png

android:layout_width="50dp"  
android:layout_height="50dp"

image.png

android:layout_width="80dp"  
android:layout_height="80dp"

image.png

最后这里可以看到autoSizeMaxTextSize的效果

这里可以多提一句,一般这种字体随宽高自适应的场景在正常开发中比较少见。如果你的项目合理的话,一般字体的大小都是固定那几套,所以把字体大小定义到资源文件中,甚至通过style的方式去设置,才是最节省时间的方式。

2. 字体颜色自适应

关于字体的颜色自适应,如果你真想把这套东西搞起来,你就需要对“颜色”这个概念有一定的深层次的了解。我这里就只简单做一些效果来举例。

我这里演示Textview根据背景颜色来自动设置字体颜色是白色还是黑色,当背景颜色是暗色时(比如黑色),字体颜色变成白色,当背景颜色是亮色时(比如白色),字体颜色变成黑色。

那么首先需要有个概念:我怎么判断背景是亮色还是暗色?

这就需要对颜色有一定的理解。要判断一个颜色是暗色还是亮色,可以通过计算颜色的亮度来实现。一种常见的方法是将RGB颜色值转换为灰度值,然后根据灰度值来判断颜色的深浅程度。
灰度值的计算公式 灰度值 = 0.2126 * R + 0.7152 * G + 0.0722 * B

根据这个公式,我们能封装一个判断颜色是否是亮色的方法

private fun isLightColor(color: Int): Boolean {  
    val r = color shr 16 and 0xFF  
    val g = color shr 8 and 0xFF  
    val b = color and 0xFF  
    val luminance = (0.2126 * r + 0.7152 * g + 0.0722 * b) / 255  
    return luminance > 0.5
}

如果觉得这个判断不太符合你心里的预期,可以修改最后一行的luminance > 0.5值

下一步,我们需要获取控件的背景,然后从背景中获取颜色值。

获取背景直接调用

val d = textView?.background

根据Drawable去获取颜色

private fun getColorByDrawable(d : Drawable) : Int{  
    val bitmap = Bitmap.createBitmap(  
        textView?.width ?: 0,  
        textView?.height ?: 0,  
        Bitmap.Config.ARGB_8888  
    )
    val canvas = Canvas(bitmap)  
    d.setBounds(0, 0, canvas.width, canvas.height)  
    d.draw(canvas)  
    return bitmap.getPixel(0, 0)  
}

注意,我这里不考虑渐变色的情况,只是考虑单色的情况,所以x和y是传0,一般对于复杂的渐变色也不好做适配,但是对于background分边框和填充两种颜色的情况,一般文字都是显示在填充区域,这时候的x和y可以去根据边框宽度去加个偏移量(总之可以灵活应变)

还有一种场景,对于TextView没背景颜色,是它的父布局有背景颜色的情况,可以循环去调用父布局的view.background判断是否为空,为空就循环一次,不为空直接获取颜色。我这里就不演示代码了。

这里先把全部代码贴出来(都是用了最简单的方式)

override fun onCreate(savedInstanceState: Bundle?) {  
    super.onCreate(savedInstanceState)  
    setContentView(R.layout.activity_demo_text)  
  
    textView = findViewById(R.id.tv)  
    val d = textView?.background  
    textView?.post {  
        if (d != null){  
            if (isLightColor(getColorByDrawable(d))){  
                textView?.setTextColor(resources.getColor(R.color.black))  
            }else{  
                textView?.setTextColor(resources.getColor(R.color.white))  
            }  
        }  
    }  
}

private fun getColorByDrawable(d : Drawable) : Int{  
    val bitmap = Bitmap.createBitmap(  
        textView?.width ?: 0,  
        textView?.height ?: 0,  
        Bitmap.Config.ARGB_8888  
    )
    val canvas = Canvas(bitmap)  
    d.setBounds(0, 0, canvas.width, canvas.height)  
    d.draw(canvas)  
    return bitmap.getPixel(0, 0)  
}

private fun isLightColor(color: Int): Boolean {  
    val r = color shr 16 and 0xFF  
    val g = color shr 8 and 0xFF  
    val b = color and 0xFF  
    val luminance = (0.2126 * r + 0.7152 * g + 0.0722 * b) / 255  
    return luminance > 0.5
}

然后改几个背景色来看看效果

android:background="#000000"

image.png

android:background="#ffffff"

image.png

android:background="#3377ff"

image.png

android:background="#ee7700"

image.png


网站公告

今日签到

点亮在社区的每一天
去签到