RippleDrawable, созданный программным способом, отличается от своего xml-аналога

Я пытаюсь проследить эту проблему некоторое время. Я думаю, что нашел какое-то объяснение некоторое время назад. К сожалению, его потеряли в комментариях кода где-то.

Я пытаюсь создать Material Borderless-Button в Java. Для начала, вот что выглядит кнопка в рамке:

Кнопка 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>

Java-эквивалент inset-drawable (btn_default_mtrl_shape.xml):

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 - того же цвета, что и с android:tint в определении xml.

RippleDrawable создан программно:

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

Я знаю, что хотя маска-цвет/форма визуализируется визуально, ее альфа-функция влияет на RippleDrawable. Это не проблема здесь - все цвета, используемые для маски, имеют полномасштабную альфу.

Я также подтвердил, что цвета, считанные с атрибутов - colorControlHighlight & colorButtonNormal, верны для темы в игре.

Тем не менее, результат:

Xml-исполнение:

enter image description here

В Java:

enter image description here

Интересный бит заключается в том, что это происходит в API 21. В API 22 оба подхода дают одинаковые результаты.

Вопрос:

Я уверен, что это ошибка API 21. Если кто-то может отслеживать это, мы можем найти множитель для значения альфа/цвет, чтобы компенсировать эту визуальную разницу.

В дополнение к общей доброжелательности, я также обещаю щедрость, поскольку я уже потратил довольно много времени на это.

Ответ 1

Попробуйте этот альтернативный конструктор new RippleDrawable(ColorStateList.valueOf(colorRipple), backgroundDrawable, null);