Android 5.0 Lollipop:setColorFilter"泄漏"到其他按钮

时间:2014-11-19 11:32:32

标签: android android-layout android-5.0-lollipop android-styles

我正在使用setColorFilter来设置我的一个按钮的颜色过滤器。这一直在Android 5.0 Lollipop更新之前完美运行。现在,滤色器似乎泄漏到我的其他按钮上,即使我关闭活动并重新打开(如果我关闭应用程序并重新打开它会重置)。

我的styles.xml(v21):(与旧版本相同,除非此处其父级为“材质”,否则为“Holo”)

<style name="Theme.FullScreen" parent="@android:style/Theme.Material.Light.NoActionBar.Fullscreen">
    <item name="android:buttonStyle">@style/StandardButton</item>
    <item name="android:windowTranslucentStatus">true</item>
</style>

我的styles.xml(适用于所有版本):

<style name="StandardButton" parent="android:style/Widget.Button">
    <item name="android:background">@android:drawable/btn_default</item>
</style>

我的按钮:

<Button
    android:id="@+id/mainMenuButton"              
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:onClick="mainMenu"
    android:text="@string/button_mainMenu"
    android:visibility="gone" />

我的代码:

Button mainMenuButton = (Button) findViewById(R.id.mainMenuButton);
mainMenuButton.getBackground().setColorFilter(new PorterDuffColorFilter(getResources().getColor(R.color.light_green), PorterDuff.Mode.MULTIPLY));
mainMenuButton.setVisibility(View.VISIBLE);

颜色:

<color name="light_green">#5CD65C</color>

结果:

我打开应用程序,然后游戏活动和所有按钮都正确显示。我按下按钮设置彩色滤镜,返回主菜单并重新打开游戏活动,现在所有按钮都是绿色。

有什么想法吗?

3 个答案:

答案 0 :(得分:20)

问题是后台Drawable在许多视图中被重用。为确保多个视图之间不共享Drawable,您应使用mutate方法。

请参阅:mutate()

示例代码:

Drawable background = mainMenuButton.getBackground();
background.mutate();
background.setColorFilter(new PorterDuffColorFilter(getResources().getColor(R.color.light_green), PorterDuff.Mode.MULTIPLY));
mainMenuButton.setBackground(background);

答案 1 :(得分:1)

drawable的实例在所有按钮中共享,因此设置colorfilter会更改所有按钮(您不会立即看到更改,因为按钮不会立即失效)。

尝试手动加载drawable(BitmapFactory.decodeResource(getResources(), android.R.drawable.btn_default, null)),然后将其设置为按钮背景。

答案 2 :(得分:1)

OP在这里。谢谢你的建议。使用以下代码修复了该问题。

设置过滤器

Drawable background = getResources().getDrawable(android.R.drawable.btn_default);
background.setColorFilter(new PorterDuffColorFilter(getResources().getColor(R.color.light_green), PorterDuff.Mode.MULTIPLY));
mainMenuButton.setBackground(background); // Use setBackgroundDrawable for API<16
mainMenuButton.setVisibility(View.VISIBLE);

其他按钮没有变绿。

清除过滤器

接下来发生的事情是,似乎Android(部分)忽略了我清除滤色器的调用(稍后会在代码中发生)。 “部分”,因为它是绿色的,但是当我按下它时,它变成黄色(这是btn_default行为,而不是带有滤镜的深绿色)。为了解决这个问题,我不得不将我的函数调用顺序更改为以下内容:

mainMenuButton.setVisibility(View.VISIBLE)
mainMenuButton.getBackground().clearColorFilter();
mainMenuButton.invalidate();

注意:但这会反转按钮的行为。当我按下(并按住)按钮时,它似乎仍然具有绿色滤镜行为并变为深绿色。当我发布它时,按照btn_default返回灰色。对此有何建议?

我希望这至少能以某种方式帮助其他人解决这个奇怪的问题,这对我来说只发生在Android 5.0 Lollipop API 21级。(我测试了API 8,9,12,13,16,17,18和19没有出现这个问题的地方。而且它的AOT编译似乎并不像我预期的那样,因为在Android 4.4.4设备上启用ART不会导致这个问题。)奇怪的是,mutate()没有正如我所预料的那样工作。