Tuesday, May 6, 2014

Not editable prefix in EditText

Today I have decided to start sharing my "simple and brilliant" ideas with the world. I don't know if I will continue to do such things in the future but, at least, it worth to try.

So what to start with...

Probably with the latest task I have tried to solve on Android. The task was simple enough - show not editable phone prefix in EditText. Something like this:



Most of the time I try to optimize my code so it implies some limitations:

  1. it must work fast. Actually, it will be a bigger challange for me to make such a simple control work slowly :)
  2. minimize view hierarchy - no need to use "Linear -> Text -> Edit" here
  3. code must look good without any dirty hacks
  4. generalization is good most of the times but no need to be a fanatic
So lets start. Idea is to extend EditText and to override four methods:
  1. onMeasure - to calculate prefix size
  2. onLayout - to position prefix correctly
  3. onDraw - to actually draw prefix
  4. getCompoundPaddingLeft - to offset EditText's content
Here is full class code:

public class PhoneNumberEdit extends EditText {

  private String mPrefix = "+3"; // can be hardcoded for demo purposes
  private Rect mPrefixRect = new Rect(); // actual prefix size

  public PhoneNumberEdit(Context context, AttributeSet attrs) {
    super(context, attrs);
  }

  @Override
  protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
    getPaint().getTextBounds(mPrefix, 0, mPrefix.length(), mPrefixRect);
    mPrefixRect.right += getPaint().measureText(" "); // add some offset

    super.onMeasure(widthMeasureSpec, heightMeasureSpec);
  }

  @Override
  protected void onDraw(Canvas canvas) {
    super.onDraw(canvas);
    canvas.drawText(mPrefix, super.getCompoundPaddingLeft(), getBaseline(), getPaint());
  }

  @Override
  public int getCompoundPaddingLeft() {
    return super.getCompoundPaddingLeft() + mPrefixRect.width();
  }
}

7 comments:

  1. Thanks a lot, sir. You're like a savior to Android noobs like me.

    ReplyDelete
  2. can u please make it to support rtl.

    ReplyDelete
  3. Thanks a lot mate. Solved my issue. Is there a way of making the prefix part of the string in the EditText? Like when I set prefix as +254 and enter 720123456 in the text field, I want to get +254720123456 when I call phoneEditText.getText() in the java code

    ReplyDelete
    Replies
    1. You can't override getText() method for this but you can always add new one:

      public String getTextWithPrefix() {
      return mPrefix + getText();
      }

      Delete
  4. please help me in making it to support rtl.

    ReplyDelete