前言
我们要写一个自定义组合控件,放在MainActivity中,MainActivity的布局文件是Android Studio自动生成,名字是activity_main.xml我们要写的自定义组合控件由3个TextView组成(叫它们 num1,num2, num3 吧),分别显示三个数字。 规律是 num1显示 a,mum2和num3 就显示 (a+1)和(a+2)。根据需求,我们需要给自定义控件增加一个自定义属性:startNum。它代表了num1显示的数字。步骤:
在values下面新建一个名叫attrs(这个随意)的XML;一个declare-styleable标签被称作一个TypeArray,每个declare-styleable标签可以包含多个attr子标签。 attr的写法是 一个name,一个format。 比如” <resources> <declare-styleable name="texts"> <attr name="startNum" format="integer"/> </declare-styleable> </resources>format类型参考链接:http://blog.csdn.net/lincyang/article/details/7421757
新建一个XML作为布局文件,这里我们取名my_customed_view.xml. 以LinearLayout包裹,所以等会儿的组合控件也必须继承自LinearLayout ,在这里写好组合控件的样子。新建一个JAVA类:MyCustomedView,名称随意。继承自LinearLayout。这时候android studio会提示你实现构造方法,选择自动实现之;在出来的4个方法中,第一个方法只适用于代码创建。我们在XML中定义的自定义控件需要从AttributeSet这个类中读取属性。先放一下这里。我们重新回到布局文件中, 在 activity_main.xml中写下(怎么布局自己定,我为了简单,就放了这么一个组合控件): <com.huang.android.customedview1.MyCustomedView texts:startNum = "5" android:layout_width="wrap_content" android:layout_height="wrap_content" />这时Android Studio会报错,提示不知道 texts:startNum是个啥。别急,在activity_main.xml根布局元素里面增加也一句:
xmlns:my_name_space = "http://schemas.android.com/apk/res-auto"my_name_space可以随便写,等号后面的不能改。Gradle现在已经可以实现自动查找对应的TypeArray和属性了,找不到编译通不过的。
MyCustomedView中,我们在……比如public MyCustomedView(Context context, AttributeSet attrs)这个方法中,定义一个 private int startNum; private TypedArray ta; private Context mContext; private TextView num1; private TextView num2; private TextView num3;于此同时,我们看到构造方法中的 AttributeSet attrs``这个参数。Context提供了 一系列`obtainStyledAttributes`的重载从attr对象中提取出调用者填写的属性。 这里我们简单点儿: ta = mContext.obtainStyledAttributes(attrs,R.styleable.texts);“` 此时ta中保存的就是我们之前定义在attrs.xml中的 ,名为texts的 declare-styleable标签…….下的attr子标签了 (不信你可以Toast一下它的长度)。
接下来还有两步必须: 调用LayoutInflater绘制 ViewLayoutInflater.from(mContext).inflate(R.layout.my_customed_view,this); //注意这个this 取出我们想要的属性: int startNum = ta.getInteger(R.styleable.texts_startNum,4); //我们的属性是startNum. //Android Studio自动在它前面加上texts_来表明它是texts下的startNum属性,避免冲突。 收工,拿到属性想怎么处理都是你的事情了。附上代码: MainActivity的布局文件:
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" xmlns:my_name_space = "http://schemas.android.com/apk/res-auto" android:layout_width="match_parent" android:layout_height="match_parent" android:paddingBottom="@dimen/activity_vertical_margin" android:paddingLeft="@dimen/activity_horizontal_margin" android:paddingRight="@dimen/activity_horizontal_margin" android:paddingTop="@dimen/activity_vertical_margin" tools:context="com.huang.android.customedview1.MainActivity"> <com.huang.android.customedview1.MyCustomedView my_name_space:startNum = "5" android:layout_width="match_parent" android:layout_height="wrap_content" /> </RelativeLayout>MyCustomedView自定义组合控件类
public class MyCustomedView extends LinearLayout { private int startNum; private TypedArray ta; private Context mContext; private TextView num1; private TextView num2; private TextView num3; public MyCustomedView(Context context) { super(context); mContext = context; } public MyCustomedView(Context context, AttributeSet attrs) { super(context, attrs); mContext = context; ta = mContext.obtainStyledAttributes(attrs,R.styleable.texts); Toast.makeText(mContext,"length == "+ta.length(),Toast.LENGTH_LONG).show(); initViews(); } public MyCustomedView(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); mContext = context; initViews(); } public MyCustomedView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) { super(context, attrs, defStyleAttr, defStyleRes); mContext = context; initViews(); } private void initViews() { LayoutInflater.from(mContext).inflate(R.layout.my_customed_view,this); num1 =(TextView) findViewById(R.id.TV_num1); num2 =(TextView) findViewById(R.id.TV_num2); num3 =(TextView) findViewById(R.id.TV_num3); startNum = ta.getInteger(R.styleable.texts_startNum,4); num1.setText(startNum+""); num2.setText( (startNum+1)+""); num3.setText( (startNum+2)+""); } }MyCustomedView布局文件:
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="wrap_content"> <TextView android:id="@+id/TV_num1" android:layout_weight="1" android:layout_width="0dp" android:gravity="center_horizontal" android:layout_height="wrap_content" android:textSize="30sp" android:text="1" /> <TextView android:layout_weight="1" android:layout_width="0dp" android:layout_height="wrap_content" android:text="2" android:gravity="center_horizontal" android:textSize="30sp" android:id="@+id/TV_num2"/> <TextView android:text="3" android:layout_weight="1" android:layout_width="0dp" android:layout_height="wrap_content" android:gravity="center_horizontal" android:textSize="30sp" android:id="@+id/TV_num3" /> </LinearLayout>Values目录下的attrs.xml
<?xml version="1.0" encoding="utf-8"?> <resources> <declare-styleable name="texts"> <attr name="startNum" format="integer"/> </declare-styleable> </resources>