前言
最近比较忙,没有时间去梳理一些硬核的东西,今天就来分享一些简单有意思的技巧。拿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"