在开发APP布局时候经常会看到在EditText
的右侧或者左侧出现类似ICON,比如查看密码,点击可以清空输入的字符等,我们通常的做法中在EditText
外层再套一层LinearLayout
,这无疑增加了布局的复杂度。
今天我们通过扩展EditText
来实现四个drawable
都可以点击的功能。
实现思路
重写onTouchEvent,当用户点击时,判断点击点是否在图标的位置上,如果在就拦截掉点击事件,调用点击图标的回调
实现步骤
- 通过
getCompoundDrawables()
取得四个方向的drawable - 取得点击的坐标
- 把坐标转换到drawable的坐标体系,难点为需要考虑到有多个的情况,所以左右的图标y通过文本垂直中线来计算,上下图标的x同理
- 分别判断坐标是否包含在图标区域拦截事件
完整实现类
package com.yy.drawableclickedittextdemo;
import android.content.Context;
import android.graphics.Rect;
import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
import android.view.MotionEvent;
public class ClickDrawableEditText extends android.support.v7.widget.AppCompatEditText {
private static String tag= ClickDrawableEditText.class.getSimpleName();
//点击位置
private int positionX = 0;
private int positionY;
// 回调接口
private OnDrawableClickListener onDrawableClickListener;
public ClickDrawableEditText(Context context, AttributeSet attrs) {
super(context, attrs);
}
public ClickDrawableEditText(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
public void setOnDrawableClickListener(OnDrawableClickListener onDrawableClickListener) {
this.onDrawableClickListener = onDrawableClickListener;
}
@Override
public boolean onTouchEvent(MotionEvent event) {
//图标区域
Rect bounds;
if (event.getAction() == MotionEvent.ACTION_DOWN) {
positionX = Math.round(event.getX());
positionY = Math.round(event.getY());
Drawable[] ds=this.getCompoundDrawables();
Drawable drawableRight = ds[2];
Drawable drawableLeft = ds[0];
Drawable drawableTop = ds[1];
Drawable drawableBottom = ds[3];
//计算点击点在Drawable中的位置
int xClickPosition,yClickPosition;
//长宽
int w=getWidth();
int h=getHeight();
//文本中心的坐标
int midX=(w-getTotalPaddingLeft()-getTotalPaddingRight())/2+getTotalPaddingLeft();
int midY=(h-getTotalPaddingTop()-getTotalPaddingBottom())/2+getTotalPaddingTop();
if (drawableLeft != null) {
bounds = drawableLeft.getBounds();
// 转换到drawableLeft坐标系统
xClickPosition = positionX-getPaddingLeft();
yClickPosition = (midY-positionY)+bounds.height()/2;
if (bounds.contains(xClickPosition, yClickPosition) && onDrawableClickListener != null) {
onDrawableClickListener.onClick(DrawablePosition.LEFT);
event.setAction(MotionEvent.ACTION_CANCEL);
return false;
}
}
if (drawableRight != null) {
bounds = drawableRight.getBounds();
xClickPosition = positionX - w + bounds.right +getPaddingRight();
yClickPosition= (midY-positionY)+bounds.height()/2;
if (bounds.contains(xClickPosition, yClickPosition) && onDrawableClickListener != null) {
onDrawableClickListener.onClick(DrawablePosition.RIGHT);
event.setAction(MotionEvent.ACTION_CANCEL);
return false;
}
}
if (drawableTop != null) {
bounds = drawableTop.getBounds();
xClickPosition = (midX - positionX)+bounds.width()/2;
yClickPosition= positionY - getPaddingTop();
if (bounds.contains(xClickPosition, yClickPosition) && onDrawableClickListener != null) {
onDrawableClickListener.onClick(DrawablePosition.TOP);
event.setAction(MotionEvent.ACTION_CANCEL);
return false;
}
}
if(drawableBottom!=null)
{
bounds = drawableBottom.getBounds();
xClickPosition = (midX - positionX)+bounds.width()/2;
yClickPosition= positionY - h + bounds.height()+ getPaddingBottom();
if (bounds.contains(xClickPosition, yClickPosition) && onDrawableClickListener != null) {
onDrawableClickListener.onClick(DrawablePosition.BOTTOM);
event.setAction(MotionEvent.ACTION_CANCEL);
return false;
}
}
}
return super.onTouchEvent(event);
}
/**
* 设置点击图标的侦听接口
*/
public interface OnDrawableClickListener{
public void onClick(int position);
}
/**
* 图标的位置方向
*/
public final static class DrawablePosition{
public final static int LEFT=0;
public final static int TOP=1;
public final static int RIGHT=2;
public final static int BOTTOM=3;
}
}
引用
在xml布局中引用控件
<com.yy.drawableclickedittext.ClickDrawableEditText
android:id="@+id/password"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="@string/prompt_password"
android:padding="0dp"
android:drawablePadding="10dp"
android:imeActionLabel="@string/action_sign_in_short"
android:inputType="textPassword"
android:maxLines="1"
android:singleLine="true"
android:drawableRight="@mipmap/city_icon_care"
android:drawableLeft="@mipmap/ic_launcher_round"
android:drawableTop="@mipmap/city_icon_care"
android:drawableBottom="@mipmap/ic_launcher_round"
/>
在界面中增加点击侦听
mPasswordView.setOnDrawableClickListener(new ClickDrawableEditText.OnDrawableClickListener() {
@Override
public void onClick(int position) {
String str="";
switch (position){
case ClickDrawableEditText.DrawablePosition.LEFT:
str="click left";
break;
case ClickDrawableEditText.DrawablePosition.TOP:
str="click top";
break;
case ClickDrawableEditText.DrawablePosition.RIGHT:
str="click right";
break;
case ClickDrawableEditText.DrawablePosition.BOTTOM:
str="click bottom";
break;
}
Toast.makeText(LoginActivity.this,str,Toast.LENGTH_SHORT).show();
}
});
demo下载
如果需要完整demo,请点击GitHub下载链接