自定义控件分三种:
- 自绘控件
- 组合控件
- 继承控件
代码已上传到 github
以后的自定义控件就都放这个仓库
需求
这里由于项目的需要实现一个自定义EditText,主要实现的为两点,一个是工具图标toolIcon,例如点击清除EditText内容。一个为EditText左边的提示图标hintIcon, 例如输入账号密码时前面的图标。
为了让这个控件的拓展性更高,设置了两个点击事件接口。对于toolIcon来说,默认点击事件为清除EditText内容,如果需要更改,在代码中设设置相关的点击事件即可。
步骤
- 继承EditText
- 编写attrs.xml, 创建declare-styleable
- 编写MyEditText
- 布局中使用
实现
获取布局文件中设置的属性
这里返回的是一个TypedArray数组,获取之后就可以获得布局文件中设置的属性了
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
| private void init(Context context, AttributeSet attrs) { TypedArray typedArray = context.getTheme().obtainStyledAttributes( attrs, R.styleable.MyEditText, 0, 0);
hintIcon = typedArray.getDrawable(R.styleable.MyEditText_hintIcon); toolIcon = typedArray.getDrawable(R.styleable.MyEditText_toolIcon); fixed = typedArray.getBoolean(R.styleable.MyEditText_fixed, true);
if (toolIcon != null && fixed) { setHeight(toolIcon.getIntrinsicHeight()); }
setCompoundDrawablesWithIntrinsicBounds(hintIcon, null, null, null);
setCompoundDrawablePadding(10);
typedArray.recycle();
onClickListenerWithEditTextToolIcon = new OnClickListenerWithEditTextToolIcon() { @Override public void onClick() { setText(""); } }; }
|
设置资源图片
EditText是继承自TextView,在TextView中存在两个方法
1 2
| setCompoundDrawablesWithIntrinsicBounds(left, top, right, bottom) setCompoundDrawables(left, top, right, bottom)
|
是设置资源图片的位置,第一个方法和第二个方法的区别在于第一个方法中资源图片的大小是由系统来获取图片固有的大小,第二个方法则是需要自己通过LayoutParams设置大小。
设置点击事件
我们通过setCompoundDrawables()等方法设置的图片,而由于在父类中并没有提供相关的图片点击处理接口,因此可以重写onTouchEvent()来实现相关的点击事件,只需要根据我们手指落点或抬起点的位置就可以判断手指是否点击了相关图片。在这里,我选择了手指抬起时处理
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47
|
@Override public boolean onTouchEvent(MotionEvent event) {
if (event.getAction() == MotionEvent.ACTION_UP) { if (hintIcon != null) { if (event.getX() < hintIcon.getIntrinsicWidth() && event.getX() > 0) { if (getCompoundDrawables()[0] != null && onClickListenerWithEditTextHintIcon != null) { onClickListenerWithEditTextHintIcon.onClick(); } } }
if (toolIcon != null) { if (event.getX() > (getWidth() - toolIcon.getIntrinsicWidth()) && event.getX() < getWidth()) { if (getCompoundDrawables()[2] != null ) { onClickListenerWithEditTextToolIcon.onClick(); } } } }
return super.onTouchEvent(event); }
public interface OnClickListenerWithEditTextHintIcon { void onClick(); }
public interface OnClickListenerWithEditTextToolIcon { void onClick(); }
|
完整代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167
| package com.customwidget.lzqwidget.cuswidget;
import android.content.Context; import android.content.res.TypedArray; import android.graphics.drawable.Drawable; import android.util.AttributeSet; import android.view.MotionEvent; import android.widget.EditText;
import com.customwidget.lzqwidget.R;
public class MyEditText extends EditText {
private Drawable hintIcon = null; private Drawable toolIcon = null;
private OnClickListenerWithEditTextHintIcon onClickListenerWithEditTextHintIcon = null;
private OnClickListenerWithEditTextToolIcon onClickListenerWithEditTextToolIcon = null;
private boolean fixed = true;
public MyEditText(Context context) { super(context); }
public MyEditText(Context context, AttributeSet attrs) { super(context, attrs); init(context, attrs); }
public MyEditText(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); init(context, attrs); }
private void init(Context context, AttributeSet attrs) { TypedArray typedArray = context.getTheme().obtainStyledAttributes( attrs, R.styleable.MyEditText, 0, 0);
hintIcon = typedArray.getDrawable(R.styleable.MyEditText_hintIcon); toolIcon = typedArray.getDrawable(R.styleable.MyEditText_toolIcon); fixed = typedArray.getBoolean(R.styleable.MyEditText_fixed, true);
if (toolIcon != null && fixed) { setHeight(toolIcon.getIntrinsicHeight()); }
setCompoundDrawablesWithIntrinsicBounds(hintIcon, null, null, null);
setCompoundDrawablePadding(10);
typedArray.recycle();
onClickListenerWithEditTextToolIcon = new OnClickListenerWithEditTextToolIcon() { @Override public void onClick() { setText(""); } }; }
@Override public boolean onTouchEvent(MotionEvent event) {
if (event.getAction() == MotionEvent.ACTION_UP) { if (hintIcon != null) { if (event.getX() < hintIcon.getIntrinsicWidth() && event.getX() > 0) { if (getCompoundDrawables()[0] != null && onClickListenerWithEditTextHintIcon != null) { onClickListenerWithEditTextHintIcon.onClick(); } } }
if (toolIcon != null) { if (event.getX() > (getWidth() - toolIcon.getIntrinsicWidth()) && event.getX() < getWidth()) { if (getCompoundDrawables()[2] != null ) { onClickListenerWithEditTextToolIcon.onClick(); } } } }
return super.onTouchEvent(event); }
public void setOnClickListenerWithEditTextHintIcon( OnClickListenerWithEditTextHintIcon clickListenerOfHintIcon) { this.onClickListenerWithEditTextHintIcon = clickListenerOfHintIcon; }
public void setOnClickListenerWithEditTextToolIcon( OnClickListenerWithEditTextToolIcon clickListenerOfToolIcon) { this.onClickListenerWithEditTextToolIcon = clickListenerOfToolIcon; }
@Override protected void onTextChanged(CharSequence text, int start, int lengthBefore, int lengthAfter) { super.onTextChanged(text, start, lengthBefore, lengthAfter);
if (text.length() > 0 && getCompoundDrawables()[2] == null && toolIcon != null) {
setCompoundDrawablesWithIntrinsicBounds(hintIcon, null, toolIcon, null); }
if (text.length() == 0 && getCompoundDrawables()[2] != null && toolIcon != null) { setCompoundDrawablesWithIntrinsicBounds(hintIcon, null, null, null); } }
public interface OnClickListenerWithEditTextHintIcon { void onClick(); }
public interface OnClickListenerWithEditTextToolIcon { void onClick(); } }
|
attrs.xml:
1 2 3 4 5 6 7 8 9 10
| <?xml version="1.0" encoding="utf-8"?> <resources>
<declare-styleable name="MyEditText"> <attr name="hintIcon" format="integer" /> <attr name="toolIcon" format="integer" /> <attr name="fixed" format="boolean" /> </declare-styleable>
</resources>
|