Android TextView图标对齐优化:使用LayerList精准控制drawable位置

背景

我们经常使用TextView的drawableStartdrawableEnd等属性来为文字添加图标。但有时会遇到这样的问题:

xml 复制代码
<TextView
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_gravity="center"
    android:drawableStartCompat="@drawable/icon_left_arrow"
    android:includeFontPadding="false"
    android:drawablePadding="2dp"
    android:text="我是文字"
    android:textColor="@color/red"
    android:textSize="18sp" />

执行结果:

当图标尺寸大于或小于文字高度时,有时会出现图标位置偏移、视觉不居中的问题,而XML中又没有直接调整图标上下位置的属性,这时候该咋办呢?

:上述效果也可以通过代码来实现,XML中不再设置drawableXXX等属性:

ini 复制代码
<TextView
    android:id="@+id/tv_text"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_gravity="center"
    android:text="我是文字"
    android:includeFontPadding="false"
    android:textColor="@color/red"
    android:textSize="18sp" />

代码中动态设置:

kotlin 复制代码
//扩展函数
fun TextView.setLeftDrawable(leftDrawableRes: Int, widthInDp: Int = 10, heightInDp: Int = 10) {
    val drawable = ContextCompat.getDrawable(context, leftDrawableRes)

    val scale = context.resources.displayMetrics.density
    val widthPx = (widthInDp * scale + 0.5f).toInt() //dp to px
    val heightPx = (heightInDp * scale + 0.5f).toInt() //dp to px
    drawable?.setBounds(0, 0, widthPx, heightPx)
    compoundDrawablePadding = (2 * scale + 0.5f).toInt() //设置padding
    setCompoundDrawables(drawable, null, null, null)
}

//使用
mTvText.setCenteredDrawable(R.drawable.icon_left_arrow, 6, 10)

执行效果同上。

优化方式

方案1:分成两个控件

ini 复制代码
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:gravity="center">

    <ImageView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center"
        android:layout_marginEnd="2dp"
        android:src="@drawable/icon_left_arrow" />

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center"
        android:includeFontPadding="false"
        android:text="我是文字"
        android:textColor="@color/red"
        android:textSize="18sp" />
</LinearLayout>

执行结果:

把箭头单独拆成一个控件来处理,如果不居中还可以自由调整。

方案2:使用LayerList来控制(推荐)

LayerList(层叠列表)是一种Drawable资源,它允许我们将多个drawable组合在一起,并精确控制每个元素的位置、尺寸和对齐方式。实现步骤如下:

  • 创建LayerList Drawable

res/drawable/目录下创建layer_arrow_icon

xml 复制代码
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
    <item
        android:width="6dp"
        android:height="10dp" 
        android:gravity="center"
        android:drawable="@drawable/icon_left_arrow"
        android:top="1dp">
    </item>
</layer-list>

android:drawable:引用的原始图标资源,android:width/height:精确控制图标尺寸,android:top/bottom等可以调整图标上下间距。

  • 在TextView中应用优化后的Drawable
xml 复制代码
<TextView
    app:drawableStartCompat="@drawable/layer_arrow_icon"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_gravity="center"
    android:text="我是文字"
    android:drawablePadding="2dp"
    android:textColor="@color/red"
    android:textSize="18sp" />

执行效果同上面居中样式的,不再贴了。

扩展:多图层控制

比如现在需要对图标加个背景,依然可以使用多层LayerList:

xml 复制代码
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
    <!-- 背景层 -->
    <item
        android:width="16dp"
        android:height="16dp"
        android:gravity="center"
        android:top="1dp">
        <shape android:shape="oval">
            <solid android:color="#33000000" />
        </shape>
    </item>

    <item
        android:width="6dp"
        android:height="10dp"
        android:drawable="@drawable/icon_left_arrow"
        android:gravity="center"
        android:top="1dp" />
</layer-list>

执行结果:

通过LayerList优化TextView中drawable的位置和尺寸,可以动态调整图标尺寸,避免尺寸不匹配,优化居中效果,且无需修改现有布局结构。

相关推荐
●VON9 小时前
AtomGit Flutter鸿蒙客户端:数据模型
android·服务器·安全·flutter·harmonyos·鸿蒙
火柴就是我9 小时前
记录一个文本随手指缩放的功能
android
Zender Han10 小时前
Android APK 签名 v1、v2、v3、v4 有什么区别?
android
神仙别闹10 小时前
基于 PHP + MySQL学生信息管理系统
android·mysql·php
墨狂之逸才11 小时前
Android 保活机制详解 —— 从概念到实践
android
故渊at11 小时前
第二板块:Android 四大组件标准化学理 | 第十二篇:四大组件全景总结与系统服务(System Server)架构
android·架构·wpf·四大组件·system service
问心无愧051311 小时前
ctf sow web入门112
android·前端·笔记
朱涛的自习室12 小时前
Munk AI 正式开源:一个“自我进化”的 AI 测试引擎
android·人工智能·github
啦啦啦_999912 小时前
4. Transformer_3_解码器部分
android·深度学习·transformer
数智工坊13 小时前
【ROS 2 全栈入门指南三】:Action、参数与Launch文件全链路指南
android·stm32·嵌入式硬件·学习·机器人