创建自定义控件根据控件的需求主要有一下几种方案:
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文件中指定相关属性的值。
2. 创建ImageButton的背景,使用Selector Drawable。
jimi:is_checked="true"是(1)中自定义的属性
3. 创建布局文件,可以指定自定义属性的值。
4. 创建自定义类,继承至ImageButton。让自定义类有ImageButton的所有功能。在构造方法中通过TypedArray读取自定义属性的值。
5. 实现Checkable接口。
接口如下:
自定义类全部代码:
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文件中指定相关属性的值。
- <?xmlversion="1.0"encoding="utf-8"?>
- <resources>
- <!--customcheckableimageButton-->
- <declare-styleablename="CheckableImageButton">
- <attrname="is_checked"format="boolean"/>
- <attrname="personality">
- <enumname="radio"value="0"/>
- <enumname="check"value="1"/>
- </attr>
- </declare-styleable>
- </resources>
2. 创建ImageButton的背景,使用Selector Drawable。
- <?xmlversion="1.0"encoding="UTF-8"?>
- <selectorxmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:jimi="http://schemas.android.com/apk/res/com.seclock.jimi">
- <itemandroid:state_pressed="true"android:drawable="@drawable/transparent"/>
- <itemjimi:is_checked="true"android:drawable="@drawable/checkable_image_btn_state_checked"/>
- <itemandroid:drawable="@drawable/transparent"/>
- </selector>
jimi:is_checked="true"是(1)中自定义的属性
3. 创建布局文件,可以指定自定义属性的值。
- <?xmlversion="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接口。
接口如下:
- /**
- *Changethecheckedstateoftheview
- *
- *@paramcheckedThenewcheckedstate
- */
- voidsetChecked(booleanchecked);
- /**
- *@returnThecurrentcheckedstateoftheview
- */
- booleanisChecked();
- /**
- *Changethecheckedstateoftheviewtotheinverseofitscurrentstate
- *
- */
- voidtoggle();
自定义类全部代码:
- publicclassCheckableImageButtonextendsImageButtonimplementsCheckable{
- privatestaticfinalStringDEBUG_TAG=CheckableImageButton.class
- .getSimpleName();
- privatestaticfinalintPERSONALITY_RADIO_BUTTON=0;
- privatestaticfinalintPERSONALITY_CHECK_BUTTON=1;
- privatestaticfinalint[]CHECKED_STATE_SET={R.attr.checked};
- privatebooleanmChecked;
- privateintpersonality;
- privatebooleanmBroadcasting;
- privateOnCheckedChangeListenermOnCheckedChangeListener;
- publicCheckableImageButton(Contextcontext){
- super(context);
- }
- publicCheckableImageButton(Contextcontext,AttributeSetattrs,
- intdefStyle){
- super(context,attrs,defStyle);
- }
- publicCheckableImageButton(Contextcontext,AttributeSetattrs){
- super(context,attrs);
- //获取自定义属性的值
- TypedArraya=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);
- //GivebackapreviouslyretrievedStyledAttributes,forlaterre-use.
- a.recycle();
- }
- @Override
- publicbooleanperformClick(){
- //拦截点击事件处理check
- if(personality==PERSONALITY_CHECK_BUTTON){
- toggle();
- }elseif(personality==PERSONALITY_RADIO_BUTTON){
- setChecked(true);
- }
- returnsuper.performClick();
- }
- @Override
- publicvoidsetChecked(booleanchecked){
- 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
- publicbooleanisChecked(){
- returnmChecked;
- }
- @Override
- publicvoidtoggle(){
- setChecked(!mChecked);
- }
- @Override
- publicint[]onCreateDrawableState(intextraSpace){
- int[]states=super.onCreateDrawableState(extraSpace+1);
- if(isChecked()){
- mergeDrawableStates(states,CHECKED_STATE_SET);
- }
- returnstates;
- }
- @Override
- protectedvoiddrawableStateChanged(){
- super.drawableStateChanged();
- //invalidate();
- }
- publicstaticinterfaceOnCheckedChangeListener{
- /**
- *interfacedefinitionforacallbacktobeinvokedwhenthechecked
- *imagebuttonchanged
- *
- *@parambutton
- *@paramisChecked
- **/
- publicvoidonCheckedChanged(CheckableImageButtonbutton,
- booleanisChecked);
- }
- /**
- *@Title:保存状态.
- *@authorAnders
- */
- staticclassSaveStateextendsBaseSavedState{
- booleanchecked;
- publicSaveState(Parcelin){
- super(in);
- checked=(Boolean)in.readValue(null);
- }
- publicSaveState(ParcelablesuperState){
- super(superState);
- }
- @Override
- publicvoidwriteToParcel(Parceldest,intflags){
- super.writeToParcel(dest,flags);
- dest.writeValue(checked);
- }
- publicstaticfinalParcelable.Creator<SaveState>CREATOR=newCreator<CheckableImageButton.SaveState>(){
- @Override
- publicSaveState[]newArray(intsize){
- returnnewSaveState[size];
- }
- @Override
- publicSaveStatecreateFromParcel(Parcelsource){
- returncreateFromParcel(source);
- }
- };
- }
- @Override
- protectedParcelableonSaveInstanceState(){
- ParcelablesuperParcelable=super.onSaveInstanceState();
- SaveStatess=newSaveState(superParcelable);
- ss.checked=isChecked();
- returnss;
- }
- @Override
- protectedvoidonRestoreInstanceState(Parcelablestate){
- SaveStatess=(SaveState)state;
- super.onRestoreInstanceState(ss.getSuperState());
- setChecked(ss.checked);
- }
- publicOnCheckedChangeListenergetmOnCheckedChangeListener(){
- returnmOnCheckedChangeListener;
- }
- publicvoidsetmOnCheckedChangeListener(
- OnCheckedChangeListenermOnCheckedChangeListener){
- this.mOnCheckedChangeListener=mOnCheckedChangeListener;
- }
- }