以编程方式替换选择器图像

Posted

技术标签:

【中文标题】以编程方式替换选择器图像【英文标题】:Replace selector images programmatically 【发布时间】:2011-06-09 12:16:41 【问题描述】:

我有一个 ImageView,它有一个可绘制的图像资源设置为一个选择器。如何以编程方式访问选择器并更改突出显示和非突出显示状态的图像?

这里是选择器的代码:

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/iconSelector">
  <!-- pressed -->
  <item android:state_pressed="true" android:drawable="@drawable/btn_icon_hl" />
  <!-- focused -->
  <item android:state_focused="true" android:drawable="@drawable/btn_icon_hl" />
  <!-- default -->
  <item android:drawable="@drawable/btn_icon" />
</selector>

我希望能够将btn_icon_hlbtn_icon 替换为其他图像。

【问题讨论】:

拥有两个选择器并交换它们不是更容易吗? 问题在于你能得到数百个 xml 文件吗? 【参考方案1】:

据我所知(我自己也尝试过类似的事情),在 StateListDrawable 已经定义之后,无法修改单个状态。但是,您可以通过代码定义一个新的:

StateListDrawable states = new StateListDrawable();
states.addState(new int[] android.R.attr.state_pressed,
    getResources().getDrawable(R.drawable.pressed));
states.addState(new int[] android.R.attr.state_focused,
    getResources().getDrawable(R.drawable.focused));
states.addState(new int[]  ,
    getResources().getDrawable(R.drawable.normal));
imageView.setImageDrawable(states);

您可以只保留其中两个,或者根据需要创建一个不同的。

【讨论】:

我无法将此添加到图像视图中。 setState 对它不可用。 其实我找到了,它的 setImageDrawable() 非常感谢它的工作并为我节省了大约 40 个 xml 文件! 所以我有另一个相关的说明。我希望你能回答。我在自定义控件内的 ImageView 上设置了这个选择器。自定义控件也有一个选择器作为背景。所以整个控件的选择器有效,而 ImageView 选择器无效。有什么我做错了吗?有顺序吗? 不客气!是的我不知道为什么我把setState,应该是setImageDrawable,你是对的。根据您的其他问题,我建议发布一个新问题,其中包含您的自定义控件及其选择器的代码,我不确定答案。 我使用的是相同的代码。始终保留我在 ----> new int[] 状态中指定的图像。我哪里错了??【参考方案2】:

我遇到了同样的问题,并进一步解决了它。但是唯一的问题是您不能在 xml 中指定 NavStateListDrawable,因此您必须通过代码设置 UI 元素的背景。然后必须重写 onStateChange 方法,以确保每次更改主可绘制对象的级别时,您也会更新子级别列表的级别。

在构建 NavStateListDrawable 时,您必须传入您希望显示的图标的级别。

public class NavStateListDrawable extends StateListDrawable 

    private int level;

    public NavStateListDrawable(Context context, int level) 

        this.level = level;
        //int stateChecked = android.R.attr.state_checked;
        int stateFocused = android.R.attr.state_focused;
        int statePressed = android.R.attr.state_pressed;
        int stateSelected = android.R.attr.state_selected;

        addState(new int[] stateSelected      , context.getResources().getDrawable(R.drawable.nav_btn_pressed));
        addState(new int[] statePressed      , context.getResources().getDrawable(R.drawable.nav_btn_selected));
        addState(new int[] stateFocused      , context.getResources().getDrawable(R.drawable.nav_btn_focused));

        addState(new int[]-stateFocused, -statePressed, -stateSelected, context.getResources().getDrawable(R.drawable.nav_btn_default));


    

    @Override
    protected boolean onStateChange(int[] stateSet) 

        boolean nowstate = super.onStateChange(stateSet);

        try
            LayerDrawable defaultDrawable = (LayerDrawable)this.getCurrent();


            LevelListDrawable bar2 =  (LevelListDrawable)defaultDrawable.findDrawableByLayerId(R.id.nav_icons);
            bar2.setLevel(level);
        catch(Exception exception)
        

        

        return nowstate;
    

对于所有不同的导航按钮可绘制状态,我有如下内容。

<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">

   <item android:drawable="@drawable/top_bar_default" >

   </item>

    <item android:id="@+id/nav_icons" android:bottom="0dip">
        <level-list xmlns:android="http://schemas.android.com/apk/res/android">
            <item android:maxLevel="0" >
                <bitmap
                    android:src="@drawable/top_bar_icon_back"
                    android:gravity="center" />
            </item>
            <item android:maxLevel="1" >
                <bitmap
                    android:src="@drawable/top_bar_icon_nav"
                    android:gravity="center" />
            </item>
            <item android:maxLevel="2" >
                <bitmap
                    android:src="@drawable/top_bar_icon_settings"
                    android:gravity="center" />
            </item>
            <item android:maxLevel="3" >
                <bitmap
                    android:src="@drawable/top_bar_icon_search"
                    android:gravity="center" />
            </item>
        </level-list>

    </item>

</layer-list>

我打算将此作为问答发布,但既然您提出了这个问题,那就给您吧。请注意,这为您节省了大量的 xml 文件定义。我从大约 50-100 个 xml 定义减少到大约 4 个!。

【讨论】:

navstatelistdrawable 代码有效地使选择器 xml 变得多余。 嗨,emilie,作为按钮背景的可绘制对象是否有可能因任何原因第一次不会出现。目前我遇到了一个问题,我需要触摸按钮区域以显示背景,或者切换出来并切换回活动。 (这只发生在 hdpi 屏幕上,但在我的 mdpi 上工作正常)。我相信其他人也可能有这个问题。您的代码是否针对所有屏幕密度进行了测试? 嗨,不,这是很久以前写的,当时只适用于一个设备。我不确定可能会出现什么样的问题,但据我所知,多个屏幕密度和布局不应该出现问题。 谢谢,我不太清楚自己做错了什么,但最后我得到了以下结果: buttonStates = new StateListDrawable(); buttonStates.addState(new int[]statePressed, ApplicationConstants.moduleImageLoader.findImageByName(drawable_pressed)); buttonStates.addState(new int[]-stateFocused, -statePressed, -stateSelected, ApplicationConstants.moduleImageLoader.findImageByName(drawable_normal)); 这是我看到必须为设置为 false 的状态使用负值的第一个地方。文档不是很清楚。感谢您的提示!

以上是关于以编程方式替换选择器图像的主要内容,如果未能解决你的问题,请参考以下文章

添加日期选择器以编程方式查看?

以编程方式将选择器添加到导航栏按钮

在反应中以编程方式关闭蚂蚁设计范围选择器

如何以编程方式在移动设备上调用本机日期选择器

以编程方式调用 segue 导致 NSInvalidArgumentException,原因:'UILabel 长度'无法识别的选择器

以编程方式创建的 UIBarButtonItem 未启动选择器操作