java - StateListDrawable 切换滤色器

标签 java android android-layout android-tabhost colorfilter

我想创建自定义按钮以在 TabHost 中使用。我一直在尝试只使用相同的图像资源 (png),但根据状态改变滤色器。所以我做了这个作为自定义按钮的布局:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent" android:layout_height="fill_parent">
    <ImageView android:id="@+id/tab_icon"
        android:layout_centerInParent="true" android:layout_alignParentTop="true"
        android:layout_centerHorizontal="true" android:layout_width="wrap_content"
        android:layout_height="wrap_content"/>
    <TextView android:id="@+id/tab_text" android:layout_below="@id/tab_icon"
        android:layout_centerHorizontal="true" android:layout_width="wrap_content"
        android:layout_height="wrap_content" />
</RelativeLayout>

在我的 Activity 中,我添加了这样的标签:

tabHost.addTab(tabHost.newTabSpec(TAB_NAME_NEWS).setIndicator(buildTab(R.drawable.tab_icon_news, R.string.news))
          .setContent(newsIntent));

这是“buildTab”方法:

private final static int[] SELECTED = new int[] { android.R.attr.state_selected };
private final static int[] IDLE = new int[] { -android.R.attr.state_selected };

private View buildTab(int icon, int label) {
    LayoutInflater inflater = LayoutInflater.from(this);
    View view = inflater.inflate(R.layout.tab_button, null);
    StateListDrawable drawable = new StateListDrawable();

    Drawable selected = getResources().getDrawable(icon);
    selected.mutate();
    selected.setBounds(0, 0, selected.getIntrinsicWidth(), selected.getIntrinsicHeight());
    selected.setColorFilter(new LightingColorFilter(0xFFFFFFFF, 0x0000FF00));
    drawable.addState(SELECTED, selected);

    Drawable idle = getResources().getDrawable(icon);
    idle.mutate();
    idle.setColorFilter(new LightingColorFilter(0xFFFFFFFF, 0x000000FF));
    drawable.addState(IDLE, idle);

    ((ImageView) view.findViewById(R.id.tab_icon)).setImageDrawable(drawable);
    ((TextView) view.findViewById(R.id.tab_text)).setText(getString(label));
    return view;
}

在选中状态下,图像应该是完全绿色的(0x0000FF00),在非选中状态下,它应该是蓝色的(0x000000FF)。

问题是滤色器似乎被完全忽略了。在任何情况下我都看不到颜色发生变化。

我也尝试通过设置 android:tint 来获得相同的结果<ImageView/> 上的属性(property), 但显然你不能使用对 <selector> 的引用在那里,因为它抛出一个 NumberFormatException .

我看不出我做错了什么,所以我们将不胜感激。

最佳答案

好吧,我从来没有让上面的代码工作,所以这就是我最终做的。

首先,我将 LayerDrawable 子类化:

public class StateDrawable extends LayerDrawable {

    public StateDrawable(Drawable[] layers) {
        super(layers);
    }

    @Override
    protected boolean onStateChange(int[] states) {
        for (int state : states) {
            if (state == android.R.attr.state_selected) {
                super.setColorFilter(Color.argb(255, 255, 195, 0), PorterDuff.Mode.SRC_ATOP);
            } else {
                super.setColorFilter(Color.GRAY, PorterDuff.Mode.SRC_ATOP);
            }
        }
        return super.onStateChange(states);
    }

    @Override
    public boolean isStateful() {
        return true;
    }

}

我将 buildTab() 方法更改为以下内容:

private View buildTab(int icon, int label) {
    LayoutInflater inflater = LayoutInflater.from(this);
    View view = inflater.inflate(R.layout.tab_button, null);
    ((ImageView) view.findViewById(R.id.tab_icon)).setImageDrawable(new StateDrawable(new Drawable[] { getResources()
          .getDrawable(icon) }));
    ((TextView) view.findViewById(R.id.tab_text)).setText(getString(label));
    return view;
}

我仍然像这样添加标签:

Intent fooIntent = new Intent().setClass(this, FooActivity.class);
tabHost.addTab(tabHost.newTabSpec(TAB_NAME_INFO).setIndicator(buildTab(R.drawable.tab_icon_info, R.string.info)).setContent(infoIntent));

这对我有用,与 android 1.6 兼容。

关于java - StateListDrawable 切换滤色器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6018602/

相关文章:

java - Dropwizard 配置不适用于 Shaded jar

java - 在 LibGDX 中处置 Assets 管理器

android - 广告不可见。不刷新广告。屏幕关闭后

Android isScreenOn Nullpointer异常

android - 高于 2dp 的高度会导致按钮消失

android,如何从另一个 .xml 文件加载 linearlayout?

机器人 : layout_weight not picking values from correct layout on orientation change

java - 是否可以像在MySQL中一样在elasticsearch中使用spring数据查询IN?

java - 当文件大小发生变化时,Struts DiskFile.getInputStream() 返回 ByteArrayInputStream 和 FileArrayInputStream

java - 在 Java 中,我应将 Timer 类事件监听器附加到哪些对象?