My Material Design EditText, delete function

This article is original, please indicate the source of reprint. Welcome to my Jane book.

Preface:

Material Design has developed an excellent form of text field — when the user clicks on the empty text field, the prompt that was in the input field will float to the top of the input field through an animation, and the text color will also change to emphasize color. To make it easier for developers to do this, Google has created a TextInputLayout component, which puts an EditText or TextInputEditText inside it

Add the dependent

compile 'com. Android. Support: appcompat - v7:25.1.0'
compile 'com. Android. Support: design: 25.1.0'Copy the code

TextInputLayout common attributes and usage

Names in the layout The parameter types Method name in the code annotations
counterEnabled boolean setCounterEnabled(boolean) Turns character counters on or off
counterMaxLength int setCounterMaxLength(int) Sets the maximum length of a character counter. (Only used to set the maximum counter value and does not affect the maximum length of text that can actually be entered)
errorEnabled boolean setErrorEnabled(boolean) Used to set whether error notification is enabled.
hint String setHint(CharSequence) Set the prompt for the input box.
hintAnimationEnabled boolean setHintAnimationEnabled(boolean) Toggles on or off the animation that hints float into labels.
hintEnabled boolean setHintEnabled(boolean) Hint float toggles the hint float on or off, and when set to false, just as with EditText, the hint disappears after the text is entered.
hintTextAppearance style setHintTextAppearance(int) Hint style, font color, font size, and so on. If you want to use it, please use it uniformly to ensure the unity of APP experience.
passwordToggleEnabled boolean setPasswordVisibilityToggleEnabled(boolean) Controls whether the password visibility switch is enabled. If this parameter is set to false, this function is disabled, and the password visible switch is not displayed on the right of the password input box.
passwordToggleDrawable Drawable setPasswordVisibilityToggleDrawable(Drawable) Icon for setting the password visibility switch. We usually set different ICONS for different situations, and we can use a custom selector to control the toggle of ICONS based on the “state_checked” property.
passwordToggleTint Color setPasswordVisibilityToggleTintList(ColorStateList) Controls the color of the password visible switch icon. We can set different colors on or off, and we can use a custom color selector to control the color switching based on the “state_checked” and “state_selected” properties.
passwordToggleTintMode PorterDuff.Mode setPasswordVisibilityToggleTintMode(PorterDuff.Mode) Controls the background color blending mode of the password visible switch icon. I don’t really understand this place. I hope someone can help me.
passwordToggleContentDescription int setPasswordVisibilityToggleContentDescription(int) This feature is for Talkback or other accessibility features. TalkBack reads the value of contentDescription and tells the user what the operation is.

Note: passwordToggleTintMode for more information please refer to Xfermode in Android.

Layout layout

<? xmlversion="1.0" encoding="utf-8"? > <! -- TextInputLayout:app:hintEnabled="true"// Sets whether the hint attribute can be used. The default is true
    app:hintAnimationEnabled="true"// Sets whether animation can be used. The default is true
    app:hintTextAppearance="@style/hintAppearance"// Set the text properties of the hint, and change the size and color of the hint
    app:counterEnabled="true"// Sets whether counters can be turned on. The default is false
    app:counterOverflowTextAppearance="@style/counterOverflowTextAppearance"// Set the color and size of the calculator text after offside
    app:counterTextAppearance="@style/hintAppearance"// Set the normal counter text color and size
    app:counterMaxLength="11"// Set the maximum word limit for the calculator
    app:errorEnabled="true"// Whether to allow error messages. Default is true
    app:errorTextAppearance="@style/errorAppearance"// Error message text size and color
    app:passwordToggleEnabled="true"// Sets whether to display the password eye. The default is false
    app:passwordToggleDrawable="@mipmap/ic_launcher"// Customize the eye icon
    app:passwordToggleTint="@color/colorAccent"// Color the eyes
    app:passwordToggleTintMode="multiply"// Select the shader mode to use with passwordToggleTint
-->
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
              xmlns:app="http://schemas.android.com/apk/res-auto"
              android:layout_width="match_parent"
              android:layout_height="wrap_content"
              android:orientation="vertical">

    <android.support.design.widget.TextInputLayout
        android:id="@+id/widget_textinput_layout"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:theme="@style/TextInputLayoutLineColor"
        app:counterEnabled="true"
        app:counterMaxLength="11"
        app:counterOverflowTextAppearance="@style/counterOverflowTextAppearance"
        app:errorTextAppearance="@style/errorAppearance"
        app:hintTextAppearance="@style/hintAppearance">

        <com.caihan.mydemo.widget.edittext.AutoCheckEditText
            android:id="@+id/widget_et"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:drawableEnd="@drawable/v2_et_del_image"
            android:drawableStart="@drawable/v2_register_phone"
            android:hint="Please enter user name"
            android:imeOptions="actionNext"
            android:inputType="number"
            android:singleLine="true"/>
    </android.support.design.widget.TextInputLayout>

    <android.support.design.widget.TextInputLayout
        android:id="@+id/widget_textinput_layout2"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:theme="@style/TextInputLayoutLineColor"
        app:counterEnabled="true"
        app:counterMaxLength="11"
        app:counterOverflowTextAppearance="@style/counterOverflowTextAppearance"
        app:errorTextAppearance="@style/errorAppearance"
        app:hintTextAppearance="@style/hintAppearance"
        app:passwordToggleEnabled="true"
        app:passwordToggleTint="@color/colorAccent">

        <com.caihan.mydemo.widget.edittext.AutoCheckEditText
            android:id="@+id/widget_et2"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:drawableStart="@drawable/v2_login_pwd"
            android:hint="Please enter your password"
            android:imeOptions="actionDone"
            android:inputType="textPassword"
            android:singleLine="true"/>
    </android.support.design.widget.TextInputLayout>
</LinearLayout>Copy the code

Style

<! --EditText theme Start-->
<style name="TextInputLayoutLineColor" parent="Theme.AppCompat.Light">
    <! -- Color without focus -->
    <item name="colorControlNormal">@color/colorAccent</item>
    <! Get focus color -->
    <item name="colorControlActivated">@color/main_color</item>
</style>

<! -- Float tag -->
<style name="hintAppearance" parent="TextAppearance.AppCompat">
    <item name="android:textSize">14sp</item>
    <item name="android:textColor">@color/colorPrimary</item>
</style>

<! -- Error message -->
<style name="errorAppearance" parent="TextAppearance.AppCompat">
    <item name="android:textSize">14sp</item>
    <item name="android:textColor">@android:color/holo_red_light</item>
</style>

<! Float labels, underscores, and count text change color when the count exceeds the maximum length.
<style name="counterOverflowTextAppearance" parent="TextAppearance.AppCompat">
    <item name="android:textSize">14sp</item>
    <item name="android:textColor">@android:color/holo_red_dark</item>
</style>
<! --EditText theme End-->Copy the code

modular

I like to package one function or several functions as a module, and then the project is composed of one module after another. Each module is completely decoupled, which is conducive to the later maintenance and modification. Let’s look at the structure first





AutoCheckEditText

WarnViewStatus

/** * Created by caihan on 2016/9/16
public interface WarnViewStatus {
    /** * display warning ** @param MSGS */
    void show(String... msgs);

    /**
     * 隐藏警告语
     */
    void hide();
}Copy the code

WarningMsg

/** * Created by caihan on 2017/1/22
public class WarningMsg {
    private static final String TAG = "WarningMsg";
    private int mType;
    private String mMsgString;

    public WarningMsg(int typ) {
        setType(typ);
    }

    private void setType(int typ) {
        mType = typ;
    }

    /** * regex error message * @return */
    public String getMsg() {
        switch (mType) {
            case EditTextType.TYPE_OF_MOBILE:
                // Check the phone
                mMsgString = "Please enter the correct mobile phone number";
                break;
            case EditTextType.TYPE_OF_TEL:
                // Line check
                mMsgString = "Please enter the correct landline number";
                break;
            case EditTextType.TYPE_OF_EMAIL:
                // Mailbox verification
                mMsgString = "Please enter the correct email address";
                break;
            case EditTextType.TYPE_OF_URL:
                / / check the url
                mMsgString = "Please enter the correct address";
                break;
            case EditTextType.TYPE_OF_CHZ:
                // Check Chinese characters
                mMsgString = "Please enter correct Chinese";
                break;
            case EditTextType.TYPE_OF_USERNAME:
                // Verify the user name
                mMsgString = "Please enter the correct user name";
                break;
            case EditTextType.TYPE_OF_USER_DEFINE:
                mMsgString = "";
                break;
            default:
                mMsgString = "";
                break;
        }
        return mMsgString;
    }

    /** * Invalid message ** @return */
    public String getLengthMsg() {
        mMsgString = "Not up to the mark";
        return mMsgString;
    }

    public String getMinLengthMsg() {
        mMsgString = "Not up to the mark";
        return mMsgString;
    }

    public String getMaxLengthMsg() {
        mMsgString = "Not up to the mark";
        returnmMsgString; }}Copy the code

EditTextType

/** * Created by caihan on 2017/1/22. */
public interface EditTextType {

    // Mobile check type
    int TYPE_OF_MOBILE = 0xb0;
    // Check type of landline
    int TYPE_OF_TEL = 0xb1;
    // Mailbox verification type
    int TYPE_OF_EMAIL = 0xb2;
    // Url verification type
    int TYPE_OF_URL = 0xb3;
    // Chinese check type
    int TYPE_OF_CHZ = 0xb4;
    // User name verification type
    int TYPE_OF_USERNAME = 0xb5;
    // User-defined
    int TYPE_OF_USER_DEFINE = 0xbb;
}Copy the code

Check

/** * Created by caihan on 2017/1/16
public class Check {
    private static final String TAG = "Check";
    // Verify the landline number in the correct format: XXX/XXXX-XXXXXXX/XXXXXXXX
    private static final String REGEX_TEL = "^ 0 \ \ d {2, 3} [-]? \ \ d {7, 8}";

    public static boolean getMatch(int typ, String string.String. userRegxs) {boolean isMatch = false;
        switch (typ) {
            case EditTextType.TYPE_OF_MOBILE:
                isMatch = isMobile(string);
                break;
            case EditTextType.TYPE_OF_TEL:
                isMatch = isTel(string);
                break;
            case EditTextType.TYPE_OF_EMAIL:
                isMatch = isEmail(string);
                break;
            case EditTextType.TYPE_OF_URL:
                isMatch = isURL(string);
                break;
            case EditTextType.TYPE_OF_CHZ:
                isMatch = isChz(string);
                break;
            case EditTextType.TYPE_OF_USERNAME:
                isMatch = isUsername(string);
                break;
            case EditTextType.TYPE_OF_USER_DEFINE:
                if(userRegxs ! =null && userRegxs.length > 0 && !StringUtils.isEmpty(userRegxs[0])) {
                    isMatch = isMatch(userRegxs[0].string);
                }
                break;
            default:
                break;
        }
        return isMatch;
    }

    /** * @param string Indicates whether the text to be verified * @return matches the mobile phone number format */
    private static boolean isMobile(String string) {
        return RegexUtils.isMobileSimple(string);
    }

    /** * @param string Indicates whether the text to be verified * @return matches the format of the landline number */
    private static boolean isTel(String string) {
        return RegexUtils.isMatch(REGEX_TEL, string);
    }

    /** * @param string Indicates whether the text to be verified * @return matches the email format */
    private static boolean isEmail(String string) {
        return RegexUtils.isEmail(string);
    }

    /** * @param string Indicates whether the text to be verified * @return matches the url format */
    private static boolean isURL(String string) {
        return RegexUtils.isURL(string);
    }

    /** * @param string Indicates whether the text to be verified * @return matches Chinese characters */
    private static boolean isChz(String string) {
        return RegexUtils.isZh(string);
    }

    /** * @param string Indicates whether the text to be verified * @return matches the user name */
    private static boolean isUsername(String string) {
        return RegexUtils.isUsername(string);
    }

    Return {@code true}: matches 

{@code false}: does not match */
private static boolean isMatch(String regex, CharSequence input) { returnRegexUtils.isMatch(regex, input); }}Copy the code

The above classes are basically nothing to say, I am not used to put everything in one class, so I divided a lot of classes out, personal habit problem. AutoCheckEditText is an AutoCheckEditText class that implements delete buttons and regex annotations

/** * Created by caihan on 2017/1/16. */
public class AutoCheckEditText extends TextInputEditText implements TextWatcher.View.OnFocusChangeListener {
    private static final String TAG = "AutoCheckEditText";

    private Context mContext;
    private int mType;
    private Drawable successDrawable;
    private Drawable unsuccessDrawable;
    private String userRegx;
    // Left icon
    private Drawable mLeftDrawable;
    // Delete the icon on the right
    private Drawable mRightDrawable;
    private final int DRAWABLE_LEFT = 0;
    private final int DRAWABLE_TOP = 1;
    private final int DRAWABLE_RIGHT = 2;
    private final int DRAWABLE_BOTTOM = 3;
    private WarnViewStatus mWarnViewListener;
    private WarningMsg mWarningMsg;
    private int mMinLength = 0;
    private int mMaxLength = Integer.MAX_VALUE;

    public AutoCheckEditText(Context context) {
        super(context);
        init(context);
    }

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

    public AutoCheckEditText(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init(context);
    }


    private void init(Context context) {
        if (context == null) return;
        mContext = context;
        mRightDrawable = getCompoundDrawablesRelative()[DRAWABLE_RIGHT];
        mLeftDrawable = getCompoundDrawablesRelative()[DRAWABLE_LEFT];
// this.setImeOptions(EditorInfo.IME_ACTION_DONE);
// this.setInputType(EditorInfo.TYPE_CLASS_TEXT);
        setCompoundDrawablesRelativeWithIntrinsicBounds(mLeftDrawable, null.null.null);
        this.addTextChangedListener(this);
        this.setOnFocusChangeListener(this);
    }

    / * * *@paramTyp Indicates the type to be verified *@paramWarnViewStatus Error message status listener */
    public void creatCheck(int typ, WarnViewStatus warnViewStatus) {
        this.mType = typ;
        mWarningMsg = new WarningMsg(typ);
        mWarnViewListener = warnViewStatus;
    }

    /** * Sets the length of the judgment range **@param minLength
     * @param maxLength
     */
    public void setLength(int minLength, int maxLength) {
        setMinLength(minLength);
        setMaxLength(maxLength);
    }

    public void setMinLength(int minLength) {
        mMinLength = minLength;
    }

    public void setMaxLength(int maxLength) {
        mMaxLength = maxLength;
    }

    / * * *@paramTyp Indicates the type to be verified *@paramSuccess Indicates the icon * when the match is successful@paramUnsuccess Icon * for a failed match@paramUserRegex User - defined re */
    public void creatCheck(int typ, Drawable success, Drawable unsuccess, String userRegex) {
        creatCheck(typ, success, unsuccess);
        this.userRegx = userRegex;
    }

    / * * *@paramTyp Indicates the type to be verified *@paramSuccess Indicates the icon * when the match is successful@paramUnsuccess Indicates the icon */ when the match fails
    private void creatCheck(int typ, Drawable success, Drawable unsuccess) {
        mType = typ;
        successDrawable = success;
        successDrawable.setBounds(0.0,
                successDrawable.getMinimumWidth(), successDrawable.getMinimumHeight());
        unsuccessDrawable = unsuccess;
        unsuccessDrawable.setBounds(0.0,
                unsuccessDrawable.getMinimumWidth(), unsuccessDrawable.getMinimumHeight());
        mWarningMsg = new WarningMsg(typ);
    }

    @Override
    public void beforeTextChanged(CharSequence s, int start, int count, int after) {}@Override
    public void afterTextChanged(Editable s) {
        updateCleanable(s.toString().length(), true);
        if(s ! =null && s.length() > 0) {
            if (s.length() >= mMinLength && s.length() <= mMaxLength) {
                booleanisMatch = Check.getMatch(mType, s.toString(), userRegx); changeWarnStatus(! isMatch, mWarningMsg.getMsg());// if (isMatch) {
// setCompoundDrawables(null, null, successDrawable, null);
// } else {
// setCompoundDrawables(null, null, unsuccessDrawable, null);
/ /}
            } else {
                changeWarnStatus(true, mWarningMsg.getLengthMsg()); }}else {
// setCompoundDrawables(null, null, null, null);
            changeWarnStatus(false, mWarningMsg.getMsg()); }}@Override
    public void onTextChanged(CharSequence s, int start, int before, int count) {}@Override
    public boolean onTouchEvent(MotionEvent event) {
        // We can get four drawable (up, down, left, and right). Empty if icon is not set.
        if(mRightDrawable ! =null && event.getAction() == MotionEvent.ACTION_UP) {
            // Check if you click on the delete icon on the right
            // Note that getRwwX() is used to get the position relative to the screen, getX() may get the position relative to the parent component
            int leftEdgeOfRightDrawable = getRight() - getPaddingRight()
                    - mRightDrawable.getBounds().width();
            if (event.getRawX() >= leftEdgeOfRightDrawable) {
                setText(""); }}return super.onTouchEvent(event);
    }

    @Override
    protected void finalize(a) throws Throwable {
        mRightDrawable = null;
        super.finalize();
    }

    @Override
    public void onFocusChange(View v, boolean hasFocus) {
        // Update the status and check whether the delete button is displayed
        updateCleanable(this.getText().length(), hasFocus);
    }

    /** * The delete button on the right is displayed only when the content is not empty and the focus is obtained@param length
     * @param hasFocus
     */
    private void updateCleanable(int length, boolean hasFocus) {
        if (length > 0 && hasFocus) {
            setCompoundDrawablesRelativeWithIntrinsicBounds(mLeftDrawable, null, mRightDrawable, null);
        } else {
            setCompoundDrawablesRelativeWithIntrinsicBounds(mLeftDrawable, null.null.null); }}/** * Updates the error message status **@paramIsShow Indicates whether to display a prompt. True = Display *@paramMSG prompt */
    private void changeWarnStatus(boolean isShow, String msg) {
        if(mWarnViewListener ! =null) {
            if (isShow) {
                mWarnViewListener.show(msg);
            } else{ mWarnViewListener.hide(); }}}}Copy the code

And you might say, well, why does this inherit TextInputEditText instead of EditText? The purpose of this is to display the hint in the editor in full screen mode. I mentioned this in the introduction, but again, you can use the EditText instead

AutoCheckEditTextClass

So here’s how to use it. I’ve created a class for TextInputLayout and EditText. Okay

/** * Created by caihan on 2017/1/22. * Widget_autocheck_et_layout.xml */
public class AutoCheckEditTextClass implements WarnViewStatus {
    private static final String TAG = "AutoCheckEditTextClass";

    private TextInputLayout mTextInputLayout;
    private AutoCheckEditText mAutoCheckEditText;

    public AutoCheckEditTextClass(TextInputLayout inputLayout, AutoCheckEditText editText) {
        mTextInputLayout = inputLayout;
        mAutoCheckEditText = editText;
    }

    /** * Sets the regular verification type *@param typ
     * @return* /
    public AutoCheckEditTextClass checkType(int typ) {
        mAutoCheckEditText.creatCheck(typ, this);
        return this;
    }

    /** * Set the minimum judgment length (usually not set, default 0) *@param minLength
     * @return* /
    public AutoCheckEditTextClass setMinLength(int minLength) {
        mAutoCheckEditText.setMinLength(minLength);
        return this;
    }

    / * * *@paramMaxLength When setting the maximum length, sets the maximum word limit for the calculator *@paramCounterEnabled Whether the calculator is enabled *@return* /
    public AutoCheckEditTextClass setMaxLength(int maxLength, boolean counterEnabled) {
        mTextInputLayout.setCounterMaxLength(maxLength);
        mTextInputLayout.setCounterEnabled(counterEnabled);
        mAutoCheckEditText.setMaxLength(maxLength);
        return this;
    }

    / * * *@paramMaxLength When setting the maximum length, sets the maximum word limit for the calculator *@return* /
    public AutoCheckEditTextClass setMaxLength(int maxLength) {
        mTextInputLayout.setCounterMaxLength(maxLength);
        mTextInputLayout.setCounterEnabled(false);
        mAutoCheckEditText.setMaxLength(maxLength);
        return this;
    }

    /** * TextInputLayout Hint switch * If you only want to use the EditText default, pass false. The default is true@param hintEnabled
     * @return* /
    public AutoCheckEditTextClass setHintEnabled(boolean hintEnabled) {
        mTextInputLayout.setHintEnabled(hintEnabled);
        return this;
    }

    @Override
    public void show(String... msgs) {
        mTextInputLayout.setErrorEnabled(true);
        if (msgs.length > 0 && !StringUtils.isEmpty(msgs[0])) {
            mTextInputLayout.setError(msgs[0]); }}@Override
    public void hide(a) {
        mTextInputLayout.setErrorEnabled(false); }}Copy the code

Interface to invoke

Okay, so that’s it for modules, and finally let’s look at how the interface calls them, okay

In the Layout

Just a word

<include layout="@layout/widget_autocheck_et_layout"/>Copy the code

In the Acticity

There’s only one link

AutoCheckEditTextClass editTextClass = new AutoCheckEditTextClass(mWidgetTextinputLayout,
                mWidgetEt)
                .checkType(EditTextType.TYPE_OF_MOBILE).setMaxLength(11,true);Copy the code

Wrap it up!


Thank you

Thanks to Blankj for AndroidUtilCode and EditText with regular checksum

The last

Always want to say that find time to write a few Demo on GitHub, so more convenient hand hand party directly download down to use, but have no time, the boss of the evil meeting said that can not let me too idle, when the program ape idle, we comment on =.=