要实现图片平铺,必须使用带tilemode="repeat"的bitmap drawable资源(如res/drawable/bg_tile.xml),而非直接在imageview中用android:src或android:background;api 23+才支持xml中设置tilemode,低版本需代码调用mutate()后设tilemodex/y。

android:src 和 android:background 都不能直接平铺图片
XML 中用 android:src 或 android:background 引入一张 Bitmap,默认是拉伸或居中显示,不是平铺。想实现平铺(tiling),必须换思路:用 BitmapDrawable 配合 tileMode,且只能通过代码或 XML 定义 drawable 资源来实现。
- 直接在
ImageView的 XML 里写android:background="@drawable/xxx"是可行的,但前提是@drawable/xxx是一个带tileMode的bitmap标签定义 -
tileMode只支持"disabled"、"clamp"、"repeat"、"mirror",常用的是"repeat" - 注意:API 23+ 才支持在 XML 中直接写
tileMode;低版本必须用代码设置setTileModeX/setTileModeY - 平铺对性能影响不大,但若图片本身分辨率高、又没做尺寸裁剪,可能触发大量重复绘制,建议用小尺寸图(如 8×8 或 16×16 像素)作为平铺单元
XML 中用 bitmap 标签开启平铺和抗锯齿
bitmap 是 drawable 资源的一种 XML 形式,支持 tileMode 和 antialias,但它不是直接写在布局 XML 里,而是单独放在 res/drawable/ 下,再被引用。
- 新建文件
res/drawable/bg_tile.xml,内容如下:
<?xml version="1.0" encoding="utf-8"?>
<bitmap xmlns:android="http://schemas.android.com/apk/res/android"
android:src="@drawable/pattern_dot"
android:tileMode="repeat"
android:antialias="true" />
-
android:antialias="true"对 bitmap 边缘做抗锯齿,仅在缩放或旋转时生效;静态展示下几乎看不出差别,但配合scaleType="matrix"或动画时有用 -
android:dither="true"(可选)能改善颜色过渡带状感,尤其在低端屏上,但会略微增加内存开销 - 这张
@drawable/pattern_dot必须是 PNG,且推荐无透明通道或 Alpha 清晰——带半透边缘的图在平铺时容易出现接缝色差
Java/Kotlin 代码中动态启用 tileMode 更灵活
XML 方式受限于 API 级别和复用场景,实际开发中常需要运行时切换平铺开关或调整模式,这时必须用代码。
- 获取背景 drawable 后强转为
BitmapDrawable,再调用getBitmap()获取原图 - 不能直接对
BitmapDrawable调setTileModeX,得先用mutate()防止共享状态污染 - 正确写法(Kotlin 示例):
val drawable = imageView.background
if (drawable is BitmapDrawable) {
val mutated = drawable.mutate()
(mutated as BitmapDrawable).tileModeX = Shader.TileMode.REPEAT
(mutated as BitmapDrawable).tileModeY = Shader.TileMode.REPEAT
}
- 注意:
mutate()必须在设tileMode前调用,否则无效;且只对当前实例生效,不影响其他引用同一资源的地方 - 如果图片来自网络或 Asset,需先解码为
Bitmap,再构建BitmapDrawable,此时antialias要靠Paint.setAntiAlias(true)在自定义Drawable中控制
常见错误:平铺不生效或锯齿明显
最常遇到的两个现象:图片只显示一次、边缘毛刺严重。根本原因往往不在参数本身,而在资源或使用链路上。
- 平铺不生效 → 检查是否误把
bitmapXML 放在res/drawable-v24/下导致低版本加载失败,回退到默认 drawable;统一放res/drawable/ - 锯齿明显 →
antialias="true"不起作用?确认该 drawable 是否被套在layer-list或state-list中——嵌套层级过深时,父容器可能覆盖子项的抗锯齿设置 - ImageView 设置了
scaleType="centerCrop"或"fitXY",会破坏平铺逻辑,必须用"matrix"或保持默认(即不设) - 用 Android Studio 预览 XML 时,平铺可能不渲染,这是预览器限制,真机或模拟器才真实生效
真正要小心的是 tileMode 和 antialias 的组合效果依赖底层 Skia 渲染路径,不同 Android 版本行为略有差异,尤其是 Android 7.0 之前对 mirror 模式支持不完整。测的时候别只看一个机型。










