自定义控件 — 创建Checkable ImageButton

本文详细介绍了如何在Android中创建一个具有检查状态的自定义ImageButton组件,包括添加自定义属性、创建布局文件、实现Checkable接口等关键步骤。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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

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文件中指定相关属性的值。 

Java代码   收藏代码
  1. <?xml version="1.0" encoding="utf-8"?>  
  2. <resources>      
  3.     <!-- custom checkable imageButton -->      
  4.     <declare-styleable name="CheckableImageButton">          
  5.         <attr name="is_checked" format="boolean"/>          
  6.         <attr name="personality">              
  7.             <enum name="radio" value="0"/>              
  8.             <enum name="check" value="1"/>          
  9.         </attr>      
  10.     </declare-styleable>  
  11. </resources>   

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

Java代码   收藏代码
  1. <?xml version="1.0" encoding="UTF-8"?>  
  2. <selector  xmlns:android="http://schemas.android.com/apk/res/android"    
  3.     xmlns:jimi="http://schemas.android.com/apk/res/com.seclock.jimi">    
  4.     <item android:state_pressed="true" android:drawable="@drawable/transparent"  />    
  5.     <item jimi:is_checked="true" android:drawable="@drawable/checkable_image_btn_state_checked"  />    
  6.     <item android:drawable="@drawable/transparent"  />  
  7. </selector>   

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

3. 创建布局文件,可以指定自定义属性的值。 
Java代码   收藏代码
  1. <?xml version="1.0" encoding="UTF-8"?>  
  2. <LinearLayoutxmlns:android="http://schemas.android.com/apk/res/android"  
  3.     xmlns:jimi="http://schemas.android.com/apk/res/com.seclock.jimi"      
  4.     android:layout_width="fill_parent"      
  5.     android:layout_height="fill_parent">      
  6.     <you.package.name.CheckableImageButton          
  7.     android:layout_width="fill_parent"          
  8.     android:layout_height="fill_parent"          
  9.     jimi:is_check="true"          
  10.     jimi:personality="radio"      
  11.     />  
  12. </LinearLayout>   


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

5. 实现Checkable接口。 

接口如下: 

Java代码   收藏代码
  1. /**      
  2. * Change the checked state of the view      
  3. *       
  4. * @param checked The new checked state      
  5. */      
  6. void setChecked(boolean checked);              
  7. /**      
  8. * @return The current checked state of the view      
  9. */      
  10. boolean isChecked();          
  11. /**      
  12. * Change the checked state of the view to the inverse of its current state      
  13. *      
  14. */      
  15. void toggle();   

自定义类全部代码: 

Java代码   收藏代码
  1. public class CheckableImageButton extends ImageButton implements Checkable {  
  2.     private static final String DEBUG_TAG = CheckableImageButton.class  
  3.             .getSimpleName();  
  4.   
  5.     private static final int PERSONALITY_RADIO_BUTTON = 0;  
  6.     private static final int PERSONALITY_CHECK_BUTTON = 1;  
  7.     private static final int[] CHECKED_STATE_SET = { R.attr.checked };  
  8.   
  9.     private boolean mChecked;  
  10.     private int personality;  
  11.     private boolean mBroadcasting;  
  12.     private OnCheckedChangeListener mOnCheckedChangeListener;  
  13.   
  14.     public CheckableImageButton(Context context) {  
  15.         super(context);  
  16.     }  
  17.   
  18.     public CheckableImageButton(Context context, AttributeSet attrs,  
  19.             int defStyle) {  
  20.         super(context, attrs, defStyle);  
  21.     }  
  22.   
  23.     public CheckableImageButton(Context context, AttributeSet attrs) {  
  24.         super(context, attrs);  
  25.         // 获取自定义属性的值  
  26.         TypedArray a = context.obtainStyledAttributes(attrs,  
  27.                 R.styleable.checkedImageButton);  
  28.         mChecked = a.getBoolean(R.styleable.checkedImageButton_checked, false);  
  29.         personality = a.getInt(R.styleable.checkedImageButton_personality,  
  30.                 PERSONALITY_RADIO_BUTTON);  
  31.         setChecked(mChecked);  
  32.         // Give back a previously retrieved StyledAttributes, for later re-use.  
  33.         a.recycle();  
  34.     }  
  35.   
  36.     @Override  
  37.     public boolean performClick() {  
  38.         // 拦截点击事件处理check  
  39.         if (personality == PERSONALITY_CHECK_BUTTON) {  
  40.             toggle();  
  41.         } else if (personality == PERSONALITY_RADIO_BUTTON) {  
  42.             setChecked(true);  
  43.         }  
  44.         return super.performClick();  
  45.     }  
  46.   
  47.     @Override  
  48.     public void setChecked(boolean checked) {  
  49.         Log.d(DEBUG_TAG, "setChecked:" + checked);  
  50.         if (mChecked != checked) {  
  51.             mChecked = checked;  
  52.             // 状态改变刷新视图  
  53.             refreshDrawableState();  
  54.         }  
  55.         if (mBroadcasting) {  
  56.             return;  
  57.         }  
  58.         mBroadcasting = true;  
  59.         if (null != mOnCheckedChangeListener) {  
  60.             mOnCheckedChangeListener.onCheckedChanged(this, mChecked);  
  61.         }  
  62.         mBroadcasting = false;  
  63.     }  
  64.   
  65.     @Override  
  66.     public boolean isChecked() {  
  67.         return mChecked;  
  68.     }  
  69.   
  70.     @Override  
  71.     public void toggle() {  
  72.         setChecked(!mChecked);  
  73.     }  
  74.   
  75.     @Override  
  76.     public int[] onCreateDrawableState(int extraSpace) {  
  77.         int[] states = super.onCreateDrawableState(extraSpace + 1);  
  78.         if (isChecked()) {  
  79.             mergeDrawableStates(states, CHECKED_STATE_SET);  
  80.         }  
  81.         return states;  
  82.     }  
  83.   
  84.     @Override  
  85.     protected void drawableStateChanged() {  
  86.         super.drawableStateChanged();  
  87.         // invalidate();  
  88.     }  
  89.   
  90.     public static interface OnCheckedChangeListener {  
  91.         /** 
  92.          * interface definition for a callback to be invoked when the checked 
  93.          * image button changed 
  94.          *  
  95.          * @param button 
  96.          * @param isChecked 
  97.          * */  
  98.         public void onCheckedChanged(CheckableImageButton button,  
  99.                 boolean isChecked);  
  100.     }  
  101.   
  102.     /** 
  103.      * @Title: 保存状态. 
  104.      * @author Anders 
  105.      */  
  106.     static class SaveState extends BaseSavedState {  
  107.         boolean checked;  
  108.   
  109.         public SaveState(Parcel in) {  
  110.             super(in);  
  111.             checked = (Boolean) in.readValue(null);  
  112.         }  
  113.   
  114.         public SaveState(Parcelable superState) {  
  115.             super(superState);  
  116.         }  
  117.   
  118.         @Override  
  119.         public void writeToParcel(Parcel dest, int flags) {  
  120.             super.writeToParcel(dest, flags);  
  121.             dest.writeValue(checked);  
  122.         }  
  123.   
  124.         public static final Parcelable.Creator<SaveState> CREATOR = new Creator<CheckableImageButton.SaveState>() {  
  125.   
  126.             @Override  
  127.             public SaveState[] newArray(int size) {  
  128.                 return new SaveState[size];  
  129.             }  
  130.   
  131.             @Override  
  132.             public SaveState createFromParcel(Parcel source) {  
  133.                 return createFromParcel(source);  
  134.             }  
  135.         };  
  136.     }  
  137.   
  138.     @Override  
  139.     protected Parcelable onSaveInstanceState() {  
  140.         Parcelable superParcelable = super.onSaveInstanceState();  
  141.         SaveState ss = new SaveState(superParcelable);  
  142.         ss.checked = isChecked();  
  143.         return ss;  
  144.     }  
  145.   
  146.     @Override  
  147.     protected void onRestoreInstanceState(Parcelable state) {  
  148.         SaveState ss = (SaveState) state;  
  149.         super.onRestoreInstanceState(ss.getSuperState());  
  150.         setChecked(ss.checked);  
  151.     }  
  152.   
  153.     public OnCheckedChangeListener getmOnCheckedChangeListener() {  
  154.         return mOnCheckedChangeListener;  
  155.     }  
  156.   
  157.     public void setmOnCheckedChangeListener(  
  158.             OnCheckedChangeListener mOnCheckedChangeListener) {  
  159.         this.mOnCheckedChangeListener = mOnCheckedChangeListener;  
  160.     }  
  161.   
  162. }  
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值