您的位置:首页 > 移动开发 > Android开发

[Android]自定义CheckableImageButton

2016-03-16 16:51 429 查看
现如今大多数app的UI都越做越精细,身为一名Android开发者,我经常遇到这种情况——实现采用自定义图片的按钮(如ImageButton)而非RadioButton来实现单选功能,虽然RadioButton本身就是Android提供的单选按钮,但因为其自带的button并不美观,往往会被要求直接采用图片来充当Button。今天就为大家带来一篇自定义CheckableImageButton的文章。

首先,和大部分自定义控件一样,我们需要先在attrs.xml文件中定义相应的style。

attrs.xml

<declare-styleable name="CheckableImageButton">
<attr name="isChecked" format="boolean"/>
</declare-styleable>


接着,我们可以为我们的可选中ImageButton创建Selector文件,指定其在选中和未被选中时呈现的图片

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:myApp="http://schemas.android.com/apk/res/com.yourPackage.xxx">
<item dxx:isChecked="true" android:drawable="@mipmap/users"></item>
<item dxx:isChecked="false" android:drawable="@mipmap/users_g"></item>
</selector>


[b]注意:上面selector里的xmlns:myApp=”http://schemas.android.com/apk/res/com.yourPackage.xxx”路径改为自己的工程路径[/b]

现在我们可以开始写自定义CheckableImageView了

代码如下

CheckableImageView.java

public class CheckableImageButton extends ImageButton implements Checkable{
//判断是否被点击
private boolean isChecked;
private OnCheckedChangeListener mOnCheckedChangeListener;
private static final int[] CHECKED_STATE_SET = { R.attr.isChecked };
public CheckableImageButton(Context context) {
super(context);
}

public CheckableImageButton(Context context, AttributeSet attrs) {
super(context, attrs);
//获取自定义属性
TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.CheckableImageButton);
isChecked = a.getBoolean(R.styleable.CheckableImageButton_isChecked, false);
setChecked(isChecked);
a.recycle();
}

public CheckableImageButton(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
//获取自定义属性
TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.CheckableImageButton);
isChecked = a.getBoolean(R.styleable.CheckableImageButton_isChecked, false);
setChecked(isChecked);
a.recycle();
}

@Override
public boolean performClick() {
//拦截点击事件
setChecked(true);
return super.performClick();
}

@Override
public void setChecked(boolean checked) {
if (isChecked != checked) {
isChecked = checked;
refreshDrawableState();
if (null != mOnCheckedChangeListener) {
mOnCheckedChangeListener.onCheckedChanged(this, isChecked);
refreshDrawableState();
}
}
}

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

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

@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();
}

@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;
}

//自定义接口,用来监听check的改变
public static interface OnCheckedChangeListener {
public void onCheckedChanged(CheckableImageButton button, boolean isChecked);
}
//用于恢复Check状态信息
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);
}
};
}
}


下面就可以在layout文件中调用了

<LinearLayout
xmlns:dxx="http://schemas.android.com/apk/res/philips.com.myapplication"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true">
<philips.com.myapplication.customview.CheckableImageButton
android:id="@+id/firstIb"
android:layout_width="0dp"
android:layout_height="20dp"
android:layout_weight="1"
android:background="@null"
android:src="@drawable/image_button_first"
android:scaleType="fitCenter"
android:layout_marginLeft="15dp"
android:layout_marginRight="15dp"
dxx:isChecked="true"
/>
<philips.com.myapplication.customview.CheckableImageButton
android:id="@+id/secondIb"
android:layout_width="0dp"
android:layout_height="20dp"
android:layout_weight="1"
android:background="@null"
android:src="@drawable/image_button_second"
android:scaleType="fitCenter"
android:layout_marginLeft="15dp"
android:layout_marginRight="15dp"
/>
<philips.com.myapplication.customview.CheckableImageButton
android:id="@+id/thirdIb"
android:layout_width="0dp"
android:layout_height="20dp"
android:layout_weight="1"
android:background="@null"
android:src="@drawable/image_button_third"
android:scaleType="fitCenter"
android:layout_marginLeft="15dp"
android:layout_marginRight="15dp"
/>

</LinearLayout>


在MainActivity里的调用代码

@Override
public void onCheckedChanged(CheckableImageButton button, boolean isChecked) {
if (isChecked) {
switch (button.getId()) {
case R.id.firstIb:
checkableImageButton2.setChecked(false);
checkableImageButton3.setChecked(false);
break;
case R.id.secondIb:
checkableImageButton1.setChecked(false);
checkableImageButton3.setChecked(false);
break;
case R.id.thirdIb:
checkableImageButton1.setChecked(false);
checkableImageButton2.setChecked(false);
}
}
}


现在就可以实现RadioButton的效果了
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  android android开发 ui