Android 自定义自动清空EditText

   Android系统自带的EditText,虽然功能是实现了,但是总是感觉给人是缺胳膊少腿的。你就不能像ios一样,输入框的末尾加个小叉叉吗?通常Android要实现这个功能,很常见的是使用组合布局实现,但是这样不好!原因可见这篇文章Android 性能优化之布局优化。还有就是利用EditText的drawableRight属性添加一张图片实现,但是通常又要UI妹妹切一张图甚是麻烦!于是,我觉得直接用Java代码画出一个叉叉,实现一键清空的EdidText不就好了嘛 。高仿京东首页搜索框!

   效果图:

   

   首先说明下我们的思路:自定义一个Drawable类用于画叉叉,然后充当自定义的EditText的drawableRight,最后添加相应的事件监听即可!

   1.创造我们需要的Drawable,命明为DeleteDrawable。

public class DeleteDrawable extends Drawable{

    @Override
    public void draw(Canvas canvas) { }

    @Override
    public void setAlpha(int alpha) { }

    @Override
    public void setColorFilter(ColorFilter colorFilter) { }

    @Override
    public int getOpacity() {return PixelFormat.TRANSLUCENT;}
}

可见继承自Drawable一共必须要实现 上述四个方法,setAlpha和setColorFiler是设置透明度和设置颜色过滤器,通常利用自定义Drawable里面的Paint调用对应的api设置即可。getOpacity()是关于透明度的,通常有PixelFormat.TRANSLUCENT、PixelFormat.TRANSPARENT、PixelFormat.OPAQUE三个值,前两种支持透明度格式,只是一个是支持半透明,一个支持全透明。最后一个不支持透明。这四个方法中最重要的就是draw方法了,它是我们画叉叉的关键。里面的Canvas参数是控件的OnDraw方法里面传下来的!如下DeleteDrawable的全部代码:

class DeleteDrawable extends Drawable{
    private float mSize;
	private Paint mPaint;
	 
	public DeleteDrawable(float size){
		mSize=size;
		init();
	}
	 
	private void init(){
		 mPaint=new Paint();
		 mPaint.setAntiAlias(true);
		 mPaint.setStyle(Paint.Style.FILL);
	}

	 @Override
	public void draw(Canvas canvas) {
		float space=mSize/5;
		float centerX=mSize/2;
		float centerY=mSize/2;
		float width=mSize/10;
		
		mPaint.setColor(mDeleteBgColor);//灰色
		canvas.drawCircle(centerX,centerY,centerX,mPaint);
		
		mPaint.setColor(Color.WHITE);
		canvas.save();
    	canvas.rotate(45,centerX,centerY);
    	canvas.drawRect(centerX-width/2,space,centerX+width/2,mSize-space,mPaint); //画矩形线
    	canvas.restore();
    	canvas.rotate(135,centerX,centerY);
    	canvas.drawRect(centerX-width/2,space,centerX+width/2,mSize-space,mPaint); //画矩形线
	}
	 
	@Override
	public void setAlpha(int alpha) {
		mPaint.setAlpha(alpha);
	}
	@Override
	public void setColorFilter(ColorFilter cf) {mPaint.setColorFilter(cf);}
	@Override
	public int getOpacity() {
		return PixelFormat.OPAQUE;
	}
	   
   }
其中成员变量mSize便是小叉叉圆圈所在的外切正方形的边长,同时也是小叉叉圆圈的直径。灰色圆圈里面的2条叉线是成90度相交的。
canvas.rotate(45,centerX,centerY);
表示把画布旋转45度,canvas.save()表示保存当前画布状态,即画布没有旋转的状态。width表示小叉叉线(矩形的宽)至于它的长是mSize-2*space。想象一下倾斜着45度的叉叉线不就是把正规的十字叉旋转45度嘛!,canvas.restore表示回到最近的save状态,即画布没有旋转的状态。
如图(图比较丑,大家将就着看看,程序员的审美,哈哈)

好了,小叉叉画好了,接着我们需要给其添加事件了。

2.自定义EdiText,我们叫做CleanEditText好了。
我们需要2个关键的成员变量GradientDrawable和DeleteDrawable,前一个是EditText的背景,后一个是小叉叉!GradientDrawable是shape xml文件的Java对应的类。我们既然是自定义控件当然是做到最少的需要xml的帮助啦,这样移植的话一个类文件就搞定了,多开心!我们需要添加TextWatcher用于获得输入矿中的字符数目以便控制DeleteDrawable的显示和隐藏。重写控件的onSizeChanged方法(主要是怕用户开始时输入框中有字符,或者控件的大小发生了变化):
 @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
    	super.onSizeChanged(w, h, oldw, oldh);
    	if(mDeleteDrawable==null){
    	  float length=getHeight()*0.45f;
    	  mDeleteDrawable=new DeleteDrawable(length);
    	  mDeleteDrawable.setBounds(0,0,(int)length,(int)length);
    	  if(textAmount>0){
    	   setCompoundDrawables(null,null,mDeleteDrawable,null);
    	  }
    	}
    }
	

textAmount表示EdiText中的字符数目。setCompoundDrawables(null,null,mDeleteDrawable,null);给EditText右边缘设置Drawable。

再就是afterTextChanged中的代码:

@Override
    public void afterTextChanged(Editable s) {
 	    textAmount=s.toString().trim().length();
 	    //优化渲染,invalidate消耗性能 
 	    if((lastTextAmount==0&&textAmount>0)||(lastTextAmount>0&&textAmount==0)){ 
 	    if(textAmount>0&&mDeleteDrawable!=null){
 	      mCanClean=true;
 	      setCompoundDrawables(null,null,mDeleteDrawable,null);
 	    }else{
 	      mCanClean=false;
 	      setCompoundDrawables(null,null,null,null);
 	    }
 	      invalidate();
 	    }
 	    lastTextAmount=textAmount;
    }

mCanClean是Boolean类型的值,表示小叉叉是否出现。setCompoundDrawables(null,null,null,null);小叉叉消失,if((lastTextAmount==0&&textAmount>0)||(lastTextAmount>0&&textAmount==0)),文字从无到有或者从有到无才应该显示或者让小叉叉消失,设置完成之后需要调用invalidate()方法,让控件重绘,进而调用OnDraw方法。invalidate()方法相当的消耗性能所以需要上面的判断来优化渲染。

最后,我们需要给小叉叉提供点击事件:

public boolean onTouchEvent(MotionEvent event) {
    	super.onTouchEvent(event);
    	
    	switch (event.getAction()) {
    	//手指抬起
    	case MotionEvent.ACTION_UP:{
			int x=(int)event.getX();
			if(x>(getWidth()-getHeight()*0.9)&&mCanClean){
			   setText("");
			   if(mDeleteDrawable!=null){
				   mDeleteDrawable.setVisible(false,true);
			   }
			}
			return true;
    	}
    	
    	default:
    		break;
		}
    	return true;
    }
    
手指抬起的时候清空EditText,为何要乘以0.9,因为小叉叉的外切正方形的边长是getHeight()*0.45,这里设置成其2倍是为了,增大点击区域,提升体验!

到这里自定义一键清空的EditText基本完成,但是一个好的控件是高度支持定制化的,所有我们需要把小叉叉的背景颜色图,以及EditText的背景的颜色,圆角弧度等都抽出去。做成自定义属性,比较简单就不多做赘述了。最后给出了CleanEditText的全部代码,大家可以下载下来看看,欢迎大家,留言批评,共同探讨,共同进步!

CleanEditText的全部代码:CleanEditText

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值