Clearable Material EditText In Android

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 Empty Activity.
  • Step 2 - Setting up the Library.
  • Step 3 - Implementation of Custom Control in Android.
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.   
  3.     private Drawable drawableTemp;  
  4.     private Drawable drawableRight;  
  5.   
  6.     int actionX, actionY;  
  7.   
  8.     private DrawableClickListener clickListener;  
  9.   
  10.     public ClearableEditText(Context context) {  
  11.         super(context);  
  12.     }  
  13.   
  14.     public ClearableEditText(Context context, AttributeSet attrs) {  
  15.         super(context, attrs);  
  16.     }  
  17.   
  18.     public ClearableEditText(Context context, AttributeSet attrs, int defStyleAttr) {  
  19.         super(context, attrs, defStyleAttr);  
  20.     }  
  21.   
  22.     protected void onDraw(Canvas canvas) {  
  23.         super.onDraw(canvas);  
  24.   
  25.     }  
  26.   
  27.     @Override  
  28.     protected void onSizeChanged(int w, int h, int oldw, int oldh) {  
  29.         super.onSizeChanged(w, h, oldw, oldh);  
  30.     }  
  31.   
  32.     @Override  
  33.     public void setCompoundDrawables(Drawable left, Drawable top,  
  34.                                      Drawable right, Drawable bottom) {  
  35.         if (right != null) {  
  36.             drawableRight = right;  
  37.         }  
  38.         super.setCompoundDrawables(left, top, right, bottom);  
  39.     }  
  40.   
  41.     @Override  
  42.     protected void onTextChanged(CharSequence text, int start, int lengthBefore, int lengthAfter) {  
  43.         if (text.toString().length() > 0) {  
  44.             drawableRight = drawableTemp;  
  45.             setCompoundDrawables(nullnull, drawableRight, null);  
  46.         } else {  
  47.             drawableTemp = drawableRight;  
  48.             setCompoundDrawables(nullnullnullnull);  
  49.         }  
  50.         super.onTextChanged(text, start, lengthBefore, lengthAfter);  
  51.     }  
  52.   
  53.     @SuppressLint("ClickableViewAccessibility")  
  54.     @Override  
  55.     public boolean onTouchEvent(MotionEvent event) {  
  56.         Rect bounds;  
  57.         if (event.getAction() == MotionEvent.ACTION_DOWN) {  
  58.             actionX = (int) event.getX();  
  59.             actionY = (int) event.getY();  
  60.             if (drawableRight != null) {  
  61.   
  62.                 bounds = drawableRight.getBounds();  
  63.                 int x, y;  
  64.                 int extraTapArea = 13;  
  65.   
  66.                 /* 
  67.                   IF USER CLICKS JUST OUT SIDE THE RECTANGLE OF THE DRAWABLE 
  68.                   THAN ADD X AND SUBTRACT THE Y WITH SOME VALUE SO THAT AFTER 
  69.                   CALCULATING X AND Y CO-ORDINATE LIES INTO THE DRAWBABLE 
  70.                   BOUND. - this process help to increase the tappable area of 
  71.                   the rectangle. 
  72.                  */  
  73.                 x = actionX + extraTapArea;  
  74.                 y = actionY - extraTapArea;  
  75.   
  76.                 /* 
  77.                  Since this is right drawable subtract the value of x from the width 
  78.                  of view. so that width - tapped_area will result in x co-ordinate in drawable bound. 
  79.                 */  
  80.                 x = getWidth() - x;  
  81.   
  82.                  /*x can be negative if user taps at x co-ordinate just near the width. 
  83.                   e.g views width = 300 and user taps 290. Then as per previous calculation 
  84.                   290 + 13 = 303. So subtract X from getWidth() will result in negative value. 
  85.                   So to avoid this add the value previously added when x goes negative. 
  86.                  */  
  87.   
  88.                 if (x <= 0) {  
  89.                     x += extraTapArea;  
  90.                 }  
  91.   
  92.                  /* 
  93.                  If result after calculating for extra tap-able area is negative. 
  94.                  assign the original value so that after subtracting 
  95.                  extra tapping area value doesn't go into negative value. 
  96.                  */  
  97.   
  98.                 if (y <= 0)  
  99.                     y = actionY;  
  100.   
  101.                 /* 
  102.                 If drawable bounds contains the x and y points then move ahead. 
  103.                 */  
  104.                 if (bounds.contains(x, y) && clickListener != null) {  
  105.                     clickListener.onClick();  
  106.                     event.setAction(MotionEvent.ACTION_CANCEL);  
  107.                     return false;  
  108.                 }  
  109.                 return super.onTouchEvent(event);  
  110.             }  
  111.   
  112.         }  
  113.         return super.onTouchEvent(event);  
  114.     }  
  115.   
  116.     @Override  
  117.     protected void finalize() throws Throwable {  
  118.         drawableRight = null;  
  119.         super.finalize();  
  120.     }  
  121.   
  122.     public void setDrawableClickListener(DrawableClickListener listener) {  
  123.         this.clickListener = listener;  
  124.     }  
  125.   
  126.     public interface DrawableClickListener {  
  127.         void onClick();  
  128.     }  
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.   
  10.     <android.support.design.widget.TextInputLayout  
  11.         android:id="@+id/text_input_layout"  
  12.         android:layout_width="match_parent"  
  13.         android:layout_height="wrap_content"  
  14.         app:errorEnabled="true"  
  15.         app:layout_constraintBottom_toBottomOf="parent"  
  16.         app:layout_constraintLeft_toLeftOf="parent"  
  17.         app:layout_constraintRight_toRightOf="parent"  
  18.         app:layout_constraintTop_toTopOf="parent">  
  19.   
  20.         <com.androidmads.materialedittext.ClearableEditText  
  21.             android:id="@+id/edit_text"  
  22.             android:layout_width="match_parent"  
  23.             android:layout_height="wrap_content"  
  24.             android:drawableEnd="@drawable/ic_close"  
  25.             android:drawableRight="@drawable/ic_close"  
  26.             android:hint="Enter your name" />  
  27.   
  28.     </android.support.design.widget.TextInputLayout>  
  29.   
  30.     <Button  
  31.         android:id="@+id/button"  
  32.         android:layout_width="match_parent"  
  33.         android:layout_height="wrap_content"  
  34.         android:layout_marginTop="68dp"  
  35.         android:text="Click Here..."  
  36.         app:layout_constraintEnd_toEndOf="parent"  
  37.         app:layout_constraintStart_toStartOf="parent"  
  38.         app:layout_constraintTop_toTopOf="@+id/text_input_layout" />  
  39.   
  40. </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.