Я пытаюсь проследить эту проблему некоторое время. Я думаю, что нашел какое-то объяснение некоторое время назад. К сожалению, его потеряли в комментариях кода где-то.
Я пытаюсь создать 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-исполнение:
В Java:
Интересный бит заключается в том, что это происходит в API 21. В API 22 оба подхода дают одинаковые результаты.
Вопрос:
Я уверен, что это ошибка API 21. Если кто-то может отслеживать это, мы можем найти множитель для значения альфа/цвет, чтобы компенсировать эту визуальную разницу.
В дополнение к общей доброжелательности, я также обещаю щедрость, поскольку я уже потратил довольно много времени на это.