Material EditText in Android

Introduction

In this article, we will learn how to create and use Clearable EditText without using any third-party library. It is very easy to implement and useful control for our application development.
Steps
I have split this part into 3 steps as in the following.
Step 1 - Creating a New Project with Android Studio
  1. Open Android Studio and select Create a new project.
  2. Name the project as per your wish and select your activity template.
    Activity Template
  3. Click theFinish button to create a new project in Android Studio.
Step 2 - Setting up the Firebase Library
In this part, we will see how to set up the library for the project.
  1. Open your app level build.gradle file and add the following lines in dependencies to apply the required libraries to your project.
    1. dependencies {
    2. ...
    3. implementation 'com.android.support:appcompat-v7:26.1.0'
    4. implementation 'com.android.support.constraint:constraint-layout:1.1.2'
    5. implementation 'com.android.support:support-annotations:27.1.1'
    6. implementation 'com.android.support:design:26.1.0'
    7. }
  1. Then click Sync Now to setup your project.
Step 3 - Implementation of Clearable EditText
Create a class named as ClearableEditText extend with android.support.v7.widget.AppCompatEditText as Parent. Then open the class file and add the following lines of code.
  1. public class ClearableEditText extends android.support.v7.widget.AppCompatEditText {
  2. private Drawable drawableTemp;
  3. private Drawable drawableRight;
  4. int actionX, actionY;
  5. private DrawableClickListener clickListener;
  6. public ClearableEditText(Context context) {
  7. super(context);
  8. }
  9. public ClearableEditText(Context context, AttributeSet attrs) {
  10. super(context, attrs);
  11. }
  12. public ClearableEditText(Context context, AttributeSet attrs, int defStyleAttr) {
  13. super(context, attrs, defStyleAttr);
  14. }
  15. protected void onDraw(Canvas canvas) {
  16. super.onDraw(canvas);
  17. }
  18. @Override
  19. protected void onSizeChanged(int w, int h, int oldw, int oldh) {
  20. super.onSizeChanged(w, h, oldw, oldh);
  21. }
  22. @Override
  23. public void setCompoundDrawables(Drawable left, Drawable top,
  24. Drawable right, Drawable bottom) {
  25. if (right != null) {
  26. drawableRight = right;
  27. }
  28. super.setCompoundDrawables(left, top, right, bottom);
  29. }
  30. @Override
  31. protected void onTextChanged(CharSequence text, int start, int lengthBefore, int lengthAfter) {
  32. if (text.toString().length() > 0) {
  33. drawableRight = drawableTemp;
  34. setCompoundDrawables(null, null, drawableRight, null);
  35. } else {
  36. drawableTemp = drawableRight;
  37. setCompoundDrawables(null, null, null, null);
  38. }
  39. super.onTextChanged(text, start, lengthBefore, lengthAfter);
  40. }
  41. @SuppressLint("ClickableViewAccessibility")
  42. @Override
  43. public boolean onTouchEvent(MotionEvent event) {
  44. Rect bounds;
  45. if (event.getAction() == MotionEvent.ACTION_DOWN) {
  46. actionX = (int) event.getX();
  47. actionY = (int) event.getY();
  48. if (drawableRight != null) {
  49. bounds = drawableRight.getBounds();
  50. int x, y;
  51. int extraTapArea = 13;
  52. /*
  53. IF USER CLICKS JUST OUT SIDE THE RECTANGLE OF THE DRAWABLE
  54. THAN ADD X AND SUBTRACT THE Y WITH SOME VALUE SO THAT AFTER
  55. CALCULATING X AND Y CO-ORDINATE LIES INTO THE DRAWBABLE
  56. BOUND. - this process help to increase the tappable area of
  57. the rectangle.
  58. */
  59. x = actionX + extraTapArea;
  60. y = actionY - extraTapArea;
  61. /*
  62. Since this is right drawable subtract the value of x from the width
  63. of view. so that width - tapped_area will result in x co-ordinate in drawable bound.
  64. */
  65. x = getWidth() - x;
  66. /*x can be negative if user taps at x co-ordinate just near the width.
  67. e.g views width = 300 and user taps 290. Then as per previous calculation
  68. 290 + 13 = 303. So subtract X from getWidth() will result in negative value.
  69. So to avoid this add the value previously added when x goes negative.
  70. */
  71. if (x <= 0) {
  72. x += extraTapArea;
  73. }
  74. /*
  75. If result after calculating for extra tap-able area is negative.
  76. assign the original value so that after subtracting
  77. extra tapping area value doesn't go into negative value.
  78. */
  79. if (y <= 0)
  80. y = actionY;
  81. /*
  82. If drawable bounds contains the x and y points then move ahead.
  83. */
  84. if (bounds.contains(x, y) && clickListener != null) {
  85. clickListener.onClick();
  86. event.setAction(MotionEvent.ACTION_CANCEL);
  87. return false;
  88. }
  89. return super.onTouchEvent(event);
  90. }
  91. }
  92. return super.onTouchEvent(event);
  93. }
  94. @Override
  95. protected void finalize() throws Throwable {
  96. drawableRight = null;
  97. super.finalize();
  98. }
  99. public void setDrawableClickListener(DrawableClickListener listener) {
  100. this.clickListener = listener;
  101. }
  102. public interface DrawableClickListener {
  103. void onClick();
  104. }
Here, I have created DrawableClickListener interface.
Open your activity_main.xml file and add the following lines.
  1. <?xml version="1.0" encoding="utf-8"?>
  2. <android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
  3. xmlns:app="http://schemas.android.com/apk/res-auto"
  4. xmlns:tools="http://schemas.android.com/tools"
  5. android:layout_width="match_parent"
  6. android:layout_height="match_parent"
  7. android:layout_margin="10dp"
  8. tools:context="com.androidmads.materialedittext.MainActivity">
  9. <android.support.design.widget.TextInputLayout
  10. android:id="@+id/text_input_layout"
  11. android:layout_width="match_parent"
  12. android:layout_height="wrap_content"
  13. app:errorEnabled="true"
  14. app:layout_constraintBottom_toBottomOf="parent"
  15. app:layout_constraintLeft_toLeftOf="parent"
  16. app:layout_constraintRight_toRightOf="parent"
  17. app:layout_constraintTop_toTopOf="parent">
  18. <com.androidmads.materialedittext.ClearableEditText
  19. android:id="@+id/edit_text"
  20. android:layout_width="match_parent"
  21. android:layout_height="wrap_content"
  22. android:drawableEnd="@drawable/ic_close"
  23. android:drawableRight="@drawable/ic_close"
  24. android:hint="Enter your name" />
  25. </android.support.design.widget.TextInputLayout>
  26. <Button
  27. android:id="@+id/button"
  28. android:layout_width="match_parent"
  29. android:layout_height="wrap_content"
  30. android:layout_marginTop="68dp"
  31. android:text="Click Here..."
  32. app:layout_constraintEnd_toEndOf="parent"
  33. app:layout_constraintStart_toStartOf="parent"
  34. app:layout_constraintTop_toTopOf="@+id/text_input_layout" />
  35. </android.support.constraint.ConstraintLayout>
The Layout Preview looks like the below screenshot,
Layout Preview
This control will show the cancel icon when the control has typed text and iconwill hide when the control has no text.
Then open your MainActivity.java file and initialize your control like the following.
  1. final TextInputLayout textInputLayout = findViewById(R.id.text_input_layout);
  2. final ClearableEditText editText = findViewById(R.id.edit_text);
  3. final Button button = findViewById(R.id.button);
The cancel icon will appear when the user types the data. Add the following Drawable click listener as in the following.
  1. editText.setDrawableClickListener(new ClearableEditText.DrawableClickListener() {
  2. @Override
  3. public void onClick() {
  4. editText.setText(null);
  5. }
  6. });
Download Code
You can download the full source code of the article in GitHub. If you like this article, do star the repo in GitHub.