android:left 用于偏移当前 item 内容的绘制起点,使其左边缘相对于 layer-list 左边界右移指定像素;但需配合显式尺寸(如<size>)才能生效,否则因内容宽高为0而不可见。

layer-list 中 item 的 android:left 是什么作用?
它不是给整个 <item> 设置 margin,而是让该图层内容(比如一个 <shape>)的左边缘,相对于 layer-list 整体左边界向右偏移指定像素。这个偏移只影响当前 item 的绘制起点,不影响其他 item,也不改变 layer-list 自身尺寸。
- 如果 item 内是
<bitmap>,android:left会让图片左边缘右移,可能露出背景或其它下层图层 - 如果 item 是空的
<shape>且没设 size,偏移后可能完全不可见——因为 shape 默认尺寸为 0 - 该属性只在 API 1+ 支持,无兼容性问题,但对 vector drawable 不生效(vector 需用
android:viewportWidth和android:translateX等控制)
为什么设置了 android:left 却没看到效果?
最常见原因是:图层自身没有「可显示的宽度」。比如一个 <shape android:shape="rectangle"> 没配 android:width 或内部 <size>,那它渲染出来就是 0px 宽,再怎么左移也看不见。
- 必须显式设置尺寸:
<size android:width="48dp" android:height="48dp"/> - 或者用
<bitmap>并确保android:src有图、且未设android:gravity="center"抵消偏移 - 检查父容器是否设置了
android:paddingLeft或约束布局导致视觉混淆 -
android:left值为负数是允许的,会向左溢出,但超出 layer-list 边界的部分会被裁剪(除非父 View 开启android:clipChildren="false")
android:left 和 android:gravity 在同一个 item 里怎么共存?
android:gravity 控制的是 item 内容(如 bitmap 或 shape)在其分配到的「绘制区域」内的对齐方式;而 android:left 是先把这个绘制区域整体右移。两者顺序是:先按 left/top/right/bottom 定位区域,再在该区域内按 gravity 对齐内容。
- 例如:item 设了
android:left="20dp"和android:gravity="right",且内部是个 30dp 宽的 bitmap,则 bitmap 右边缘会贴在 layer-list 左边界 + 20dp 的位置上 - 若同时设
android:right="10dp",则绘制区域宽度 = layer-list 总宽 − 20dp − 10dp;此时gravity="center"才真正在该区域内居中 - 避免滥用
gravity来“模拟”偏移——它不改变区域位置,只改内容摆放,容易和 left/top 冲突
替代方案:什么时候不该用 android:left?
当你要做的是「响应式偏移」(比如适配不同屏幕密度)、或需要动画控制、或图层要跟随文字/控件动态对齐时,XML 静态 android:left 就不够用了。
- 运行时修改:用
LayerDrawable.setLayerInset(),传入 layer index、left、top、right、bottom - 组合 Drawable:把需要偏移的 drawable 包一层
InsetDrawable,更语义清晰,也支持动态 inset - ConstraintLayout 背景:直接用 View 的 background + layout_marginStart,比 layer-list 更灵活
- 注意:所有 inset 类操作都会增加绘制层级和计算开销,简单图标建议直接切多套资源或用 VectorDrawable 的
android:translateX
<size> —— 以为设了 android:left 图层就“存在”,结果 runtime 里压根没渲染出来。










