因为赶潮流,在刚结束的项目中,整个项目的设计风格都是扁平化的,相对于拟物化的设计,android的selector就可以大显身手了。也是的项目中的图片数量大大减少,带来的好处就是项目大小减小,项目运行所占用的资源也减少。这两天有点时间,所有打算把这方的知识总结一下,也希望能能有个更深入的理解和掌握。
1、view的状态
- android:state_pressed
Boolean 控件被压(触摸touched/点击clicked)的时候返回true。默认为false。 - android:state_focused
Boolean 控件获得焦点的时候返回true。默认为false。这里解释一下使用场景,<模拟器容易看到>比如使用滑轮或键盘的方向导航键导航到某一个控件上,则此控件就得到了焦点。当然其它的点击,选择,光标等也都有焦点跟随的。 - android:state_selected
Boolean 控件被选中的时候返回true。默认为false。比如一个tab被打开。 - android:state_checkableBoolean 控件处于可选状态的时候返回true。默认为false。说明,这个属性和下面的checked属性仅仅用于那些在可选和不可选两种状态当中过渡的控件
- android:state_checked
Boolean 控件被选中的时候返回true。默认为false。 - android:state_enabled
Boolean 控件可用的时候返回true。默认为false。 - android:state_window_focusedBoolean 当应用的窗口处于聚焦状态时返回true,当窗口失去焦点时返回false(就是说应用窗口处于前台时返回true,处于后台返回false。比如通知罩(即通知栏被拉下后的半透时界面)被打开时或者一个对话框(dialog)出现的时候。后面的窗口就处于失焦状态。
state_selected与state_facused区别:
查看View源码,其中setSelect()方法如下
/**
* Changes the selection state of this view. A view can be selected or not.
* Note that selection is not the same as focus. Views are typically
* selected in the context of an AdapterView like ListView or GridView;
* the selected view is the view that is highlighted.
*
* @param selected true if the view must be selected, false otherwise
*/
public void setSelected(boolean selected) {
if (((mPrivateFlags & SELECTED) != 0) != selected) {
mPrivateFlags = (mPrivateFlags & ~SELECTED) | (selected ? SELECTED : 0);
if (!selected) resetPressedState();
invalidate();
refreshDrawableState();
dispatchSetSelected(selected);
}
}
注:selected不同于focus状态,通常在AdapterView类群下例如ListView或者GridView会使某个View处于 selected状态,并且获得该状态的View处于高亮状态。
下面来看下用selector来改变view的背景色的。
以上两张图,第一张代表button正常状态下显示的背景色,第二张图片是在按下的状态下的背景色。
上面两张图,第一张是第一个输入框获取焦点时显现灰色,第二个输入框在失去焦点的状态下,显示黄色。第二张图,第一个输入框失去焦点,第二个输入框获取焦点时的状态。
btn_selector.xml
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="@color/blue" android:state_pressed="true"/>
<item android:drawable="@color/orange"/>
</selector>
et_selector.xml
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="@color/gray" android:state_focused="true"/>
<item android:drawable="@color/orange"/>
</selector>
demo:
2013-12-14补充。
2、StateListDrawable 介绍
该类定义了不同状态值下与之对应的图片资源,即我们可以利用该类保存多种状态值,多种图片资源。即selector的代码表现。
下面利用此类来实现上面的效果。先介绍此类的一个重要方法:
void |
Add a new image/string ID to the set of images.添加一个图片或者资源引用id来设置图片。
具体代码实现如下:
package org.sunday.main;
import android.os.Bundle;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.StateListDrawable;
import android.view.Menu;
import android.widget.Button;
import android.widget.EditText;
public class MainActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Button btn = (Button) findViewById(R.id.btn);
btn.setBackgroundDrawable(createBtnDrawable());
EditText et1 = (EditText) findViewById(R.id.et1);
et1.setBackgroundDrawable(createEtDrawable());
EditText et2 = (EditText) findViewById(R.id.et2);
et2.setBackgroundDrawable(createEtDrawable());
}
//创建Button的Drawable
private StateListDrawable createBtnDrawable() {
StateListDrawable sld = new StateListDrawable();
//获取Android框架自带的属性 attr
int pressed = android.R.attr.state_pressed;
sld.addState(new int []{pressed}, getResources().getDrawable(R.color.blue));
//没有任何状态时,给它设置空集合
sld.addState(new int []{}, getResources().getDrawable(R.color.orange));
return sld;
}
//创建EditText的Drawable
private StateListDrawable createEtDrawable() {
StateListDrawable sld = new StateListDrawable();
//获取Android框架自带的属性 attr
int focused = android.R.attr.state_focused;
sld.addState(new int []{focused}, getResources().getDrawable(R.color.gray));
//没有任何状态时,给它设置空集合
sld.addState(new int []{}, getResources().getDrawable(R.color.orange));
return sld;
}
}