自定义控件 — 创建Checkable ImageButton

创建自定义控件根据控件的需求主要有一下几种方案:

1、如果现有的控件已经具备了你想要的功能,那么修改或者扩展它们的外观或行为。通过override事件处理函数和onDraw,仍然调用父类的方法,在你定制控件时就不需要重新实现它的功能。
2、组合控件来创建原子的、可重用的widgets,它会引发一些相互关联的控件的功能性发生变化。例如,你可以创建一个下拉的combobox,通过组合一个TextView和一个Button,当点击Button时,显示一个浮动的ListView。

3、当你需要一个完全不同的界面,而不能通过改变和组合现有的控件来达到的时候,选择创建一个全新的控件。

CheckableImageButton

Android自带的ImageButton是不支持像CheckBox, RadioButton拥有的check(选中)状态的,Android提供的组件还算丰富,我们能用这些组件快速开发一个简单的应用程序,但在比较复杂项目中就会感觉捉襟见肘了,但幸好在Android系统上开发者能自由定制自己的UI组件,来弥补现有组件的不足。

创建一个CheckableImageButton需要做的工作:

1. 添加资源文件 res/values/attrs.xml,添加自定义组件CheckableImageButton,声明is_checked和personality属性,以后就能通过这两个属性在XML文件中指定相关属性的值。

<?xml version="1.0" encoding="utf-8"?>
<resources>
<!-- custom checkable imageButton -->
<declare-styleable name="CheckableImageButton">
<attr name="is_checked" format="boolean"/>
<attr name="personality">
<enum name="radio" value="0"/>
<enum name="check" value="1"/>
</attr>
</declare-styleable>
</resources>

2. 创建ImageButton的背景,使用Selector Drawable。

<?xml version="1.0" encoding="UTF-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:jimi="http://schemas.android.com/apk/res/com.seclock.jimi">
<item android:state_pressed="true" android:drawable="@drawable/transparent" />
<item jimi:is_checked="true" android:drawable="@drawable/checkable_image_btn_state_checked" />
<item android:drawable="@drawable/transparent" />
</selector>

jimi:is_checked="true"是(1)中自定义的属性

3. 创建布局文件,可以指定自定义属性的值。
<?xml version="1.0" encoding="UTF-8"?>
<LinearLayoutxmlns:android="http://schemas.android.com/apk/res/android"
xmlns:jimi="http://schemas.android.com/apk/res/com.seclock.jimi"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<you.package.name.CheckableImageButton
android:layout_width="fill_parent"
android:layout_height="fill_parent"
jimi:is_check="true"
jimi:personality="radio"
/>
</LinearLayout>


4. 创建自定义类,继承至ImageButton。让自定义类有ImageButton的所有功能。在构造方法中通过TypedArray读取自定义属性的值。

5. 实现Checkable接口。

接口如下:

/**     
* Change the checked state of the view
*
* @param checked The new checked state
*/
void setChecked(boolean checked);
/**
* @return The current checked state of the view
*/
boolean isChecked();
/**
* Change the checked state of the view to the inverse of its current state
*
*/
void toggle();

自定义类全部代码:

public class CheckableImageButton extends ImageButton implements Checkable {
private static final String DEBUG_TAG = CheckableImageButton.class
.getSimpleName();

private static final int PERSONALITY_RADIO_BUTTON = 0;
private static final int PERSONALITY_CHECK_BUTTON = 1;
private static final int[] CHECKED_STATE_SET = { R.attr.checked };

private boolean mChecked;
private int personality;
private boolean mBroadcasting;
private OnCheckedChangeListener mOnCheckedChangeListener;

public CheckableImageButton(Context context) {
super(context);
}

public CheckableImageButton(Context context, AttributeSet attrs,
int defStyle) {
super(context, attrs, defStyle);
}

public CheckableImageButton(Context context, AttributeSet attrs) {
super(context, attrs);
// 获取自定义属性的值
TypedArray a = context.obtainStyledAttributes(attrs,
R.styleable.checkedImageButton);
mChecked = a.getBoolean(R.styleable.checkedImageButton_checked, false);
personality = a.getInt(R.styleable.checkedImageButton_personality,
PERSONALITY_RADIO_BUTTON);
setChecked(mChecked);
// Give back a previously retrieved StyledAttributes, for later re-use.
a.recycle();
}

@Override
public boolean performClick() {
// 拦截点击事件处理check
if (personality == PERSONALITY_CHECK_BUTTON) {
toggle();
} else if (personality == PERSONALITY_RADIO_BUTTON) {
setChecked(true);
}
return super.performClick();
}

@Override
public void setChecked(boolean checked) {
Log.d(DEBUG_TAG, "setChecked:" + checked);
if (mChecked != checked) {
mChecked = checked;
// 状态改变刷新视图
refreshDrawableState();
}
if (mBroadcasting) {
return;
}
mBroadcasting = true;
if (null != mOnCheckedChangeListener) {
mOnCheckedChangeListener.onCheckedChanged(this, mChecked);
}
mBroadcasting = false;
}

@Override
public boolean isChecked() {
return mChecked;
}

@Override
public void toggle() {
setChecked(!mChecked);
}

@Override
public int[] onCreateDrawableState(int extraSpace) {
int[] states = super.onCreateDrawableState(extraSpace + 1);
if (isChecked()) {
mergeDrawableStates(states, CHECKED_STATE_SET);
}
return states;
}

@Override
protected void drawableStateChanged() {
super.drawableStateChanged();
// invalidate();
}

public static interface OnCheckedChangeListener {
/**
* interface definition for a callback to be invoked when the checked
* image button changed
*
* @param button
* @param isChecked
* */
public void onCheckedChanged(CheckableImageButton button,
boolean isChecked);
}

/**
* @Title: 保存状态.
* @author Anders
*/
static class SaveState extends BaseSavedState {
boolean checked;

public SaveState(Parcel in) {
super(in);
checked = (Boolean) in.readValue(null);
}

public SaveState(Parcelable superState) {
super(superState);
}

@Override
public void writeToParcel(Parcel dest, int flags) {
super.writeToParcel(dest, flags);
dest.writeValue(checked);
}

public static final Parcelable.Creator<SaveState> CREATOR = new Creator<CheckableImageButton.SaveState>() {

@Override
public SaveState[] newArray(int size) {
return new SaveState[size];
}

@Override
public SaveState createFromParcel(Parcel source) {
return createFromParcel(source);
}
};
}

@Override
protected Parcelable onSaveInstanceState() {
Parcelable superParcelable = super.onSaveInstanceState();
SaveState ss = new SaveState(superParcelable);
ss.checked = isChecked();
return ss;
}

@Override
protected void onRestoreInstanceState(Parcelable state) {
SaveState ss = (SaveState) state;
super.onRestoreInstanceState(ss.getSuperState());
setChecked(ss.checked);
}

public OnCheckedChangeListener getmOnCheckedChangeListener() {
return mOnCheckedChangeListener;
}

public void setmOnCheckedChangeListener(
OnCheckedChangeListener mOnCheckedChangeListener) {
this.mOnCheckedChangeListener = mOnCheckedChangeListener;
}

}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值