android开发时,很多时候我们要动态为各种控件设置背景和前景。其中一种方法是在程序代码中的各个时间响应函数如onClick、onFocus等中为控件设定背景。然而,这种方法实现起来不仅繁琐,而且常常不仅人意。不用担心,其实实现这种功能有一个捷径(虽然有人说捷径往往是到达目标最远的路,但是我还是乐此不疲)。这个捷径就是使用android里面的selector。
Selector是一个选择器,可以根据控件的状态来选择响应的资源(如背景图,颜色值)。下面是个例子,力求简单,只为说明问题。
Selector.xml
<?xml version="1.0" encoding="utf-8" ?>
<selectorxmlns:android=
"http://schemas.android.com/apk/res/android">
<item android:state_pressed="true"android:color="#ff0000" />
<item android:color="#00ff00" />
</selector>
Main.xml中Button定义如下:
<Button android:id="@+id/btn_listen"
android:layout_width="fill_parent"
android:layout_height="wrap_contet"
android:background="R.drawable.Selector"
/>
</pre><p> 则该Button颜色在按下的时候会是红色(#ff0000),没有按下的时候会是绿色(#00ff00)。</p><p>用法就如此简单。</p><p> 其实selector提供给我们的不仅仅是以上的state_pressed属性,还有更多可用的属性让我们完成更加复杂的功能。</p><p>可用的属性有:</p><p>1、state_pressed</p><p>2、state_focused</p><p>3、state_selected</p><p>4、state_checkable</p><p>5、state_checked</p><p>6、state_enabled</p><p>7、window_focused</p><p> 然后可以用这些属性的各种值的组合来定义selector里面的一个item。</p><p> Selector会为我们根据控件当前状态从中选择一个匹配的item然后将空间的背景设为所选item里面的背景。匹配算法是从第一个item开始逐个比较,找到相应的item,如果没有最后一个将作为默认的匹配item。Item匹配的条件是item中定义的属性状态和当前控件状态一样,如果某个属性在该item中没有定义,则视为自动匹配。</p><p> </p><p> 上述方法是在xml中为控件指定了背景,也可以在程序中动态指定背景或者其他属性。下面以指定一个控件的字体颜色为例。</p><p>大体上可以分为</p><p>1、创建xml解释器</p><p>2、创建ColorStateList</p><p>3、用前面定义的ColorStateList为控件设定字体颜色</p><p></p><pre name="code" class="java">//步骤一
XmlResourceParser xpp=Resources.getSystem().getXml
(R.color.wblog_listitem_text_selector);
try {
//步骤二
ColorStateList csl= ColorStateList.createFromXml(getResources(),
xpp);
//步骤三
btnSendPrivateMsg.setTextColor(csl);
} catch (Exception e) {
// TODO: handle exception
}
<h2><strong>//代码实现</strong></h2><pre name="code" class="java">package lab.sodino.statelist;
import android.app.Activity;
import android.content.Context;
import android.content.res.ColorStateList;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.StateListDrawable;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.TextView;
/**
* 对TextView设置ColorStateList使其在Normal、Pressed、Focused、Unable四种状态下显示不同的颜色。<br/>
* StateListDrawable可直接使用图片应用在相似场合。
*/
public class ActColorStateList extends Activity implements OnClickListener {
private TextView txtShow;
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
txtShow = (TextView) findViewById(R.id.txtShow);
txtShow.setText("Sodino\nNormal:0xffffffff\nPressed:0xffffff00\nFocused:0xff0000ff\nUnable:0xffff0000");
txtShow.setTextColor(createColorStateList(0xffffffff, 0xffffff00, 0xff0000ff, 0xffff0000));
txtShow.setOnClickListener(this);
}
/** 对TextView设置不同状态时其文字颜色。 */
private ColorStateList createColorStateList(int normal, int pressed, int focused, int unable) {
int[] colors = new int[] { pressed, focused, normal, focused, unable, normal };
int[][] states = new int[6][];
states[0] = new int[] { android.R.attr.state_pressed, android.R.attr.state_enabled };
states[1] = new int[] { android.R.attr.state_enabled, android.R.attr.state_focused };
states[2] = new int[] { android.R.attr.state_enabled };
states[3] = new int[] { android.R.attr.state_focused };
states[4] = new int[] { android.R.attr.state_window_focused };
states[5] = new int[] {};
ColorStateList colorList = new ColorStateList(states, colors);
<span style="color:#FF0000;"><strong> /** states 包含的为该组件正常状态时的颜色,如果不设置 states[5] = new int[]{} 则在正常情况下,组件通常情况下所影响的部分将变为无色
**/</strong></span>
return colorList;
}
/** 设置Selector。 */
public static StateListDrawable newSelector(Context context, int idNormal, int idPressed, int idFocused,
int idUnable) {
StateListDrawable bg = new StateListDrawable();
Drawable normal = idNormal == -1 ? null : context.getResources().getDrawable(idNormal);
Drawable pressed = idPressed == -1 ? null : context.getResources().getDrawable(idPressed);
Drawable focused = idFocused == -1 ? null : context.getResources().getDrawable(idFocused);
Drawable unable = idUnable == -1 ? null : context.getResources().getDrawable(idUnable);
// View.PRESSED_ENABLED_STATE_SET
bg.addState(new int[] { android.R.attr.state_pressed, android.R.attr.state_enabled }, pressed);
// View.ENABLED_FOCUSED_STATE_SET
bg.addState(new int[] { android.R.attr.state_enabled, android.R.attr.state_focused }, focused);
// View.ENABLED_STATE_SET
bg.addState(new int[] { android.R.attr.state_enabled }, normal);
// View.FOCUSED_STATE_SET
bg.addState(new int[] { android.R.attr.state_focused }, focused);
// View.WINDOW_FOCUSED_STATE_SET
bg.addState(new int[] { android.R.attr.state_window_focused }, unable);
// View.EMPTY_STATE_SET
bg.addState(new int[] {}, normal);
return bg;
}
@Override
public void onClick(View v) {
if (v == txtShow) {
txtShow.setEnabled(false);
}
}
}