Android TextView的颜色和字体自适应

前言

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

1. 字体大小自适应

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

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

ini 复制代码
android:autoSizeMaxTextSize="22dp"  
android:autoSizeMinTextSize="8dp"  
android:autoSizeTextType="uniform"

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

ini 复制代码
android:layout_width="50dp"  
android:layout_height="20dp"
ini 复制代码
android:layout_width="50dp"  
android:layout_height="30dp"
ini 复制代码
android:layout_width="50dp"  
android:layout_height="50dp"
ini 复制代码
android:layout_width="80dp"  
android:layout_height="80dp"

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

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

2. 字体颜色自适应

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

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

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

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

灰度值的计算公式 灰度值 = 0.2126 * R + 0.7152 * G + 0.0722 * B

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

kotlin 复制代码
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值

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

获取背景直接调用

ini 复制代码
val d = textView?.background

根据Drawable去获取颜色

kotlin 复制代码
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判断是否为空,为空就循环一次,不为空直接获取颜色。我这里就不演示代码了。

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

kotlin 复制代码
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
}

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

ini 复制代码
android:background="#000000"
ini 复制代码
android:background="#ffffff"
ini 复制代码
android:background="#3377ff"
ini 复制代码
android:background="#ee7700"
相关推荐
天空中的野鸟39 分钟前
Android音频采集
android·音视频
小白也想学C2 小时前
Android 功耗分析(底层篇)
android·功耗
曙曙学编程2 小时前
初级数据结构——树
android·java·数据结构
闲暇部落4 小时前
‌Kotlin中的?.和!!主要区别
android·开发语言·kotlin
诸神黄昏EX6 小时前
Android 分区相关介绍
android
大白要努力!7 小时前
android 使用SQLiteOpenHelper 如何优化数据库的性能
android·数据库·oracle
Estar.Lee7 小时前
时间操作[取当前北京时间]免费API接口教程
android·网络·后端·网络协议·tcp/ip
Winston Wood7 小时前
Perfetto学习大全
android·性能优化·perfetto
Dnelic-10 小时前
【单元测试】【Android】JUnit 4 和 JUnit 5 的差异记录
android·junit·单元测试·android studio·自学笔记
Eastsea.Chen13 小时前
MTK Android12 user版本MtkLogger
android·framework