android 以编程方式创建的RippleDrawable看起来与其xml对应物不同

mpbci0fu  于 2023-05-05  发布在  Android
关注(0)|答案(1)|浏览(153)

我一直在试图跟踪这个问题有一段时间了。我想我以前确实找到了一个解释。不幸的是,它在代码注解中丢失了。
我想用Java创建一个Material Borderless-Button。首先,下面是框架中按钮的外观:
按钮bg(button_borderless_material.xml):

<?xml version="1.0" encoding="utf-8"?>
<ripple xmlns:android="http://schemas.android.com/apk/res/android"
        android:color="?attr/colorControlHighlight">
    <item android:id="@id/mask"
        android:drawable="@drawable/btn_default_mtrl_shape" />
</ripple>

drawable用作掩码(btn_default_mtrl_shape.xml):

<?xml version="1.0" encoding="utf-8"?>
<!-- Used as the canonical button shape. -->
<inset xmlns:android="http://schemas.android.com/apk/res/android"
       android:insetLeft="@dimen/button_inset_horizontal_material"
       android:insetTop="@dimen/button_inset_vertical_material"
       android:insetRight="@dimen/button_inset_horizontal_material"
       android:insetBottom="@dimen/button_inset_vertical_material">
    <shape android:shape="rectangle"
           android:tint="?attr/colorButtonNormal">
        <corners android:radius="@dimen/control_corner_material" />
        <solid android:color="@color/white" />
        <padding android:left="@dimen/button_padding_horizontal_material"
                 android:top="@dimen/button_padding_vertical_material"
                 android:right="@dimen/button_padding_horizontal_material"
                 android:bottom="@dimen/button_padding_vertical_material" />
    </shape>
</inset>

inset-drawablebtn_default_mtrl_shape.xml)的Java等价物:

Drawable createButtonShape(Context context, int color) {
    Resource res = context.getResources();
    int radius = res
            .getDimensionPixelSize(R.dimen.control_corner_material);
    int paddingH = res
            .getDimensionPixelSize(R.dimen.button_padding_horizontal_material);
    int paddingV = res
            .getDimensionPixelSize(R.dimen.button_padding_vertical_material);
    int insetH = context.getResources()
            .getDimensionPixelSize(R.dimen.button_inset_horizontal_material);
    int insetV = res
            .getDimensionPixelSize(R.dimen.button_inset_vertical_material);

    float[] outerRadii = new float[8];
    Arrays.fill(outerRadii, radius);

    RoundRectShape r = new RoundRectShape(outerRadii, null, null);

    ShapeDrawable shapeDrawable = new ShapeDrawable(r);
    shapeDrawable.getPaint().setColor(color);
    shapeDrawable.setPadding(paddingH, paddingV, paddingH, paddingV);

    return new InsetDrawable(shapeDrawable,
            insetH, insetV, insetH, insetV);
}

color参数是从主题的attr/colorButtonNormal中获得的-与xml定义中android:tint使用的颜色相同。
以编程方式创建的RippleDrawable

@TargetApi(Build.VERSION_CODES.LOLLIPOP)
Drawable createButtonRippleBg(Context context,
                                             int colorButtonNormal,
                                             int colorControlHighlight) {
    return new RippleDrawable(ColorStateList.valueOf(colorControlHighlight),
                    null, createButtonShape(context, colorButtonNormal));
}

我知道,即使遮罩颜色/形状没有视觉渲染,它的alpha * 确实 * 影响RippleDrawable。这不是一个问题-所有的颜色正在使用的面具有充分的成熟阿尔法。
我还确认了从属性中读取的颜色-colorControlHighlight & colorButtonNormal-对于正在使用的主题是正确的。
然而,结果是:
XML格式副本:

在Java中:

有趣的是,这发生在API 21上。在API 22上,两种方法产生相同的结果。

问题:

我确信这是API 21上的一个bug。如果有人能追踪到这一点,我们可能会找到alpha/color值的乘数来抵消这种视觉差异。
除了一般的善意,我还承诺一笔赏金,因为我已经花了相当长的时间。

pw9qyyiw

pw9qyyiw1#

试试这个备用构造函数new RippleDrawable(ColorStateList.valueOf(colorRipple), backgroundDrawable, null);

相关问题