【问题标题】:RippleDrawable created programmatically looks different from its xml counterpart以编程方式创建的 RippleDrawable 看起来与其对应的 xml 不同
【发布时间】:2015-07-20 12:05:27
【问题描述】:

我已经尝试追踪这个问题一段时间了。我想我前段时间确实找到了解释。不幸的是,它在某个地方的 code-cmets 中丢失了。

我正在尝试用 Java 创建一个 Material Borderless-Button。首先,框架中的按钮如下所示:

按钮背景(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-drawable 的 Java 等效项 (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 获得的 - 与 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 &amp; colorButtonNormal - 与正在播放的主题是正确的。

然而,结果是:

Xml 再现:

在 Java 中:

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

问题:

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

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

【问题讨论】:

  • 我看到的唯一区别是通过 xml 您将颜色设置为 tint android:tint="?attr/colorButtonNormal" 并通过代码将其设置为颜色 shapeDrawable.getPaint().setColor(color);
  • @mikepenz 是的,color 参数实际上是从主题的colorButtonNormal 获得的。我在上面提到了这一点:color 参数是从主题的attr/colorButtonNormal 获得的 - 与 xml 定义中的android:tint 使用的颜色相同。
  • 不,这不是我的意思。您在 xml 中将其设置为颜色shapeDrawable.getPaint().setColor(color) 为tint。为什么不通过代码也将其设置为色调? shapeDrawable.setTint();
  • @mikepenz 哦,我明白你的意思了。我之前确实尝试过 - 视觉差异仍然存在。我还尝试使用PorterDuffColorFilter 和Mode.MULTIPLY 应用ColorFilter。输出不如预期。此外,API 22 上不存在该问题,这使我相信 API 21 上的 xml 呈现存在错误。
  • 哦,我明白了。我无法证明这一点,但从截图看来,API 21 上的 xml 显示只是绘制了两次形状。所以它第二次与相同的背景重叠。

标签: android button material-design rippledrawable


【解决方案1】:

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-01-07
    • 2017-07-26
    • 1970-01-01
    • 2015-05-17
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多