Android 以编程方式创建的RippleDrawable与它的xml对应项看起来不同

Android 以编程方式创建的RippleDrawable与它的xml对应项看起来不同,android,button,material-design,rippledrawable,Android,Button,Material Design,Rippledrawable,我一直试图追踪这个问题已经有一段时间了。我想我前一段时间确实找到了一个解释。不幸的是,它丢失在某个地方的代码注释中 我正在尝试用Java创建一个材质无边框按钮。首先,以下是框架中按钮的外观: 按钮背景(Button\u borderless\u material.xml): Java等价于插入可绘制的(btn\u default\u mtrl\u shape.xml): color参数来自主题的attr/colorbutonnormal——与xml定义中的android:tint使用的颜色相同

我一直试图追踪这个问题已经有一段时间了。我想我前一段时间确实找到了一个解释。不幸的是,它丢失在某个地方的代码注释中

我正在尝试用Java创建一个
材质无边框按钮
。首先,以下是框架中按钮的外观:

按钮背景(Button\u borderless\u material.xml):

Java等价于
插入可绘制的
(btn\u default\u mtrl\u shape.xml):

color
参数来自主题的
attr/colorbutonnormal
——与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
。这不是一个问题-所有用于遮罩的颜色都有完整的alpha

我还确认了从属性读取的颜色-
colorControlHighlight&colorbutonnormal
-对于当前的主题是正确的

然而,结果是:

Xml格式副本:

在Java中:

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

问题:

我确信这是API 21上的一个bug。如果有人能追踪到这一点,我们可能会找到一个alpha/color值的乘数来抵消这种视觉差异


除了一般的善意之外,我还承诺给予赏金,因为我已经为此花费了相当长的时间

试试这个替代构造函数
新的RippleDrawable(ColorStateList.valueOf(colorRipple),backgroundDrawable,null)

我看到的唯一区别是,通过xml将颜色设置为tint
android:tint=“?attr/colorButtonNormal”
并通过代码将其设置为color
shapeDrawable.getPaint().setColor(color)
@mikepenz是的,
color
参数实际上是从主题的
colorbutonnormal
中获得的。我在上面提到过:
color
参数来自主题的
attr/colorbutonnormal
——与xml定义中的
android:tint
使用的颜色相同。不,这不是我的意思。在xml中将其设置为color
shapeDrawable.getPaint().setColor(color)
,设置为
tint
。为什么不通过代码将其设置为色调呢<代码>shapeDrawable.setTint()@mikepenz哦,我明白你的意思了。我以前确实试过——视觉上的差异仍然存在。我还尝试使用带有
模式的
PorterDuffColorFilter
应用
ColorFilter
。产出不如预期。此外,API 22上不存在这个问题,这使我相信API 21上的xml格式副本有一个bug。我无法证明这一点,但从截图来看,API 21上的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>
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);
}
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
Drawable createButtonRippleBg(Context context,
                                             int colorButtonNormal,
                                             int colorControlHighlight) {
    return new RippleDrawable(ColorStateList.valueOf(colorControlHighlight),
                    null, createButtonShape(context, colorButtonNormal));
}