在开发当中,为了达到特定的效果,仅仅依赖原有的android控件是不够的,这时候需要自定义一些控件。其实自定义控件,大体可分为三大类:
一、组合式控件,即将一些需要重复用到的一些控件包装在一起,组成一个新的控件;
二、继承现有的控件,自己去扩展其一些功能(如继承TextView ,EditText等);
三、继承一个View,自己去绘制出来。
可视具体情况,采取不同的方式来实现效果,这次主要说一下,自定义组合式控件,也是最简单的一种。
背景:实际项目中有这么一个需求,既不想要EditText自带的背景,又希望在其下面加上一条下划线,这可怎么破呢? 自然而然就会想到自定义一个组合式控件,上面一个去除背景样式的EditText,下面一个高度为0.5dp的View,即可。那么如何去自定义呢?大体只需要这么几个步骤:
1.将布局单独抽取出来;
2.定义一个类继承自布局的根容器;
3.将布局与创建的类关联起来;
4.自定义属性值;
5.获取并设置属性值;
6.在布局中使用该控件。
下面就一步步来实现这个小的效果吧:
1.将布局单独抽取出来,很简单布局如下:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical" >
<EditText
android:id="@+id/et_text"
android:textColor="#332E38"
android:textSize="13sp"
android:background="@null"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
<View
android:layout_width="match_parent"
android:layout_height="0.5dp"
android:background="@android:color/black"/>
</LinearLayout>
2.定义一个类继承自布局的根容器, 这里直接继承自LinearLayout。
3.将布局与创建的类关联起来;
5.获取并设置属性值;
这三步具体实现可看下面代码:
//2.定义一个类继承自根布局
public class LineEditText extends LinearLayout{
private static final int TYPE_DEFAUT = 3;
private Paint paint;
private EditText et_text;
//布局中使用,只需要重写带两个、三个参数的构造函数即可,最终是调用三个参数的构造
public LineEditText(Context context, AttributeSet attrs) {
this(context, attrs,0);
}
public LineEditText(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init(context,attrs);
}
private void init(Context context,AttributeSet attrs) {
//3.将布局与创建的类关联起来,注意第三个参数是this,而不是null,因为是要填充到当前容器中
View view = View.inflate(context, R.layout.view_lineedittext, this);
et_text = (EditText) view.findViewById(R.id.et_text);
//5.获取并设置属性值
TypedArray array = context.obtainStyledAttributes(attrs, R.styleable.LineEditText);
//输入文本属性
String lineText = array.getString(R.styleable.LineEditText_lineText);
//输入最大字符属性
int maxLength = array.getInt(R.styleable.LineEditText_textMaxLength,-1);
//输入类型属性
int inputType = array.getInt(R.styleable.LineEditText_textInputType, TYPE_DEFAUT);
//设置文本
et_text.setText(lineText);
//设置最大字符属性,这个可以去看下TextView的源码就知道为什么这么写了
if (maxLength >= 0) {
et_text.setFilters(new InputFilter[] { new InputFilter.LengthFilter(maxLength) });
}else{
et_text.setFilters(new InputFilter[0]);
}
//设置输入类型控制
switch (inputType) {
case TYPE_DEFAUT:
et_text.setInputType(InputType.TYPE_TEXT_FLAG_MULTI_LINE); //多行文本
//要使多行文本属性生效要加上下面两句才行
et_text.setSingleLine(false);
et_text.setHorizontallyScrolling(false);
break;
case 0:
et_text.setInputType(InputType.TYPE_CLASS_PHONE); //电话号码
break;
case 1:
et_text.setInputType(InputType.TYPE_CLASS_NUMBER); //数字
break;
case 2:
et_text.setInputType(InputType.TYPE_TEXT_FLAG_MULTI_LINE);
et_text.setSingleLine(false);
et_text.setHorizontallyScrolling(false);
break;
default:
et_text.setInputType(InputType.TYPE_TEXT_FLAG_MULTI_LINE);
et_text.setSingleLine(false);
et_text.setHorizontallyScrolling(false);
break;
}
//注意要回收
array.recycle();
}
/**
* 设置文本方法
* @param string
*/
public void setLineText(String string) {
et_text.setText(string);
}
/**
* 获取文本方法
* @param string
*/
public String getLineText() {
return et_text.getText().toString().trim();
}
}
4.自定义属性值,这个主要是在res/values/attrs.xml文件中进行自定义,这个可根据需要定义多种属性,如下所示:
<declare-styleable name ="LineEditText"> //name 最好为类名
<attr name = "lineText" format = "string"></attr> //format即是格式有string,integer,enum等
<attr name = "textMaxLength" format = "integer"></attr>
<attr name="textInputType" format="enum">
<enum name="phone" value="0" />
<enum name="number" value="1" />
<enum name="textMutiLine" value="2" />
</attr>
</declare-styleable>
最后一步,在布局文件中使用,拷贝自定义类的全路径,像使用其它控件一样,即可,记住要定义一个命名空间。
命名空间,自定义控件使用如下:
xmlns:lineEdit="http://schemas.android.com/apk/res/包名"
<com.zxhandroid.view.LineEditText
android:layout_width="match_parent"
lineEdit:textInputType="textMutiLine"
android:layout_height="wrap_content"
android:id="@+id/et_time"/>
到这里实现了一个简单的自定义控件了。。。。