How does Android customize the EditText underline?

Source: Internet
Author: User
Tags apm

Project requirements: I have worked on a project where the interaction of the login interface is impressive. The interaction designer gives a very designed design that requires a color-changeable underline, a variable icon on the left and an input box with a variable delete flag on the right,

Record making process:

    • First version

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 ();}    @Overrideprotected void OnDraw (canvas canvas) {super.ondraw (canvas);    Mpaint.setcolor (color); Canvas.drawline (0, This.getheight ()-1, This.getwidth (), This.getheight ()-1, mpaint);} Delete picture private void setdrawabLe () {if (length () < 1) {setcompounddrawableswithintrinsicbounds (left, NULL, DEL_BTN, NULL);    } else {setcompounddrawableswithintrinsicbounds (left, NULL, del_btn_down,null); }}//Handling Delete Event @overridepublic Boolean ontouchevent (Motionevent event) {if (Del_btn_down! = null && event.getactio        N () = = 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);}@Overrideprotected void onFocusChanged(boolean focused, int direction,        Rect previouslyFocusedRect) {    super.onFocusChanged(focused, direction, previouslyFocusedRect);    if (focused) {        setStatus(STATUS_FOCUSED);    } else {        setStatus(STATUS_UNFOCUSED);    }}@Overrideprotected void finalize() throws Throwable {    super.finalize();};public void setColor(int color) {    this.color = color;    this.setTextColor(color);    invalidate();}

}

Code Explanation:

The variable name STATUS_FOCUSED,STATUS_UNFOCUSED,STATUS_ERROR indicates three states, the selected state is blue, the unchecked status is gray, and the error status is red. focusedDrawableId unfocusedDrawableId errorDrawableIda picture of three states, placed on the leftmost side.

canvas.drawLine(0, this.getHeight() - 1, this.getWidth(),this.getHeight() - 1, mPaint); //画editTextThe bottom line setCompoundDrawablesWithIntrinsicBounds(left, null, del_btn, null); //place the left and right picture (left, top, right, bottom) equal toandroid:drawableLeft="" android:drawableRight=""

    • Ontouchevent when the phone is clicked, the first function to execute first, when clicked on the right to delete the icon is emptied EditText
    • SetStatus depending on the state, the picture on the left is different

Existing problems: This version Although the basic functionality has been implemented, but does not meet the requirements, the design requires text box without text, the right delete button is not displayed, do not click the Delete button, delete the button to remain gray, click on the blue can be changed.

So there's a second version of this.

public class Lineedittext extends EditText implements Textwatcher,
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_dow n;private int focuseddrawableid = r.drawable.user_select;//default private int unfocuseddrawableid = R.drawable.user;   private int Errordrawableid = R.drawable.user_error;drawable left = null;private Context mcontext;/** * Whether to get focus, default no focus */  Private Boolean hasfocus = false;  /** * x coordinate when the finger is lifted */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);}    @Overrideprotected void OnDraw (canvas canvas) {super.ondraw (canvas);    Mpaint.setcolor (color); Canvas.drawline (0, This.getheight ()-1, THIS.GEtwidth (), This.getheight ()-1, mpaint);} Delete a picture

//private void setdrawable () {//if (length () < 1) {//Setcompounddrawableswithintrinsicbounds (left , NULL, NULL, NULL); } else {//setcompounddrawableswithintrinsicbounds (left, NULL, del_btn,null);//}//}

Handle Delete Event @overridepublic Boolean ontouchevent (Motionevent event) {if (del_btn! = null && event.getaction () = =          MOTIONEVENT.ACTION_UP) {//Gets the x-coordinate of the finger lifted when clicked XUp = (int) event.getx ();          LOG.E ("XUp", xup+ "");        /*rect rect = new rect ();        Getglobalvisiblerect (rect); Rect.left = rect.right-50;*///When the distance of the clicked coordinates to the right of the current input box is less than or equal to Getcompoundpaddingright (), it is considered that the delete icon is clicked if ( GetWidth ()-xUp) <= getcompoundpaddingright ()) {if (!              Textutils.isempty (GetText (). toString ())) {SetText (""); }}}else if (del_btn! = null && event.getaction () = = Motionevent.action_down && getText (). Leng    Th ()!=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, +, +);//This.setcompounddrawables (left, NULL, NULL, NULL); setcompounddrawabl Eswithintrinsicbounds (Left,null,null,null); } postinvalidate (); }

public void setleftdrawable (int focuseddrawableid, int unfocuseddrawableid, int errordrawableid) {This.focusedd    Rawableid = Focuseddrawableid;    This.unfocuseddrawableid = Unfocuseddrawableid;    This.errordrawableid = Errordrawableid; SetStatus (status);}              private void Addlisteners () {try {setonfocuschangelistener (this);          Addtextchangedlistener (this);          } catch (Exception e) {e.printstacktrace (); }} @Overrideprotected void Onfocuschanged (Boolean focused, int direction, Rect previouslyfocusedrect) {s    Uper.onfocuschanged (focused, direction, previouslyfocusedrect);    this.hasfocus=focused;    if (focused) {setStatus (status_focused);        } else {setStatus (status_unfocused);    Setcompounddrawableswithintrinsicbounds (Left,null,null,null); }} @Overrideprotected void Finalize () throws Throwable {super.finalize ();};   public void SetColor (int color) {this.color = color; This.settextcolor (color); Invalidate ();} @Overridepublic void aftertextchanged (Editable arg0) {//TODO auto-generated Method Stub postinvalidate ();}  @Overridepublic void beforetextchanged (charsequence arg0, int arg1, int arg2, int arg3) {//TODO auto-generated Method stub if (Textutils.isempty (arg0)) {//If blank, the delete icon is not displayed Setcompounddrawableswithintrinsicboun       DS (left, NULL, NULL, NULL);       } else {//If non-empty, you want to display the delete icon Setcompounddrawableswithintrinsicbounds (left, NULL, DEL_BTN, NULL);  }} @Override public void ontextchanged (charsequence s, int start, int before, int. after) {if (Hasfocus) {if (Textutils.isempty (s)) {//If blank, the delete icon setcompounddrawableswithintrinsicbounds (left, NULL, nul         L, NULL);         } else {//If non-empty, you want to display the delete icon Setcompounddrawableswithintrinsicbounds (left, NULL, DEL_BTN, NULL);   }     }

}

@Overridepublic void onFocusChange(View arg0, boolean arg1) {    // TODO Auto-generated method stub    try {          this.hasFocus = arg1;      } catch (Exception e) {          e.printStackTrace();      }  }  

}

The more critical approach is: Ontouchevent

When entering the interface, click on the input box, to determine if there is text in the input box, if there is a gray delete button, if not, if not, if you click the Delete button, delete the button to turn blue

Problem: This version still has a problem, that is, the input length is more than the input box, the line will not extend,

Workaround:

@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: Gets the length of the control

X: Length after extension

Final effect:

After sharing the code design of this interface, I will talk to you about some new gadgets. If you are in the Royal Park, if you do not take advantage of the rich resources of the Royal Park, and how worthy of the daily inhalation of dozens of catty haze?

The sharing of words and chatter

In the Royal Park life, I wake up every morning will tell myself, is a new day, to be serious.

It's easy to write an app, and it's hard to write a good app. How to test the performance status of the APP you wrote, user experience?

What is APM?

In the fields of information technology and Systems management, application performance management (APM) are the monitoring and management of performance and availability of software applications. APM strives to detect and diagnose complex application performance problems to maintain a expected level of service. APM is "the translation of IT metrics to business meaning.

At home and abroad have a lot of mature APM manufacturers, the author has also touched several, such as APPDYNAMICS,NEWRELIC,ONEAPM

There are products that focus on APP crash monitoring: crashlytics,crittercism,bugly, etc.

What I want to share with you today is a new continent that is found in ONEAPM Mobile Insight products--the stalling monitoring

The concept of fluency, I believe that everyone is not unfamiliar, that is, within 1s of the number of graphics refresh signal interruption. The more fluent the closer the 40 o'clock, the user can perceive the lag, smoothness in 20 or less is more serious. OneAPM Mobile Insight's lag monitoring is a module that monitors the smoothness metrics.

    • Stutter Trend Chart: The trend of feedback on the number of times that occurs over time
    • Equipment Distribution: The type of equipment that is centrally distributed in the stalling phenomenon
    • Stuttering page: What happens to the page where the stutter occurs, and how much is the average fluency, and how much inferior information is stuck.

View the status of a single page and analyze the cause of preempted from the page line

If you also want to test the user experience of your APP, try this new gadget ~ ~

OneAPM Mobile Insight provides a real user experience as a metric for Crash analysis, monitoring network requests and network errors, and improving user retention. Visit the official website of OneAPM for more application performance optimization experiences and to read more technical articles, visit the OneAPM Official technology blog.

How does Android customize the EditText underline?

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.