之前拜读 xiaanming 大神写的文章xiaanming 大神的代码进行了改造,最终达到类似电脑Backspace按键一样的效果,长按的时候,会逐个删除输入框里面的文本.
改造仅修改了原代码中的OnTouchEvent事件的处理,增加了一个长按判断,使其可以处理输入框右边删除图标范围内的长按事件.
具体的步骤为在ACTION_DOWN事件中初始化初始点击坐标,这个坐标将用来判断滑动事件,因为长按的时候手指可能会有轻微的滑动,只要范围不是特别大,都可以算作是长按事件;然后还需要一个定时器,使之每隔一段时间删除一个字符,这里我定义为100ms,经过实验发现这个时长非常合适;在ACTION_MOVE事件中,只要不满足条件则终止定时器.
这里因为涉及到多线程处理,需要定义一个Handler来修改UI.
@Override
public boolean onTouchEvent(MotionEvent event) {
// TODO Auto-generated method stub
/**
* 滑动的距离
*/
float moveL=0;
/**
* 本次事件是否在判断范围之内
*/
boolean touchable=(event.getX()>(this.getWidth()-this.getTotalPaddingRight()))&&(event.getX()
if((event.getAction()==MotionEvent.ACTION_DOWN)&&touchable){
/**
* 初始点击坐标
*/
startX=event.getX();
startY=event.getY();
/**
* 字符可能会很长,使用StringBuilder可以提高性能
* 面试栽了两回的惨痛教训!!!
*/
text=new StringBuilder(this.getText());
timer=new Timer();
/**
* 从当前时间开始,每隔100毫秒执行一次
*/
timer.schedule(new TimerTask(){
@Override
public void run() {
// TODO Auto-generated method stub
if(text.length()>0){
/**
* 删除最后一个字符
*/
text=text.deleteCharAt(text.length()-1);
/**
* 每个Message只能使用一次
*/
Message msg=new Message();
msg.what=1;
msg.obj=text;
handler.sendMessage(msg);
}
Log.d("TAG_TASK","Running---");
}},0,100);
}
if(event.getAction()==MotionEvent.ACTION_MOVE){
if(touchable){
moveL=(float)Math.sqrt(Math.pow((getX()-startX),2)+Math.pow((getY()-startY), 2));
/**
* 滑动距离超出一个小范围则终止计时器
*/
if(moveL>15&&timer!=null){
Log.d("TAG_ACTION_MOVE","滑动!cancel---");
timer.cancel();
timer=null;
}
}else{
Log.d("TAG_ACTION_MOVE","越界!cancel---");
if(null!=timer){
timer.cancel();
timer=null;
}
}
}
if(event.getAction()==MotionEvent.ACTION_UP){
if(null!=timer){
timer.cancel();
timer=null;
}
//if(mClearDrawable[2]!=null){
//touchable=(event.getX()>(this.getWidth()-this.getTotalPaddingRight()))&&(event.getX()
//if(touchable){
//this.setText("");
//}
//}
}
return super.onTouchEvent(event);
}
修改UI的时候,每次setText之后光标会自动定位到最左边,这里需要给他重新移动到右边去.
private Handler handler=new Handler(){
@Override
public void handleMessage(Message msg) {
// TODO Auto-generated method stub
if(msg.what==1){
setText((CharSequence) msg.obj);
setSelection(((CharSequence) msg.obj).length());
}
}
};
其他地方的代码没有作大的修改,基本与
xiaanming 大神的一致.全部代码如下:
package phy.minichat.test;
import java.util.Timer;
import java.util.TimerTask;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.drawable.Drawable;
import android.os.Handler;
import android.os.Message;
import android.text.Editable;
import android.text.TextWatcher;
import android.util.AttributeSet;
import android.util.Log;
import android.widget.EditText;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnFocusChangeListener;
/**
* 自定义输入框
* @author 烟斜洞庭
*
*/
public class MyEditText extends EditText implements OnFocusChangeListener,TextWatcher{
private Drawable[] mClearDrawable;
/**
* 输入框的内容
*/
StringBuilder text;
float startX,startY;
Timer timer;
private Handler handler=new Handler(){
@Override
public void handleMessage(Message msg) {
// TODO Auto-generated method stub
if(msg.what==1){
setText((CharSequence) msg.obj);
setSelection(((CharSequence) msg.obj).length());
}
}
};
public MyEditText(Context context, AttributeSet attrs) {
this(context, attrs,android.R.attr.editTextStyle);
// TODO Auto-generated constructor stub
}
public MyEditText(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
// TODO Auto-generated constructor stub
init();
}
public MyEditText(Context context) {
this(context,null);
// TODO Auto-generated constructor stub
}
@Override
public void onFocusChange(View v, boolean hasFocus) {
// TODO Auto-generated method stub
if(hasFocus){
setClearIconVisible(this.getText().length()>0);
}else{
setClearIconVisible(false);
}
}
@Override
public void beforeTextChanged(CharSequence s, int start, int count,
int after) {
// TODO Auto-generated method stub
}
@Override
public void afterTextChanged(Editable s) {
// TODO Auto-generated method stub
}
protected void setClearIconVisible(boolean visible){
Drawable right=visible?mClearDrawable[2]:null;
this.setCompoundDrawables(mClearDrawable[0], mClearDrawable[1], right, mClearDrawable[3]);
}
@Override
public void onTextChanged(CharSequence text, int start,
int lengthBefore, int lengthAfter) {
// TODO Auto-generated method stub
if(this.hasFocus()){
this.setClearIconVisible(text.length()>0);
}
}
@Override
public boolean onTouchEvent(MotionEvent event) {
// TODO Auto-generated method stub
/**
* 滑动的距离
*/
float moveL=0;
/**
* 本次事件是否在判断范围之内
*/
boolean touchable=(event.getX()>(this.getWidth()-this.getTotalPaddingRight()))&&(event.getX()
if((event.getAction()==MotionEvent.ACTION_DOWN)&&touchable){
/**
* 初始点击坐标
*/
startX=event.getX();
startY=event.getY();
/**
* 字符可能会很长,使用StringBuilder可以提高性能
* 面试栽了两回的惨痛教训!!!
*/
text=new StringBuilder(this.getText());
timer=new Timer();
/**
* 从当前时间开始,每隔100毫秒执行一次
*/
timer.schedule(new TimerTask(){
@Override
public void run() {
// TODO Auto-generated method stub
if(text.length()>0){
/**
* 删除最后一个字符
*/
text=text.deleteCharAt(text.length()-1);
/**
* 每个Message只能使用一次
*/
Message msg=new Message();
msg.what=1;
msg.obj=text;
handler.sendMessage(msg);
}
Log.d("TAG_TASK","Running---");
}},0,100);
}
if(event.getAction()==MotionEvent.ACTION_MOVE){
if(touchable){
moveL=(float)Math.sqrt(Math.pow((getX()-startX),2)+Math.pow((getY()-startY), 2));
/**
* 滑动距离超出一个小范围则终止计时器
*/
if(moveL>15&&timer!=null){
Log.d("TAG_ACTION_MOVE","滑动!cancel---");
timer.cancel();
timer=null;
}
}else{
Log.d("TAG_ACTION_MOVE","越界!cancel---");
if(null!=timer){
timer.cancel();
timer=null;
}
}
}
if(event.getAction()==MotionEvent.ACTION_UP){
if(null!=timer){
timer.cancel();
timer=null;
}
//if(mClearDrawable[2]!=null){
//touchable=(event.getX()>(this.getWidth()-this.getTotalPaddingRight()))&&(event.getX()
//if(touchable){
//this.setText("");
//}
//}
}
return super.onTouchEvent(event);
}
public void init(){
mClearDrawable=this.getCompoundDrawables();
if(mClearDrawable[2]!=null){
//mClearDrawable[2].setBounds(left, top, right, bottom);
setClearIconVisible(false);
setOnFocusChangeListener(this);
addTextChangedListener(this);
}
}
}