今天实现一个非常简单的自定义控件,带删除按钮的EditText框。
首先我们要有明确的需求,要做一个怎样的EditText框,他都要实现哪些功能?
既然这样,那我们就自己给自己定个需求。
1.需要在EdtiText没输入文字的时候和普通的EditText框没什么区别,有文字输入的时候才会出现删除按钮(关于用户体验的)。
2.需要可以自己设置删除按钮的图片
3.需要和系统自带的控件一样有逼格,可以在XML中设置控件属性。
好了,暂时就这么多,那我们开始吧!
第一步:创建控件布局:(定义一个EditText,还有删除按钮,这里我们使用ImageView)
R.Layout.edittext_del_layout
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent" android:layout_height="match_parent">
<EditText android:id="@+id/editText"
android:layout_width="fill_parent"
android:layout_height="45dp"
/>
<ImageView android:id="@+id/img_del"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/ic_launcher"
android:layout_alignRight="@+id/editText"
android:layout_alignTop="@+id/editText"
android:layout_alignBottom="@+id/editText"
android:scaleType="centerCrop"
android:visibility="gone"
android:padding="5dp"
/>
</RelativeLayout>
第二步:自定义控件属性
自定义控件属性的目的是为了像系统自带控件一样在xml文件中使用类似于android:layout_width这样的方式来设置属性。
首先在在res/values目录下创建attrs.xml文件,内容如下
<?xml version="1.0" encoding="utf-8"?>
<resources>
<declare-styleable name="EditTextDeleteView">
<attr name="drawable" format="reference"></attr>
<attr name="hint" format="string"></attr>
</declare-styleable>
</resources>
这里我们定义了两个属性:
drawable:用于设置删除按钮的图片。name="drawable"指的是这个属性的名字,是自定义的,也可以叫"src"或者"image"都可以。format="reference"指的是属性值类型是引用类型,调用的时候我们可以这样来调用,例如myview:drawable="@drawable/ic_launcher",format的值有很多种,如下图,我们可以根据自己的实际需求来设置。
fromat也可以设置多种类型,例如format="reference|color",表示值可以是图片,也可以是颜色(注意中间有个竖线 "|"
hint:用于设置EditText的默认文字。类型是字符串。
第三步:编写控件代码
新建一个类,EditTextDeleteView,让他继承自RelativeLayout
实现他的构造方法,这里有三个构造方法可选:
public EditTextDeleteView(Context context)
public EditTextDeleteView(Context context,AttributeSet attrs)
public EditTextDeleteView(Context context, AttributeSet attrs, int defStyleAttr)
那我们该选择实现哪一个呢?
如果这个控件没有自定义属性,那我们选择第一种。
如果这个控件有自定义属性,我们选择第二种。
如果这个控件要设置单独的样式,我们选择第三种。
很明显这里我们选择第二种,因为我们需要使用到自定义属性。
完整的代码如下:
public class EditTextDeleteView extends RelativeLayout {
private ImageView img_del;
private EditText editText;
private RelativeLayout relativeLayout;
public EditTextDeleteView(Context context) {
super(context);
}
public EditTextDeleteView(Context context,AttributeSet attrs)
{
super(context, attrs);
//获取xml布局文件中的自定义属性的值
TypedArray array = context.obtainStyledAttributes(attrs,R.styleable.EditTextDeleteView);
Drawable drawable = array.getDrawable(R.styleable.EditTextDeleteView_drawable);
CharSequence hint = array.getText(R.styleable.EditTextDeleteView_hint);
//初始化组合控件布局
relativeLayout = (RelativeLayout) LayoutInflater.from(context).inflate(R.layout.edittext_del_layout,this,true);
img_del = (ImageView) relativeLayout.findViewById(R.id.img_del);
editText = (EditText) relativeLayout.findViewById(R.id.editText);
//给控件赋值
editText.setHint(hint);
if(drawable != null)
{
img_del.setImageDrawable(drawable);
}
//给控件添加事件,点击删除图片的时候将EditText的文字内容设置为空字符
img_del.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
editText.setText("");
}
});
//在EditText中的内容发生改变时,控制删除按钮的显示和隐藏
editText.addTextChangedListener(new TextWatcher() {
@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
if(s.length() > 0)
{
img_del.setVisibility(VISIBLE);
}else
{
img_del.setVisibility(GONE);
}
}
@Override
public void afterTextChanged(Editable s) {
}
});
//回收TypedArray
array.recycle();
};
public String getText()
{
return editText.getText().toString();
}
public void setText(String str)
{
editText.setText(str);
}
public void setDeleteImageResources(int id)
{
img_del.setImageResource(id);
}
public void setHint(CharSequence hint)
{
editText.setHint(hint);
}
}
第四步:调用
控件写好了我们调用一下试试吧。
创建界面布局文件:R.layout.activity_main
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent">
<com.example.joy.myapplication.EditTextDeleteView
android:id="@+id/editTextDeleteView"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
app:drawable="@drawable/remove"
app:hint="请输入文字">
</com.example.joy.myapplication.EditTextDeleteView>
</RelativeLayout>
主界面代码:
public class MainActivity extends ActionBarActivity{
private EditTextDeleteView editTextDeleteView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
editTextDeleteView = (EditTextDeleteView) findViewById(R.id.editTextDeleteView);
}
}
可能有的同学已经发现了
app:hint="请输入文字"
app:drawable="@drawable/remove"
hint和drawable是我们attrs文件中定义的,但是前面的app是从哪来的?
实际上app这个名字是我们自己定义的,我们只需要在我们R.layout.activity_main布局文件的根节点中声明一下,就可以使用了
xmlns:app="http://schemas.android.com/apk/res-auto"<!-- android studio声明方式 -->
这里使用的xmlns:app ,我们就用app:drawable来调用,如果我们换成其他名字例如xmlns:myview,我们就使用myview:drawable来调用。
注:本人使用的开发环境是android studio,android studio中自定义控件的xmlns声明和eclipse中略有不同,eclipse中可能会是如下方式:
xmlns:app="http://schemas.android.com/apk/res/com.example.joy.myapplication.EditTextDeleteView" <!-- eclipse声明方式 -->
到此一个简单的带删除的EditText自定义控件就完成了,我们运行一下看看效果