有如下一个组件:
最外有一个LinearLayout,包含左边的一个TextView和一个右边的EditText。
在你的APP的使用场景较多,为方便使用,决定自定义此组件,并设定相关xml属性,方便设置。
step1:
定义MyComponent继承至LinearLayout,添加构造方法、左侧和右侧view的相关属性。
public class MyComponent extends LinearLayout {
//左边
private String txtLeft;
//右边
private String txtRightHint;
@SuppressLint("NewApi")
public MyComponent(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
// TODO Auto-generated constructor stub
}
public MyComponent(Context context, AttributeSet attrs) {
this(context, attrs, 0);
// TODO Auto-generated constructor stub
}
public MyComponent(Context context) {
this(context, null);
// TODO Auto-generated constructor stub
}
}
在这三个构造方法中,第二个方法必须,不然会inflate xml报错。为了防止错误,使用this互相调用,避免出错。待会我们在三个参数的构造方法操作。
step2 :
在res/values下建立resource文件,定义attr属性
<?xml version="1.0" encoding= "utf-8"?>
<resources>
<declare-styleable name = "MyComponentAttr">
<!-- 文字属性 -->
<attr name ="txtLeft" format = "string"></attr >
<!-- 文字属性 -->
<attr name ="txtRightHint" format = "string"></attr >
</declare-styleable >
</resources>
step3:
在xml文件中,使用定义的组件,设置相关属性,别忘了加上命名空间,不然会报错。
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:app= "http://schemas.android.com/apk/res/com.ctrlz.csdnblog"
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.ctrlz.csdnblog.MainActivity$PlaceholderFragment" >
<!-- 需要加上命名空间 -->
<!-- xmlns:app="http://schemas.android.com/apk/res/yourPackageName" -->
<com.ctrlz.csdnblog.MyComponent
android:layout_width ="wrap_content"
android:layout_height= "wrap_content"
app:txtLeft= "充值号码:"
app:txtRightHint = "请输入充值号码"
>
</com.ctrlz.csdnblog.MyComponent >
</RelativeLayout>
step 4:
完善MyComponent构造方法:
public class MyComponent extends LinearLayout {
//左边
private String txtLeft;
//右边
private String txtRightHint;
private TextView tv;
private EditText et;
@SuppressLint( "NewApi")
public MyComponent(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
//获得对属性集的引用,然后就可以用"ta"的各种方法来获取相应的属性值了
TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.MyComponent );
this. txtLeft = ta.getString(R.styleable.MyComponent_txtLeft );
this. txtRightHint = ta.getString(R.styleable.MyComponent_txtRightHint );
//设置最外层的LinearLayout
setLayoutParams( new LinearLayout.LayoutParams(426, 66));
setOrientation( HORIZONTAL);
setGravity(Gravity. CENTER_VERTICAL);
setAddStatesFromChildren( true);
setBackgroundResource(R.drawable. bg_et_focus);
//TextView
tv = new TextView(context);
//设置大小
tv.setLayoutParams( new LayoutParams(120, 66));
tv.setText( txtLeft);
tv.setTextSize(22);
//设置位置
tv.setGravity(Gravity. CENTER_VERTICAL | Gravity.RIGHT );
addView( tv);
//EditText
et = new EditText(context);
et.setPadding(10, 0, 0, 0);
et.setLayoutParams( new LayoutParams(266, 66));
et.setHint( txtRightHint);
et.setTextSize(22);
et.setGravity(Gravity. CENTER_VERTICAL);
addView( et);
//回收资源
ta.recycle();
}
public MyComponent(Context context, AttributeSet attrs) {
this(context, attrs, 0);
// TODO Auto-generated constructor stub
}
public MyComponent(Context context) {
this(context, null);
// TODO Auto-generated constructor stub
}
}
结果:
效果看起来还不错吧。
整个自定义组件的过程就是概括为在attrs中设置属性名字,在xml中加上命名空间,为自定义属性赋值。同时在代码中,通过obtainStyledAttributes获取相应的在xml中赋的值。