Replace selector images programmatically

I have an ImageView that has a drawable image resource set to a selector. How do I programmatically access the selector and change the images of the highlighted and non-highlighted state?

Here is a code of selector:

<?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>

I want to be able to replace btn_icon_hl and btn_icon with other images.

68103 次浏览

据我所知(我自己也做过类似的尝试) ,在已经定义了 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);

And you could just keep two of them on hand, or create a different one as you need it.

I had the same problem and went a step further to solve it. The only problem however is you can not specify the NavStateListDrawable in xml, so you have to set the background of your UI element through code. The onStateChange method must then be overriden to ensure that every time the level of the main drawable is changed, that you also update the level of the child level list.

在构造 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个!.