当前位置: 移动技术网 > IT编程>移动开发>Android > Android如何自定义EditText下划线?

Android如何自定义EditText下划线?

2019年07月24日  | 移动技术网IT编程  | 我要评论

南京会斯通集团总裁,穿越清朝当皇帝txt,恶妃 朕要吃定你

曾经做过一个项目,其中登录界面的交互令人印象深刻。交互设计师给出了一个非常作的设计,要求做出包含根据情况可变色的下划线,左侧有可变图标,右侧有可变删除标志的输入框,如图

记录制作过程:

第一版本

public class lineedittext extends edittext {

private paint mpaint;
private int color;
public static final int status_focused = 1;
public static final int status_unfocused = 2;
public static final int status_error = 3;
private int status = 2;
private drawable del_btn;
private drawable del_btn_down;
private int focuseddrawableid = r.drawable.user_select;// 默认的
private int unfocuseddrawableid = r.drawable.user;
private int errordrawableid = r.drawable.user_error;
drawable left = null;
private context mcontext;
public lineedittext(context context) {

 super(context);
 mcontext = context;
 init();
}
public lineedittext(context context, attributeset attrs) {

 super(context, attrs);
 mcontext = context;
 init();

}
public lineedittext(context context, attributeset attrs, int defstryle) {

 super(context, attrs, defstryle);
 mcontext = context;
 typedarray a = context.obtainstyledattributes(attrs,
   r.styleable.lineedittext, defstryle, 0);
 focuseddrawableid = a.getresourceid(
   r.styleable.lineedittext_drawablefocus, r.drawable.user_select);
 unfocuseddrawableid = a.getresourceid(
   r.styleable.lineedittext_drawableunfocus, r.drawable.user);
 errordrawableid = a.getresourceid(
   r.styleable.lineedittext_drawableerror, r.drawable.user_error);
 a.recycle();
 init();
}
/** * 2014/7/31 * * @author aimee.zhang */

private void init() {
 mpaint = new paint();
 // mpaint.setstyle(paint.style.fill);
 mpaint.setstrokewidth(3.0f);
 color = color.parsecolor("#bfbfbf");
 setstatus(status);
 del_btn = mcontext.getresources().getdrawable(r.drawable.del_but_bg);
 del_btn_down = mcontext.getresources().getdrawable(r.drawable.del_but_bg_down);
 addtextchangedlistener(new textwatcher() {

  @override
  public void ontextchanged(charsequence arg0, int arg1, int arg2,
    int arg3) {
  }

  @override
  public void beforetextchanged(charsequence arg0, int arg1,
    int arg2, int arg3) {
  }

  @override
  public void aftertextchanged(editable arg0) {
   setdrawable();
  }
 });
 setdrawable();
}

@override
protected void ondraw(canvas canvas) {
 super.ondraw(canvas);
 mpaint.setcolor(color);
 canvas.drawline(0, this.getheight() - 1, this.getwidth(),
   this.getheight() - 1, mpaint);
}

// 删除图片
private void setdrawable() {
 if (length() < 1) {
  setcompounddrawableswithintrinsicbounds(left, null, del_btn, null);
 } else {
  setcompounddrawableswithintrinsicbounds(left, null, del_btn_down,null);
 }
}

// 处理删除事件
@override
public boolean ontouchevent(motionevent event) {
 if (del_btn_down != null && event.getaction() == motionevent.action_up) {
  int eventx = (int) event.getrawx();
  int eventy = (int) event.getrawy();
  log.e("eventxy", "eventx = " + eventx + "; eventy = " + eventy); 
  rect rect = new rect();
  getglobalvisiblerect(rect);
  rect.left = rect.right - 50;
  if (rect.contains(eventx, eventy))
  settext("");
 }
 return super.ontouchevent(event);
}

public void setstatus(int status) {
 this.status = status;


 if (status == status_error) {
  try {
   left = getresources().getdrawable(errordrawableid);
  } catch (notfoundexception e) {
   e.printstacktrace();
  }
  setcolor(color.parsecolor("#f57272"));
 } else if (status == status_focused) {
  try {
   left = getresources().getdrawable(focuseddrawableid);
  } catch (notfoundexception e) {
   e.printstacktrace();
  }
  setcolor(color.parsecolor("#5e99f3"));
 } else {
  try {
   left = getresources().getdrawable(unfocuseddrawableid);
  } catch (notfoundexception e) {
   e.printstacktrace();
  }
  setcolor(color.parsecolor("#bfbfbf"));
 }
 if (left != null) {
// left.setbounds(0, 0, 30, 40);

// this.setcompounddrawables(left, null, null, null);

  setcompounddrawableswithintrinsicbounds(left,null,del_btn,null);
 }
 postinvalidate();
}

public void setleftdrawable(int focuseddrawableid, int unfocuseddrawableid,
  int errordrawableid) {
 this.focuseddrawableid = focuseddrawableid;
 this.unfocuseddrawableid = unfocuseddrawableid;
 this.errordrawableid = errordrawableid;
 setstatus(status);
}

@override
protected void onfocuschanged(boolean focused, int direction,
  rect previouslyfocusedrect) {
 super.onfocuschanged(focused, direction, previouslyfocusedrect);
 if (focused) {
  setstatus(status_focused);
 } else {
  setstatus(status_unfocused);
 }
}

@override
protected void finalize() throws throwable {
 super.finalize();
};

public void setcolor(int color) {
 this.color = color;
 this.settextcolor(color);
 invalidate();
}
}

效果图:


代码解释:

变量名 status_focused,status_unfocused,status_error 标示了三种状态,选中状况为蓝色,未选中状态为灰色,错误状态为红色。 focuseddrawableid unfocuseddrawableid errordrawableid 存放三种状态的图片,放置于最左侧。

canvas.drawline(0, this.getheight() - 1, this.getwidth(),this.getheight() - 1, mpaint); //画edittext 最下方的线 setcompounddrawableswithintrinsicbounds(left, null, del_btn, null); //放置左边的和右边的图片(左,上,右,下) 相当于 android:drawableleft="" android:drawableright=""

1、ontouchevent 当手机点击时,第一个先执行的函数,当点击右侧删除图标是清空 edittext
2、setstatus 根据不同的状态,左边的图片不一样

存在的问题: 这版本虽然基本功能已经实现,但是不符合需求,设计中要求文本框中无文字时,右侧删除按钮不显示,不点击删除按钮,删除按钮要保持灰色,点击时才可以变蓝色。

因此有了第二个版本

public class lineedittext extends edittext implements textwatcher, <br /> onfocuschangelistener{

private paint mpaint;
private int color;
public static final int status_focused = 1;
public static final int status_unfocused = 2;
public static final int status_error = 3;
private int status = 2;
private drawable del_btn;
private drawable del_btn_down;
private int focuseddrawableid = r.drawable.user_select;// 默认的
private int unfocuseddrawableid = r.drawable.user;
private int errordrawableid = r.drawable.user_error;
drawable left = null;
private context mcontext;
/** 
 * 是否获取焦点,默认没有焦点 
 */ 
private boolean hasfocus = false; 
/** 
 * 手指抬起时的x坐标 
 */ 
private int xup = 0; 

public lineedittext(context context) {
 super(context);
 mcontext = context;
 init();
}

public lineedittext(context context, attributeset attrs) {
 super(context, attrs);
 mcontext = context;
 init();

}

public lineedittext(context context, attributeset attrs, int defstryle) {
 super(context, attrs, defstryle);
 mcontext = context;
 typedarray a = context.obtainstyledattributes(attrs,
   r.styleable.lineedittext, defstryle, 0);
 focuseddrawableid = a.getresourceid(
   r.styleable.lineedittext_drawablefocus, r.drawable.user_select);
 unfocuseddrawableid = a.getresourceid(
   r.styleable.lineedittext_drawableunfocus, r.drawable.user);
 errordrawableid = a.getresourceid(
   r.styleable.lineedittext_drawableerror, r.drawable.user_error);
 a.recycle();
 init();
}

/**
 * 2014/7/31
 * 
 * @author aimee.zhang
 */
private void init() {
 mpaint = new paint();
 // mpaint.setstyle(paint.style.fill);
 mpaint.setstrokewidth(3.0f);
 color = color.parsecolor("#bfbfbf");
 setstatus(status);
 del_btn = mcontext.getresources().getdrawable(r.drawable.del_but_bg);
 del_btn_down = mcontext.getresources().getdrawable(r.drawable.del_but_bg_down);
 addlisteners();
 setcompounddrawableswithintrinsicbounds(left, null, null, null);
}

@override
protected void ondraw(canvas canvas) {
 super.ondraw(canvas);
 mpaint.setcolor(color);
 canvas.drawline(0, this.getheight() - 1, this.getwidth(),
   this.getheight() - 1, mpaint);
}

// 删除图片
// private void setdrawable() { // if (length() < 1) { // setcompounddrawableswithintrinsicbounds(left, null, null, null); // } else { // setcompounddrawableswithintrinsicbounds(left, null, del_btn,null); // } // }

// 处理删除事件
@override
public boolean ontouchevent(motionevent event) {
 if (del_btn != null && event.getaction() == motionevent.action_up) {
  // 获取点击时手指抬起的x坐标 
  xup = (int) event.getx(); 
  log.e("xup", xup+""); 
  /*rect rect = new rect();
  getglobalvisiblerect(rect);
  rect.left = rect.right - 50;*/
   // 当点击的坐标到当前输入框右侧的距离小于等于 getcompoundpaddingright() 的距离时,则认为是点击了删除图标 
  if ((getwidth() - xup) <= getcompoundpaddingright()) { 
   if (!textutils.isempty(gettext().tostring())) {
    settext(""); 
   } 
  }
 }else if(del_btn != null && event.getaction() == motionevent.action_down && gettext().length()!=0){
  setcompounddrawableswithintrinsicbounds(left,null,del_btn_down,null);
 }else if(gettext().length()!=0){
  setcompounddrawableswithintrinsicbounds(left,null,del_btn,null);
 }
 return super.ontouchevent(event);
}

public void setstatus(int status) {
 this.status = status;


 if (status == status_error) {
  try {
   left = getresources().getdrawable(errordrawableid);
  } catch (notfoundexception e) {
   e.printstacktrace();
  }
  setcolor(color.parsecolor("#f57272"));
 } else if (status == status_focused) {
  try {
   left = getresources().getdrawable(focuseddrawableid);
  } catch (notfoundexception e) {
   e.printstacktrace();
  }
  setcolor(color.parsecolor("#5e99f3"));
 } else {
  try {
   left = getresources().getdrawable(unfocuseddrawableid);
  } catch (notfoundexception e) {
   e.printstacktrace();
  }
  setcolor(color.parsecolor("#bfbfbf"));
 }
 if (left != null) {
// left.setbounds(0, 0, 30, 40); // this.setcompounddrawables(left, null, null, null); setcompounddrawableswithintrinsicbounds(left,null,null,null); } postinvalidate(); }

public void setleftdrawable(int focuseddrawableid, int unfocuseddrawableid,
  int errordrawableid) {
 this.focuseddrawableid = focuseddrawableid;
 this.unfocuseddrawableid = unfocuseddrawableid;
 this.errordrawableid = errordrawableid;
 setstatus(status);
}
 private void addlisteners() { 
  try { 
   setonfocuschangelistener(this); 
   addtextchangedlistener(this); 
  } catch (exception e) { 
   e.printstacktrace(); 
  } 
 } 
@override
protected void onfocuschanged(boolean focused, int direction,
  rect previouslyfocusedrect) {
 super.onfocuschanged(focused, direction, previouslyfocusedrect);
 this.hasfocus=focused;
 if (focused) {
  setstatus(status_focused);
 } else {
  setstatus(status_unfocused);
  setcompounddrawableswithintrinsicbounds(left,null,null,null);
 }
}

@override
protected void finalize() throws throwable {
 super.finalize();
};

public void setcolor(int color) {
 this.color = color;
 this.settextcolor(color);
 invalidate();
}



@override
public void aftertextchanged(editable arg0) {
 // todo auto-generated method stub
 postinvalidate();
}

@override
public void beforetextchanged(charsequence arg0, int arg1, int arg2,
  int arg3) {
 // todo auto-generated method stub
  if (textutils.isempty(arg0)) { 
   // 如果为空,则不显示删除图标 
   setcompounddrawableswithintrinsicbounds(left, null, null, null); 
  } else { 
   // 如果非空,则要显示删除图标 
   setcompounddrawableswithintrinsicbounds(left, null, del_btn, null); 
  } 
}
@override
 public void ontextchanged(charsequence s, int start, int before, int after) { 
 if (hasfocus) { 
  if (textutils.isempty(s)) { 
   // 如果为空,则不显示删除图标 
   setcompounddrawableswithintrinsicbounds(left, null, null, null); 
  } else { 
   // 如果非空,则要显示删除图标 
   setcompounddrawableswithintrinsicbounds(left, null, del_btn, null); 
  } 
 } 
}

@override
public void onfocuschange(view arg0, boolean arg1) {
 // todo auto-generated method stub
 try { 
  this.hasfocus = arg1; 
 } catch (exception e) { 
  e.printstacktrace(); 
 } 
} 
}

比较关键的方法是:ontouchevent

当进入界面,点击输入框,要判断输入框中是否已有文字,如果有则显示灰色的删除按钮,如果没有则不显示,如果点击了删除按钮,删除按钮变蓝色

存在的问题: 这个版本依旧存在问题,就是输入长度超过输入框,所画的线不会延伸,如图


解决方法:

@override

protected void ondraw(canvas canvas) {
 super.ondraw(canvas);
 mpaint.setcolor(color);
 int x=this.getscrollx();
 int w=this.getmeasuredwidth();
 canvas.drawline(0, this.getheight() - 1, w+x,
   this.getheight() - 1, mpaint);
}

w:获取控件长度

x:延伸后的长度

最终效果:

以上就是android实现自定义的edittext下划线的方法,希望对大家的学习有所帮助。

如对本文有疑问,请在下面进行留言讨论,广大热心网友会与你互动!! 点击进行留言回复

相关文章:

验证码:
移动技术网