Android Custom EditText: Hand-in-hand instructions for making a Super EditText with a one-click deletion & Custom Style

Keywords: Android github xml Attribute


Preface

  • EditText is very common in Android development
  • This article will teach you how to make a SuperEditText control with one-click deletion function, which is rich in custom style. I hope you will like it.

Design sketch

Open source in Github: Super_EditText Welcome to Star!

Catalog


Sketch Map

1. introduction

A SuperEditText control with one-click deletion function

Open source in Github: Super_EditText Welcome to Star!


Design sketch

2. Functional introduction

2.1 Requirement scenario

For EditText, the general requirements are:

  • Facilitate users to enter twice due to input errors
  • Identify the user filling in the item
  • Adding UI elements to specific scenarios

2.2 Functional Requirements

According to the requirement scenario, the functions of EditText are as follows:

  • One key deletion
  • Rich custom style: left icon, delete function icon, split line & cursor style change. Specifically as follows:

Sketch Map

Note: The settings of this style are not available in the API that comes with the system.

  • Function list

Sketch Map

2.3 Functional Indications


Design sketch

3. characteristics

Contrast the EditText control on the market, the control Super_EditText It is characterized by:

3.1 Function Practical

  • One-click deletion function is very common in demand, and now it is more convenient to use after encapsulation.
  • Highly customizable styles (more powerful and convenient than their own), less complex but able to meet general EditText usage requirements

Customizable styles are as follows: (Note: The style settings are not available in the API that comes with the system)


Sketch Map

3.2 Easy to use

3.3 Low cost of secondary development

  • This project has been open source on Github: Super_EditText
  • Have detailed source code analysis documentation (that is, this article)

So the cost of customization is very low.

4. Detailed design of functions

Detailed functional logic is given below.

4.1 One key clears the input field

  • Description: Clear the fields entered by the current user
  • Requirement scenario: Convenient for users to enter twice due to input errors
  • Prototype map

Sketch Map
  • Source code analysis
   /*
    * Step 1: Define attributes
    * */

    private int  ic_deleteResID; // Delete icon resource ID
    private Drawable  ic_delete; // delete icon
    private int delete_x,delete_y,delete_width,delete_height; // Delete icon starting point (x,y), delete icon width and height (px)

    /*
    * Step 2: Initialize properties
    * */
   private void init(Context context, AttributeSet attrs) {

        // Get control resources
        TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.SuperEditText);
       /**
         * Initialize Delete Icon
         */
         // 1. Get the resource ID
         ic_deleteResID = typedArray.getResourceId(R.styleable.SuperEditText_ic_delete,R.drawable.delete);
         // 2. Obtain icon resources according to resource ID (converted into Drawable objects)
         ic_delete =  getResources().getDrawable(ic_deleteResID);
         // 3. Setting icon size
         // Starting point (x, y), width = left_width, height = left_height
         delete_x = typedArray.getInteger(R.styleable.SuperEditText_delete_x, 0);
         delete_y = typedArray.getInteger(R.styleable.SuperEditText_delete_y, 0);
         delete_width = typedArray.getInteger(R.styleable.SuperEditText_delete_width, 60);
         delete_height = typedArray.getInteger(R.styleable.SuperEditText_delete_height, 60);
         ic_delete.setBounds(delete_x, delete_y, delete_width, delete_height);

   /**
     * Step 3: Determine whether to display the deleted icon by listening for copying EditText itself
     * Monitoring method: onTextChanged () & onFocusChanged ()
     * Call time: when the content of the input box changes - when the focus changes
     */
    @Override
    protected void onTextChanged(CharSequence text, int start, int lengthBefore, int lengthAfter) {
        super.onTextChanged(text, start, lengthBefore, lengthAfter);
        setDeleteIconVisible(hasFocus() && text.length() > 0,hasFocus());
        // hasFocus() returns whether to get the focus of EditTEXT, that is, whether to select
        // setDeleteIconVisible ()= Judging whether to display deletion icon based on whether the input is selected or not - > Concern 1
    }

    @Override
    protected void onFocusChanged(boolean focused, int direction, Rect previouslyFocusedRect) {
        super.onFocusChanged(focused, direction, previouslyFocusedRect);
        setDeleteIconVisible(focused && length() > 0,focused);
        // Focus = whether to get the focus
        // Also, according to setDeleteIconVisible (), judge whether to display deletion icon - > Concern 1
    }

   /**
     * Focus on 1
     * Function: Determine whether deletion icons are displayed or not
     */
    private void setDeleteIconVisible(boolean deleteVisible,boolean leftVisible) {
        setCompoundDrawables(leftVisible ?  ic_left_click :  ic_left_unclick, null,
                deleteVisible ?  ic_delete: null, null);

    // Introduction to setCompound Drawables (Drawable left, Drawable top, Drawable right, Drawable bottom)
        // Function: Set icons on top, bottom, left and right of EditText (equivalent to android: drawableLeft="" android: drawableRight=")
        // Note: The incoming Drawable object must have setBounds(x,y,width,height), i.e. it must have set the initial location, width, and higher information.
        // X: Starting Point y of Component on Container X Axis: Starting Point width of Component on Container Y Axis: Length height of Component: height of Component
        // If you don't want to display it somewhere, set it to null

        // Another similar approach: set Compound Drawables Within Intrinsic Bounds (Drawable left, Drawable top, Drawable right, Drawable bottom)
        // Function: Set icons on top, bottom, left and right of EditText
        // The difference from setCompound Drawables is that the width of the incoming Drawables from setCompound Drawables Within Intrinsic Bounds () is equal to the inherent width (automatically obtained through getIntrinsicWidth () & getIntrinsicHeight ())
        // setBounds(x,y,width,height) need not be set
    }


   /**
     * Step 4: Set the click event for the deleted icon area, that is, "click = empty the search box content"
     * Principle: When the finger is raised in the deleted icon area, it is regarded as clicking the deleted icon = emptying the search box content.
     */
    @Override
    public boolean onTouchEvent(MotionEvent event) {

        // Principle: When the finger is raised in the deleted icon area, it is regarded as clicking the deleted icon = emptying the search box content.
        switch (event.getAction()) {
            // Judgment action = when the finger is raised
            case MotionEvent.ACTION_UP:
                Drawable drawable =  ic_delete;

                if (drawable != null && event.getX() <= (getWidth() - getPaddingRight())
                        && event.getX() >= (getWidth() - getPaddingRight() - drawable.getBounds().width())) {

                    // Description of Judgment Conditions
                    // event.getX(): Positional coordinates when lifted
                    // getWidth(): Width of the control
                    // getPaddingRight(): Delete the distance from the right edge of the icon icon to the right edge of the EditText control
                    // That is, getWidth() - getPaddingRight() = the right edge coordinate of the deleted icon = X1
                        // getWidth() - getPaddingRight() - drawable.getBounds().width() = coordinates of the left edge of the deleted icon = X2
                    // So the area between X1 and X2 = the area where the icon is deleted
                    // When the finger is raised in the deleted icon area (X2=<event.getX()<=X1), it is considered that the deleted icon is clicked to empty the search box.
                    setText("");

                }
                break;
        }
        return super.onTouchEvent(event);
    }


Sketch Map

4.2 Select Style

  • Description: By adding UI elements - interactive style, the user is filling in the project.
  • Requirement scenario: Identify the user filling in the item
  • Style description

Sketch Map
  • Prototype map

Sketch Map
  • Attribute specification

Sketch Map

Sketch Map
  • Source code analysis
   /*
    * Step 1: Define attributes
    * */
    private Paint mPaint; // Paint brush
    private int  ic_left_clickResID,ic_left_unclickResID;    // Icon Resource ID on the left (click & no click)
    private Drawable  ic_left_click,ic_left_unclick; // Icon on the left (click & click)
    private int left_x,left_y,left_width,left_height; // Starting point of left Icon (x,y), width and height of left Icon (px)

    private int cursor; // cursor

    // Segmentation line variable
    private int lineColor_click,lineColor_unclick;// Click - Click No Color
    private int color; 
    private int linePosition; // Splitting line position

   /*
    * Step 2: Initialize properties
    * */
private void init(Context context, AttributeSet attrs) {

        // Get control resources
        TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.SuperEditText);

        /**
         * Initialize the left Icon (click & click)
         */

        // a. Click on the left icon of the status
         // 1. Get the resource ID
         ic_left_clickResID = typedArray.getResourceId(R.styleable.SuperEditText_ic_left_click, R.drawable.ic_left_click);
         // 2. Obtain icon resources according to resource ID (converted into Drawable objects)
         ic_left_click =  getResources().getDrawable(ic_left_clickResID);
         // 3. Setting icon size
         // Starting point (x, y), width = left_width, height = left_height
         left_x = typedArray.getInteger(R.styleable.SuperEditText_left_x, 0);
         left_y = typedArray.getInteger(R.styleable.SuperEditText_left_y, 0);
         left_width = typedArray.getInteger(R.styleable.SuperEditText_left_width, 60);
         left_height = typedArray.getInteger(R.styleable.SuperEditText_left_height, 60);

         ic_left_click.setBounds(left_x, left_y,left_width, left_height);
         // Drawable.setBounds(x,y,width,height) = Sets the initial location, width, and higher information of Drawable
         // X = the starting point of the component on the container X axis, y = the starting point of the component on the container Y axis, width = the length of the component, height = the height of the component

        // b. Unclicked left Icon
         // 1. Get the resource ID
         ic_left_unclickResID = typedArray.getResourceId(R.styleable.SuperEditText_ic_left_unclick, R.drawable.ic_left_unclick);
         // 2. Obtain icon resources according to resource ID (converted into Drawable objects)
         // 3. Set the icon size (the default left Icon punctuation here is the same size as the unchecked state)
         ic_left_unclick =  getResources().getDrawable(ic_left_unclickResID);
         ic_left_unclick.setBounds(left_x, left_y,left_width, left_height);

        /**
         * Set the left image of EditText (only the left image in the initial state)
         */
        setCompoundDrawables( ic_left_unclick, null,
                null, null);

        // Introduction to setCompound Drawables (Drawable left, Drawable top, Drawable right, Drawable bottom)
        // Function: Set icons on top, bottom, left and right of EditText (equivalent to android: drawableLeft="" android: drawableRight=")
        // Note: The incoming Drawable object must have setBounds(x,y,width,height), i.e. it must have set the initial location, width, and higher information.
        // X: Starting Point y of Component on Container X Axis: Starting Point width of Component on Container Y Axis: Length height of Component: height of Component
        // If you don't want to display it somewhere, set it to null

        // Another similar approach: set Compound Drawables Within Intrinsic Bounds (Drawable left, Drawable top, Drawable right, Drawable bottom)
        // Function: Set icons on top, bottom, left and right of EditText
        // The difference from setCompound Drawables is that the width of the incoming Drawables from setCompound Drawables Within Intrinsic Bounds () is equal to the inherent width (automatically obtained through getIntrinsicWidth () & getIntrinsicHeight ())
        // setBounds(x,y,width,height) need not be set

        /**
         * Initialization cursor (color & thickness)
         */
         // Principle: Setting cursor dynamically through reflection mechanism
         // 1. Get the resource ID
         cursor = typedArray.getResourceId(R.styleable.SuperEditText_cursor, R.drawable.cursor);
         try {

            // 2. Acquiring cursor attributes by reflection
            Field f = TextView.class.getDeclaredField("mCursorDrawableRes");
            f.setAccessible(true);
            // 3. Input resource ID
            f.set(this, cursor);

         } catch (Exception e) {
            e.printStackTrace();
         }

        /**
         * Initialize partition lines (color, thickness, location)
         */
         // 1. Setting Brushes
         mPaint = new Paint();
         mPaint.setStrokeWidth(2.0f); // Thickness of partition line

         // 2. Setting the color of the partition line (using hexadecimal code, such as # 333, # 8e8e)
         int lineColorClick_default = context.getResources().getColor(R.color.lineColor_click); // Default = blue_db
         int lineColorunClick_default = context.getResources().getColor(R.color.lineColor_unclick); // Default = gray # 9b9b
         lineColor_click = typedArray.getColor(R.styleable.SuperEditText_lineColor_click, lineColorClick_default);
         lineColor_unclick = typedArray.getColor(R.styleable.SuperEditText_lineColor_unclick, lineColorunClick_default);
         color = lineColor_unclick;

         mPaint.setColor(lineColor_unclick); // Split line default color = gray
         setTextColor(color); // Default font color = gray

         // 3. Splitting line position
         linePosition = typedArray.getInteger(R.styleable.SuperEditText_linePosition, 5);
         // Eliminate self-underlining
         setBackground(null);


   /**
     * Step 3: Set all styles by listening for copying EditText itself
     * Monitoring method: onTextChanged () & onFocusChanged ()
     * Call time: when the content of the input box changes - when the focus changes
     */
      @Override
    protected void onTextChanged(CharSequence text, int start, int lengthBefore, int lengthAfter) {
        super.onTextChanged(text, start, lengthBefore, lengthAfter);
        setDeleteIconVisible(hasFocus() && text.length() > 0,hasFocus());
        // hasFocus() returns whether to get the focus of EditTEXT, that is, whether to select
        // setDeleteIconVisible ()= Judging whether to display deletion icon based on whether the input is selected or not - > Concern 1
    }

    @Override
    protected void onFocusChanged(boolean focused, int direction, Rect previouslyFocusedRect) {
        super.onFocusChanged(focused, direction, previouslyFocusedRect);
        setDeleteIconVisible(focused && length() > 0,focused);
        // Focus = whether to get the focus
        // Also, according to setDeleteIconVisible (), judge whether to display deletion icon - > Concern 1
    }

    /**
     * Focus on 1
     * Function: Set the color of the partition line
     */
    private void setDeleteIconVisible(boolean deleteVisible,boolean leftVisible) {
        color = leftVisible ? lineColor_click : lineColor_unclick;
        setTextColor(color);
        invalidate();
    }

   /**
     * Step 4: Draw a partition line
     */
    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        mPaint.setColor(color);
        setTextColor(color);
        // Drawing partition lines
        // Consideration: When the input length exceeds the input box, the lines drawn need to follow the extension.
        // Solution: Line length = control length + extended length
        int x=this.getScrollX(); // Get the extended length
        int w=this.getMeasuredWidth(); // Get control length

        // When passing in parameters, the length of the line = control length + extended length
                canvas.drawLine(0, this.getMeasuredHeight()- linePosition, w+x,
                        this.getMeasuredHeight() - linePosition, mPaint);

    }
}

attrs.xml

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <declare-styleable name="SuperEditText">

        <attr name="ic_delete" format="reference" />
        <attr name="delete_x" format="integer"  />
        <attr name="delete_y" format="integer"  />
        <attr name="delete_width" format="integer"  />
        <attr name="delete_height" format="integer"  />
        
        <attr name="ic_left_click" format="reference" />
        <attr name="ic_left_unclick" format="reference" />
        <attr name="left_x" format="integer"  />
        <attr name="left_y" format="integer"  />
        <attr name="left_width" format="integer"  />
        <attr name="left_height" format="integer"  />

        <attr name="lineColor_click" format="color"  />
        <attr name="lineColor_unclick" format="color"  />
        <attr name="linePosition" format="integer"  />

        <attr name="cursor" format="reference" />

    </declare-styleable>
</resources>

cursor.xml

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
    android:shape="rectangle" >

    <solid android:color="@color/lineColor_click" />
    <size android:width="1dp" />

</shape>

5. Full source address

Github address of Carson_Ho: Super_EditText

6. Specific use

See the article specifically: Android Custom View: You need a simple and practical SuperEditText.

7. Contribution code

  • I hope you can work with me to improve this simple and easy-to-use SuperEditText control, see specifically: Contribution Code Description
  • Suggestions on the open source project can be made on Issue. Welcome to Star!

8. summary

  • I'm sure you'll like this simple & easy-to-use SuperEditText control

Open source on Github: Super_EditText Welcome to Star!


Design sketch

Please praise! Because your encouragement is my greatest motivation to write!

Reading Related Articles
Android development: the most comprehensive and understandable Android screen adaptation solution
Android Event Distribution Mechanisms: The Most Comprehensive and Easiest to Understand in History
Android Development: The Most Complete Android Message Push Solution in History
Android development: the most comprehensive and understandable Web view in detail
Android development: JSON profile and the most comprehensive parsing method!
Four components of Android: the most comprehensive analysis in Service history
Four components of Android: the most comprehensive analysis in the history of Broadcast Receiver

Welcome to your attention. Carson_Ho The short book!

Share dried products about Android development from time to time, in the pursuit of short, flat and fast, but without lack of depth.


Posted by CWebguy on Tue, 04 Jun 2019 14:29:11 -0700