Android 5忽略Drawable XML中gravity属性致图标居中的修复方法
Android 5.x(对应API 21、22)的LayerDrawable实现存在原生平台Bug:当<item>节点同时配置android:width、android:height尺寸属性与android:gravity定位属性时,gravity定位逻辑会被直接忽略,内部的drawable会默认居中渲染,这就是图标显示在中间的原因,该缺陷在Android 6.0(API 23)及以上系统版本中已被官方修复。
以下两种方案均为原生实现,不需要引入额外依赖,可以全版本正常生效:
方案1:嵌套
<bitmap>标签配置定位(推荐,无需手动计算边距)
直接修改layer-list中图标对应的item节点,去掉item上的宽高、gravity属性,在节点内部嵌套bitmap标签承载图标,把gravity配置转移到bitmap标签上即可。修改后的完整drawable代码如下:<?xml version="1.0" encoding="utf-8"?> <selector xmlns:android="http://schemas.android.com/apk/res/android"> <item> <layer-list> <item> <shape> <padding android:left="8dp" android:right="8dp" /> <stroke android:color="@color/somecolor" android:width="2dp" /> </shape> </item> <item> <bitmap android:src="@drawable/ic_keyboard_arrow_down_text_color_24dp" android:gravity="right|center_vertical" /> </item> </layer-list> </item> </selector>该方案的原理是
<bitmap>标签自身的gravity解析逻辑不受LayerDrawable的Bug影响,会自动沿用图标原始尺寸,在全版本Android系统上都能按指定规则摆放图标,不需要手动计算边距适配。方案2:通过inset边距属性替代gravity定位
去掉图标item上的gravity和宽高属性,通过android:right、android:top、android:bottom属性配置边距,把图标约束到右侧垂直居中的位置。示例代码如下:<item android:drawable="@drawable/ic_keyboard_arrow_down_text_color_24dp" android:right="8dp" android:top="12dp" android:bottom="12dp" android:left="0dp"> </item>注意该方案需要根据使用该背景的视图实际高度手动计算上下边距:比如视图高度为48dp,24dp尺寸的图标垂直居中时上下边距为
(48dp - 24dp)/2 = 12dp,右侧边距保持和shape配置的8dp内边距对齐即可。
内容的提问来源于stack exchange,提问作者casolorz

