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
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 =.=