Android自定义组合控件

目标:实现textview和ImageButton组合,可以通过Xml设置自定义控件的属性。 
  1.控件布局:以Linearlayout为根布局,一个TextView,一个ImageButton。 
  

Xml代码   收藏代码
  1. < ?xml version="1.0" encoding="utf-8"?>  
  2.    < LinearLayout xmlns:Android="http://schemas.android.com/apk/res/android"  
  3.    android:layout_width="fill_parent" android:layout_height="fill_parent"  
  4.    android:gravity="center_vertical">  
  5.    < TextView android:layout_height="wrap_content" android:id="@+id/text1"  
  6.    android:layout_width="wrap_content">< /TextView>  
  7.    < ImageButton android:layout_width="wrap_content"  
  8.    android:layout_height="wrap_content" android:id="@+id/btn1">< /ImageButton>  
  9.    < /LinearLayout>  
  10.     


  2.自定义控件代码,从LinearLayout继承: 
  

Java代码   收藏代码
  1. public class ImageBtnWithText extends LinearLayout {  
  2.  }  
  3.   public ImageBtnWithText(Context context) {  
  4.   this(context, null);  
  5.   }  
  6.    
  7.   public ImageBtnWithText(Context context, AttributeSet attrs) {  
  8.   super(context, attrs);  
  9.   LayoutInflater.from(context).inflate(R.layout.imagebtn_with_text, thistrue);  
  10.     }  
  11.   }  


  在构造函数中将Xml中定义的布局解析出来。 
  3.在主界面布局xml中使用自定义控件: 
  

Xml代码   收藏代码
  1. < com.demo.widget2.ImageBtnWithText  
  2.    android:id="@+id/widget"  
  3.    android:layout_width="fill_parent"  
  4.    android:layout_height="fill_parent" />  
  5.     


  即使用完整的自定义控件类路径:com.demo.widget2.ImageBtnWithText定义一个元素。 
  运行可以看到控件已经能够被加载到界面上。 
  4.给按钮设置图片和文本 
  如果图片是固定不变的,那么直接在控件布局中设置ImageButton的src属性即可。 
  4.1通过Java代码设置,在控件代码中提供函数接口: 
  

Java代码   收藏代码
  1. public void setButtonImageResource(int resId) {  
  2.    mBtn.setImageResource(resId);  
  3.    }  
  4.     
  5.    public void setTextViewText(String text) {  
  6.    mTv.setText(text);  
  7.    }  
  8.     


  然后再在主界面的onCreate()通过函数调用设置即可。 
  4.2通过Xml设置属性 
  4.2.1首先定义Xml可以设置的属性集合,在values下创建attrs.xml,文件名可随意,一般都叫attrs.xml 
  

Xml代码   收藏代码
  1. < ?xml version="1.0" encoding="utf-8"?>  
  2.   < resources>  
  3.    < declare-styleable name="ImageBtnWithText">  
  4.    < attr name="android:text"/>  
  5.    < attr name="android:src"/>  
  6.    < /declare-styleable>  
  7.    < /resources>  
  8.     


  属性集合名字:ImageBtnWithText,自己可根据实际来定义; 
  集合中包含的属性列表,每行一个属性。 
  4.2.2修改自定义控件实现代码,以获取xml中定义的属性 
  

Java代码   收藏代码
  1. TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.ImageBtnWithText);  
  2.   CharSequence text = a.getText(R.styleable.ImageBtnWithText_android_text);  
  3.   if(text != null) mTv.setText(text);  
  4.   Drawable drawable = a.getDrawable(R.styleable.ImageBtnWithText_android_src);  
  5.   if(drawable != null) mBtn.setImageDrawable(drawable);  
  6.   a.recycle()  
  7.    


  首先通过context.obtainStyledAttributes获得所有属性数组; 
  然后通过TypedArray类的getXXXX()系列接口获得相应的值。 
  4.2.3在主界面布局中设置自定义控件的属 
  android:text="ABC" android:src="@drawable/icon 
  4.3自定义名称属性: 
  在4.2中使用的属性名是Android系统命名空间的,都以android开头,比如android:text等。 
实际开发中会自定义一些属性名,这些属性名仍然定义在4.2.1提到的attrs.xml中: 
  4.3.1定义属性名 
  

Xml代码   收藏代码
  1. < attr name="appendText" format="string"/>  


  和直接使用系统的attr不同的是要增加一个format属性,说明此属性是什么格式的。format可选项可参见注1 
  4.3.2使用自定义属性 
  

Xml代码   收藏代码
  1. < ?xml version="1.0" encoding="utf-8"?>  
  2.    < LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"  
  3.    xmlns:myspace="http://schemas.android.com/apk/res/com.demo.customwidget"  
  4.    android:orientation="vertical" android:layout_width="fill_parent"  
  5.    android:layout_height="fill_parent">  
  6.    < com.demo.widget2.ImageBtnWithText  
  7.    android:text="ABC" android:src="@drawable/icon" android:id="@+id/widget"  
  8.    android:layout_width="fill_parent" android:layout_gravity="center"  
  9.    android:layout_height="fill_parent" myspace:appendText="123456">  
  10.    < /com.demo.widget2.ImageBtnWithText>  
  11.    < /LinearLayout>  
  12.     


  直接在主布局文件中使用此属性appendText="abc"是不会设置生效的,而是要在主布局xml中定义一个xml命名空间: 
xmlns:myspace="http://schemas.android.com/apk/res/com.demo.customwidget" 
  命名空间的名字可以自己随便定义,此处为myspace,即xmlns:myspace; 
  后面的地址则有限制,其开始必须为:"http://schemas.android.com/apk/res/",后面则是包名com.demo.customwidget, 
  此处的包名与AndroidManifest.xml中< manifest>节点的属性package="com.demo.customwidget"一致,不是自定义控件Java代码所在的包,当然简单的程序自定义控件Java代码也一般在此包内。 
  注1:format可选项 
  "reference" //引用 
  "color" //颜色 
  "boolean" //布尔值 
  "dimension" //尺寸值 
  "float" //浮点值 
  "integer" //整型值 
  "string" //字符串 
  "fraction" //百分数,比如200% 
  枚举值,格式如下: 
  < attr name="orientation"> 
  < enum name="horizontal" value="0" /> 
  < enum name="vertical" value="1" /> 
  < /attr> 
  xml中使用时: 
  android:orientation = "vertical" 
  标志位,位或运算,格式如下: 
  < attr name="windowSoftInputMode"> 
  < flag name = "stateUnspecified" value = "0" /> 
  < flag name = "stateUnchanged" value = "1" /> 
  < flag name = "stateHidden" value = "2" /> 
  < flag name = "stateAlwaysHidden" value = "3" /> 
  < flag name = "stateVisible" value = "4" /> 
  < flag name = "stateAlwaysVisible" value = "5" /> 
  < flag name = "adjustUnspecified" value = "0x00" /> 
  < flag name = "adjustResize" value = "0x10" /> 
  < flag name = "adjustPan" value = "0x20" /> 
  < flag name = "adjustNothing" value = "0x30" /> 
  < /attr> 
  xml中使用时: 
  android:windowSoftInputMode = "stateUnspecified | stateUnchanged | stateHidden"> 
  另外属性定义时可以指定多种类型值,比如: 
  < attr name = "background" format = "reference|color" /> 
  xml中使用时: 
  android:background = "@drawable/图片ID|#00FF00"
 

最后来个完整实例: 

Java代码   收藏代码
  1. import android.content.Context;  
  2. import android.content.res.TypedArray;  
  3. import android.util.AttributeSet;  
  4. import android.view.LayoutInflater;  
  5. import android.view.View;  
  6. import android.widget.ImageButton;  
  7. import android.widget.LinearLayout;  
  8. import android.widget.ProgressBar;  
  9.   
  10. public class Meter extends LinearLayout {  
  11.     private int max=100;  
  12.     private int incrAmount=1;  
  13.     private int decrAmount=-1;  
  14.     private ProgressBar bar=null;  
  15.     public Meter(final Context ctxt, AttributeSet attrs) {  
  16.         super(ctxt, attrs);  
  17.           
  18.         this.setOrientation(HORIZONTAL);  
  19.           
  20.         TypedArray a=ctxt.obtainStyledAttributes(attrs,R.styleable.Meter);  
  21.           
  22.         //获取里面属性用 "名字_ 属性" 连接起来  
  23.         max=a.getInt(R.styleable.Meter_max, 100);  
  24.         incrAmount=a.getInt(R.styleable.Meter_incr, 1);  
  25.         decrAmount=-1*a.getInt(R.styleable.Meter_decr, 1);  
  26.           
  27.         a.recycle();  
  28.     }  
  29.     //当View中所有的子控件 均被映射成xml后触发  
  30.     @Override  
  31.     protected void onFinishInflate() {  
  32.         super.onFinishInflate();  
  33.           
  34. //      ((Activity)getContext()).getLayoutInflater().inflate(R.layout.meter, this);  
  35.           
  36.         LayoutInflater.from(getContext()).inflate(R.layout.meter, this);  
  37.           
  38.         bar=(ProgressBar)findViewById(R.id.bar);  
  39.         bar.setMax(max);  
  40.           
  41.         ImageButton btn=(ImageButton)findViewById(R.id.incr);  
  42.         btn.setOnClickListener(new View.OnClickListener() {  
  43.             public void onClick(View v) {  
  44.                 bar.incrementProgressBy(incrAmount);  
  45.             }  
  46.         });  
  47.           
  48.         btn=(ImageButton)findViewById(R.id.decr);  
  49.         btn.setOnClickListener(new View.OnClickListener() {  
  50.             public void onClick(View v) {  
  51.                 bar.incrementProgressBy(decrAmount);  
  52.             }  
  53.         });  
  54. //      this.addView(view);//不需要add,默认已经add了  
  55.     }  
  56. }  


attrs.xml: 

Xml代码   收藏代码
  1. <?xml version="1.0" encoding="utf-8"?>  
  2. <resources>  
  3.     <declare-styleable name="Meter">  
  4.         <attr name="max" format="integer" />  
  5.         <attr name="incr" format="integer" />  
  6.         <attr name="decr" format="integer" />  
  7.     </declare-styleable>  
  8. </resources>  


meter.xml文件: 

Xml代码   收藏代码
  1. <?xml version="1.0" encoding="utf-8"?>  
  2. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"  
  3.     android:orientation="horizontal"  
  4.     android:layout_width="fill_parent"  
  5.     android:layout_height="wrap_content"  
  6. >  
  7.     <ImageButton android:id="@+id/decr"  
  8.         android:layout_height="wrap_content"  
  9.         android:layout_width="wrap_content"  
  10.         android:scaleType="fitCenter"  
  11.         android:src="@drawable/arrow_down"  
  12.     />  
  13.     <ProgressBar android:id="@+id/bar"  
  14.         style="?android:attr/progressBarStyleHorizontal"  
  15.         android:layout_width="wrap_content"  
  16.         android:layout_height="wrap_content"  
  17.         android:layout_weight="1"  
  18.         android:layout_gravity="center_vertical"  
  19.     />  
  20.     <ImageButton android:id="@+id/incr"  
  21.         android:layout_height="wrap_content"  
  22.         android:layout_width="wrap_content"  
  23.         android:scaleType="fitCenter"  
  24.         android:src="@drawable/arrow_up"  
  25.     />  
  26. </LinearLayout>  


使用: 

Java代码   收藏代码
  1. @Override  
  2.     public void onCreate(Bundle savedInstanceState) {  
  3.         super.onCreate(savedInstanceState);  
  4.         setContentView(R.layout.main);  
  5.     }  


main.xml: 

Xml代码   收藏代码
  1. <?xml version="1.0" encoding="utf-8"?>  
  2. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"  
  3.     xmlns:app="http://schemas.android.com/apk/res/com.ql.app"  
  4.     android:orientation="horizontal"  
  5.     android:layout_width="fill_parent"  
  6.     android:layout_height="wrap_content"  
  7.     >  
  8.     <com.ql.app.Meter  
  9.         android:id="@+id/meter"  
  10.         android:layout_width="fill_parent"  
  11.         android:layout_height="wrap_content"  
  12.         app:max="100"  
  13.         app:incr="5"  
  14.         app:decr="5"  
  15.     />  
  16. </LinearLayout>  



 

猜你喜欢

转载自ztlblogs.iteye.com/blog/1962663