inset 标签只能用于 drawable XML 文件,不可直接写在 layout 中;必须作为根元素或嵌套在 layer-list、selector 等 Drawable 容器内,且四个 inset 属性需为 dimension 类型(如 dp/sp),不可用纯数字或 integer 资源。

inset 标签必须用在 drawable XML 文件里,不能直接写在 layout 中
很多人一上来就在 activity_main.xml 里写 <inset>,结果毫无效果——inset 不是 View 属性,也不是布局标签,它只作用于 Drawable 资源。你得新建一个 res/drawable/inset_bg.xml 这类文件,再把它设为 View 的 android:background 或 app:srcCompat(配合 VectorDrawable)。
常见错误现象:inset 写对了但界面没变化,八成是放错了位置;或者用了 android:drawableLeft 这类属性直接引用 inset XML,而该属性只接受原始 Drawable,不支持嵌套层级。
-
inset必须作为根元素或嵌套在layer-list、selector等 Drawable 容器内 - 不能用在
values/colors.xml或values/dimens.xml里 - 如果目标是给
TextView的 compound drawable 加内边距,得先用inset包一层 drawable,再通过setCompoundDrawablesWithIntrinsicBounds()动态设置
inset 的四个方向参数不是像素值,而是可带单位的尺寸引用
你写 android:insetLeft="12dp" 没问题,但写 android:insetLeft="12" 就会报错:AAPT 会把它当纯数字,而系统要求它是 dimension 类型。更隐蔽的坑是直接引用 @dimen/spacing_s —— 只要这个 dimen 定义的是 <dimen name="spacing_s">8dp</dimen>,就完全合法;但如果误写成 <integer name="spacing_s">8</integer>,运行时会崩溃,提示 Resource ID #0x7f060000 is not a valid dimension。
- 支持单位:dp、sp、px、mm、in,不支持 % 或无单位数字
- 所有四个属性(
insetLeft、insetTop、insetRight、insetBottom)都可单独设置,未声明的默认为 0 - 如果想让 inset 随屏幕密度缩放,优先用 dp;固定像素场景(如与 1px 分割线对齐)才用 px
<inset xmlns:android="http://schemas.android.com/apk/res/android"
android:drawable="@drawable/ic_star"
android:insetLeft="16dp"
android:insetTop="4dp"
android:insetRight="16dp" />
和 padding 的本质区别:inset 改的是 Drawable 自身绘制区域,不是 View 的内容边界
这是最常被混淆的点。android:padding 是 View 的属性,影响的是子 View 或文字内容的位置;而 inset 修改的是 Drawable 的内部绘制范围,比如一个 VectorDrawable 原本铺满整个背景,加了 insetTop="24dp" 后,它的顶部 24dp 区域就“空出来”了,实际图形只从下方开始绘制——这会影响点击热区、阴影投射、甚至 ClipPath 的计算起点。
- 如果你发现按钮点击区域变小了,但视觉上图标没动,很可能是误用
inset替代了padding - 和
scale、rotate等 Drawable 转换标签组合使用时,inset总是先执行(因为它是外层容器),所以缩放基于 inset 后的尺寸 - 在
MaterialButton中用app:icon时,若图标太小,别急着加inset,先检查app:iconGravity和app:iconPadding
兼容性注意:Android 5.0+ 完全支持,但 VectorDrawable 的 inset 需额外声明 tint 行为
纯色 ShapeDrawable 或 PNG 套 inset 没问题,但如果是 VectorDrawable,你会发现 tint 不生效或颜色错位。这是因为 inset 包裹后,系统默认把 tint 应用到整个包裹容器,而不是内部 vector。解决方案是在 inset 外再套一层 ripple 或 selector,或者改用 android:drawableTint 属性(API 23+)而非 tint 属性。
- 低于 API 21 的设备无法解析
inset,会直接 crash(Resources$NotFoundException),必须提供drawable-v21/专用资源 - 使用
AppCompatDelegate.setCompatVectorFromSourceEnabled(true)可缓解部分 vector 兼容问题,但不解决 inset 本身 - 动态创建 inset drawable 时,要用
InsetDrawable构造函数,传入原始 drawable 和Rect边界,别用getDrawable(R.drawable.xxx)直接取——后者在 Android 9+ 上可能返回缓存实例,导致 inset 参数失效










