You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Android使用Kaspresso测试时VectorDrawable比对失败问题咨询

问题根因
  • 尺寸不匹配:默认的hasDrawable方法加载预期VectorDrawable时,直接从资源读取未关联目标ImageView的测量参数,转Bitmap时采用drawable自身的固有宽高;而手动设置到ImageView上的VectorDrawable会被缩放适配ImageView的尺寸,两者生成的Bitmap尺寸不一致,像素比对直接失败。DataBinding设置图片时内部会自动将加载的VectorDrawable尺寸与ImageView参数做预适配,因此转出来的Bitmap和预期值尺寸一致,比对可通过。
  • Tint配置未对齐:如果你在代码中手动给ImageView设置了tint属性,但调用hasDrawable时未传入对应的tint色值ID,匹配器不会给预期drawable添加相同的tint效果,最终生成的Bitmap颜色差异导致比对失败。
  • 版本适配差异:Android 5.0以下系统中VectorDrawable的兼容包装逻辑不一致,如果手动设置时未通过DrawableCompat包装VectorDrawable,和匹配器内部包装后的预期drawable生成的Bitmap也会存在差异。
解决方案

方案1:自定义VectorDrawable专用匹配器(最稳定)

直接抛弃默认的像素比对逻辑,改为匹配VectorDrawable的ConstantState,代码示例:

fun hasVectorDrawable(@DrawableRes resId: Int): ViewAssertion {
    return ViewAssertion { view, noViewFoundException ->
        noViewFoundException?.let { throw it }
        if (view !is ImageView) {
            throw AssertionError("View is not an ImageView")
        }
        val actualDrawable = view.drawable ?: throw AssertionError("ImageView has no drawable")
        val expectedDrawable = ContextCompat.getDrawable(view.context, resId) ?: throw AssertionError("Expected drawable not found")
        // 校验ConstantState,同资源VectorDrawable的ConstantState默认一致
        if (actualDrawable.constantState != expectedDrawable.constantState) {
            throw AssertionError("Drawable does not match expected resource $resId")
        }
    }
}

使用方式:

withId<KImageView>(R.id.criticalErrorImage) {
    check(hasVectorDrawable(R.drawable.error_graphic))
}

注意:如果业务代码中对drawable调用过mutate()方法修改属性,ConstantState会发生变化,此场景下推荐使用方案2。

方案2:修改默认hasDrawable的Bitmap转换逻辑

调用hasDrawable时传入自定义的toBitmap参数,强制将两个drawable都缩放到相同尺寸再转Bitmap:

withId<KImageView>(R.id.criticalErrorImage) {
    hasDrawable(
        resId = R.drawable.error_graphic,
        toBitmap = { drawable ->
            // 可自定义统一缩放尺寸,也可读取目标ImageView的测量尺寸作为参数
            Bitmap.createScaledBitmap(drawable.toBitmap(), 200, 200, true)
        }
    )
}

方案3:补全Tint参数

如果是tint导致的比对失败,调用hasDrawable时主动传入你设置的tint色值ID即可:

withId<KImageView>(R.id.criticalErrorImage) {
    hasDrawable(
        resId = R.drawable.error_graphic,
        tintColorId = R.color.your_tint_color
    )
}

内容的提问来源于stack exchange,提问作者Filnik

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.28 03:57:03