diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 691fb2f..0a9eb12 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -72,6 +72,26 @@ android:label="" android:windowSoftInputMode="adjustResize|stateHidden" /> + + + + + + + + \ No newline at end of file diff --git a/app/src/main/java/com/project/survey/activity/login/ForgetPwdActivity.kt b/app/src/main/java/com/project/survey/activity/login/ForgetPwdActivity.kt new file mode 100644 index 0000000..f364bce --- /dev/null +++ b/app/src/main/java/com/project/survey/activity/login/ForgetPwdActivity.kt @@ -0,0 +1,30 @@ +package com.project.survey.activity.login + +import android.content.Intent +import androidx.core.widget.addTextChangedListener +import com.project.survey.activity.base.BaseBindingActivity +import com.project.survey.databinding.ActivityForgetPwdBinding + +/** + * 忘记密码 + */ +class ForgetPwdActivity : BaseBindingActivity() { + override fun getBinding(): ActivityForgetPwdBinding { + return ActivityForgetPwdBinding.inflate(layoutInflater) + } + + override fun initView() { + mBinding.etAccount.addTextChangedListener { + mBinding.tvSendCode.setEnabled(it?.isNotEmpty() == true); + } + + mBinding.tvSendCode.setOnClickListener { + startActivity(Intent(this, ForgetPwdInputCodeActivity::class.java)) + } + } + + override fun initData() { + + } + +} \ No newline at end of file diff --git a/app/src/main/java/com/project/survey/activity/login/ForgetPwdInputCodeActivity.kt b/app/src/main/java/com/project/survey/activity/login/ForgetPwdInputCodeActivity.kt new file mode 100644 index 0000000..cb09a06 --- /dev/null +++ b/app/src/main/java/com/project/survey/activity/login/ForgetPwdInputCodeActivity.kt @@ -0,0 +1,25 @@ +package com.project.survey.activity.login + +import android.content.Intent +import com.project.survey.activity.base.BaseBindingActivity +import com.project.survey.databinding.ActivityForgetPwdInputCodeBinding + +/** + * 忘记密码后的输入验证码 + */ +class ForgetPwdInputCodeActivity : BaseBindingActivity() { + override fun getBinding(): ActivityForgetPwdInputCodeBinding { + return ActivityForgetPwdInputCodeBinding.inflate(layoutInflater) + } + + override fun initView() { + mBinding.etInputCode.setOnInputListener { + startActivity(Intent(this, SetNewPwdActivity::class.java)) + } + } + + override fun initData() { + + } + +} \ No newline at end of file diff --git a/app/src/main/java/com/project/survey/activity/login/LoginActivity.kt b/app/src/main/java/com/project/survey/activity/login/LoginActivity.kt index a1996c8..c0702a5 100644 --- a/app/src/main/java/com/project/survey/activity/login/LoginActivity.kt +++ b/app/src/main/java/com/project/survey/activity/login/LoginActivity.kt @@ -18,14 +18,14 @@ class LoginActivity : BaseBindingActivity() { } override fun initView() { - mBinding.pwdShowHide.setOnClickListener { - mBinding.ivPwdShowHide.isSelected = !mBinding.ivPwdShowHide.isSelected - if (mBinding.ivPwdShowHide.isSelected) { - mBinding.etPwd.transformationMethod = HideReturnsTransformationMethod.getInstance() + mBinding.ilPwd.pwdShowHide.setOnClickListener { + mBinding.ilPwd.ivPwdShowHide.isSelected = !mBinding.ilPwd.ivPwdShowHide.isSelected + if (mBinding.ilPwd.ivPwdShowHide.isSelected) { + mBinding.ilPwd.etPwd.transformationMethod = HideReturnsTransformationMethod.getInstance() } else { - mBinding.etPwd.transformationMethod = PasswordTransformationMethod.getInstance() + mBinding.ilPwd.etPwd.transformationMethod = PasswordTransformationMethod.getInstance() } - mBinding.etPwd.setSelection(mBinding.etPwd.text?.length ?: 0) + mBinding.ilPwd.etPwd.setSelection(mBinding.ilPwd.etPwd.text?.length ?: 0) } mBinding.tvShowOutLogin.setOnClickListener { @@ -48,6 +48,11 @@ class LoginActivity : BaseBindingActivity() { } } + mBinding.tvForgetPwd.setOnClickListener { + //忘记密码 + startActivity(Intent(this, ForgetPwdActivity::class.java)) + } + } /** @@ -82,7 +87,7 @@ class LoginActivity : BaseBindingActivity() { } mBinding.etAccount.text = null - mBinding.etPwd.text = null + mBinding.ilPwd.etPwd.text = null } override fun initData() { diff --git a/app/src/main/java/com/project/survey/activity/login/LoginInputCodeActivity.kt b/app/src/main/java/com/project/survey/activity/login/LoginInputCodeActivity.kt index 6887cff..f4c44f7 100644 --- a/app/src/main/java/com/project/survey/activity/login/LoginInputCodeActivity.kt +++ b/app/src/main/java/com/project/survey/activity/login/LoginInputCodeActivity.kt @@ -18,4 +18,5 @@ class LoginInputCodeActivity : BaseBindingActivity() { + override fun getBinding(): ActivitySetNewPwdBinding { + return ActivitySetNewPwdBinding.inflate(layoutInflater) + } + + override fun initView() { + + } + + override fun initData() { + + } + +} \ No newline at end of file diff --git a/app/src/main/java/com/project/survey/widget/edittext/GravityEnum.java b/app/src/main/java/com/project/survey/util/GravityEnum.java similarity index 97% rename from app/src/main/java/com/project/survey/widget/edittext/GravityEnum.java rename to app/src/main/java/com/project/survey/util/GravityEnum.java index 0bcb2c2..2e8888e 100644 --- a/app/src/main/java/com/project/survey/widget/edittext/GravityEnum.java +++ b/app/src/main/java/com/project/survey/util/GravityEnum.java @@ -15,7 +15,7 @@ * */ -package com.project.survey.widget.edittext; +package com.project.survey.util; import android.annotation.SuppressLint; import android.annotation.TargetApi; diff --git a/app/src/main/java/com/project/survey/util/ThemeUtils.java b/app/src/main/java/com/project/survey/util/ThemeUtils.java index add43fe..1779e84 100644 --- a/app/src/main/java/com/project/survey/util/ThemeUtils.java +++ b/app/src/main/java/com/project/survey/util/ThemeUtils.java @@ -26,7 +26,6 @@ import androidx.core.content.ContextCompat; import com.project.survey.R; -import com.project.survey.widget.edittext.GravityEnum; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; diff --git a/app/src/main/java/com/project/survey/widget/edittext/PassEdittext2.java b/app/src/main/java/com/project/survey/widget/edittext/PassEdittext2.java deleted file mode 100644 index 24a2ec5..0000000 --- a/app/src/main/java/com/project/survey/widget/edittext/PassEdittext2.java +++ /dev/null @@ -1,318 +0,0 @@ -package com.project.survey.widget.edittext; - -import android.content.Context; -import android.content.res.TypedArray; -import android.graphics.Typeface; -import android.graphics.drawable.Drawable; -import android.os.Parcel; -import android.os.Parcelable; -import android.text.Editable; -import android.text.TextWatcher; -import android.text.method.PasswordTransformationMethod; -import android.util.AttributeSet; -import android.view.MotionEvent; -import android.widget.EditText; - -import androidx.annotation.NonNull; -import androidx.appcompat.widget.AppCompatEditText; - -import com.project.survey.R; -import com.project.survey.util.DensityUtils; -import com.project.survey.util.ResUtils; - -public class PassEdittext2 extends androidx.appcompat.widget.AppCompatEditText { - /** - * 增大点击区域 - */ - private int mExtraClickArea; - - private final static int ALPHA_ICON_ENABLED = (int) (255 * 0.54f); - private final static int ALPHA_ICON_DISABLED = (int) (255 * 0.38f); - - private Drawable mShowPwDrawable; - private Drawable mHidePwDrawable; - private boolean mPasswordVisible; - private boolean mShowingIcon; - private boolean mSetErrorCalled; - private boolean mHoverShowsPw; - private boolean mHandlingHoverEvent; - private PasswordTransformationMethod mTransformationMethod; - - public PassEdittext2(Context context) { - this(context, null); - } - - public PassEdittext2(Context context, AttributeSet attrs) { - this(context, attrs, R.attr.PasswordEditTextStyle); - } - - public PassEdittext2(Context context, AttributeSet attrs, int defStyleAttr) { - super(context, attrs, defStyleAttr); - initAttrs(context, attrs, defStyleAttr); - } - - public void initAttrs(Context context, AttributeSet attrs, int defStyleAttr) { - mExtraClickArea = DensityUtils.dp2px(context, 20); - TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.PasswordEditText, defStyleAttr, 0); - boolean useNonMonospaceFont; - boolean enableIconAlpha; - try { - mShowPwDrawable = ResUtils.getDrawableAttrRes(getContext(), typedArray, R.styleable.PasswordEditText_pet_iconShow); - if (mShowPwDrawable == null) { - mShowPwDrawable = ResUtils.getVectorDrawable(getContext(), R.drawable.pet_icon_visibility_24dp); - } - mHidePwDrawable = ResUtils.getDrawableAttrRes(getContext(), typedArray, R.styleable.PasswordEditText_pet_iconHide); - if (mHidePwDrawable == null) { - mHidePwDrawable = ResUtils.getVectorDrawable(getContext(), R.drawable.pet_icon_visibility_off_24dp); - } - mHoverShowsPw = typedArray.getBoolean(R.styleable.PasswordEditText_pet_hoverShowsPw, false); - useNonMonospaceFont = typedArray.getBoolean(R.styleable.PasswordEditText_pet_nonMonospaceFont, false); - enableIconAlpha = typedArray.getBoolean(R.styleable.PasswordEditText_pet_enableIconAlpha, true); - boolean isAsteriskStyle = typedArray.getBoolean(R.styleable.PasswordEditText_pet_isAsteriskStyle, false); - if (isAsteriskStyle) { - mTransformationMethod = AsteriskPasswordTransformationMethod.getInstance(); - } else { - mTransformationMethod = PasswordTransformationMethod.getInstance(); - } - } finally { - typedArray.recycle(); - } - - if (enableIconAlpha) { - mHidePwDrawable.setAlpha(ALPHA_ICON_ENABLED); - mShowPwDrawable.setAlpha(ALPHA_ICON_DISABLED); - } - -// if (useNonMonospaceFont) { -// setTypeface(Typeface.DEFAULT); -// } - - addTextChangedListener(new TextWatcher() { - @Override - public void beforeTextChanged(CharSequence s, int start, int count, int after) { - } - - @Override - public void onTextChanged(CharSequence seq, int start, int before, int count) { - } - - @Override - public void afterTextChanged(Editable s) { - if (s.length() > 0) { - if (mSetErrorCalled) { - setCompoundDrawablesRelative(null, null, null, null); - mSetErrorCalled = false; - showPasswordVisibilityIndicator(true); - } - if (!mShowingIcon) { - showPasswordVisibilityIndicator(true); - } - } else { - // hides the indicator if no text inside text field - mPasswordVisible = false; - handlePasswordInputVisibility(); - showPasswordVisibilityIndicator(false); - } - - } - }); - - handlePasswordInputVisibility(); - } - - public PassEdittext2 setExtraClickAreaSize(int extraClickArea) { - mExtraClickArea = extraClickArea; - return this; - } - - /** - * 设置密码输入框的样式 - * - * @param transformationMethod - * @return - */ - public PassEdittext2 setPasswordTransformationMethod(PasswordTransformationMethod transformationMethod) { - mTransformationMethod = transformationMethod; - return this; - } - - /** - * 设置密码输入框的样式 - * - * @param isAsteriskStyle - * @return - */ - public PassEdittext2 setIsAsteriskStyle(boolean isAsteriskStyle) { - if (isAsteriskStyle) { - mTransformationMethod = AsteriskPasswordTransformationMethod.getInstance(); - } else { - mTransformationMethod = PasswordTransformationMethod.getInstance(); - } - return this; - } - - private boolean isRtl() { - return getLayoutDirection() == LAYOUT_DIRECTION_RTL; - } - - @Override - public Parcelable onSaveInstanceState() { - Parcelable superState = super.onSaveInstanceState(); - return new PassEdittext2.SavedState(superState, mShowingIcon, mPasswordVisible); - } - - @Override - public void onRestoreInstanceState(Parcelable state) { - PasswordEditText.SavedState savedState = (PasswordEditText.SavedState) state; - super.onRestoreInstanceState(savedState.getSuperState()); - mShowingIcon = savedState.isShowingIcon(); - mPasswordVisible = savedState.isPasswordVisible(); - handlePasswordInputVisibility(); - showPasswordVisibilityIndicator(mShowingIcon); - } - - @Override - public void setError(CharSequence error) { - super.setError(error); - mSetErrorCalled = true; - - } - - @Override - public void setError(CharSequence error, Drawable icon) { - super.setError(error, icon); - mSetErrorCalled = true; - } - - @Override - public boolean onTouchEvent(MotionEvent event) { - if (!mShowingIcon) { - return super.onTouchEvent(event); - } else { - boolean touchable = isTouchable(event); - switch (event.getAction()) { - case MotionEvent.ACTION_DOWN: - if (mHoverShowsPw) { - if (touchable) { - togglePasswordIconVisibility(); - // prevent keyboard from coming up - event.setAction(MotionEvent.ACTION_CANCEL); - mHandlingHoverEvent = true; - } - } - break; - case MotionEvent.ACTION_UP: - if (mHandlingHoverEvent || touchable) { - togglePasswordIconVisibility(); - // prevent keyboard from coming up - event.setAction(MotionEvent.ACTION_CANCEL); - mHandlingHoverEvent = false; - } - break; - default: - break; - } - return super.onTouchEvent(event); - } - } - - private boolean isTouchable(MotionEvent event) { - boolean touchable; - if (isRtl()) { - touchable = event.getX() > getPaddingLeft() - mExtraClickArea && event.getX() < getPaddingLeft() + mShowPwDrawable.getIntrinsicWidth() + mExtraClickArea; - } else { - touchable = event.getX() > getWidth() - getPaddingRight() - mShowPwDrawable.getIntrinsicWidth() - mExtraClickArea && event.getX() < getWidth() - getPaddingRight() + mExtraClickArea; - } - return touchable; - } - - - private void showPasswordVisibilityIndicator(boolean shouldShowIcon) { - if (shouldShowIcon) { - Drawable drawable = mPasswordVisible ? mShowPwDrawable : mHidePwDrawable; - mShowingIcon = true; - setCompoundDrawablesRelativeWithIntrinsicBounds(null, null, drawable, null); - } else { - // reset drawable - setCompoundDrawablesRelative(null, null, null, null); - mShowingIcon = false; - } - } - - /** - * This method toggles the visibility of the icon and takes care of switching the input type - * of the view to be able to see the password afterwards. - *

- * This method may only be called if there is an icon visible - */ - private void togglePasswordIconVisibility() { - mPasswordVisible = !mPasswordVisible; - handlePasswordInputVisibility(); - showPasswordVisibilityIndicator(true); - } - - /** - * This method is called when restoring the state (e.g. on orientation change) - */ - private void handlePasswordInputVisibility() { - int selectionStart = getSelectionStart(); - int selectionEnd = getSelectionEnd(); - if (mPasswordVisible) { - setTransformationMethod(null); - } else { - setTransformationMethod(mTransformationMethod); - } - setSelection(selectionStart, selectionEnd); - - } - - /** - * Convenience class to save / restore the state of icon. - */ - protected static class SavedState extends BaseSavedState { - - private final boolean mShowingIcon; - private final boolean mPasswordVisible; - - private SavedState(Parcelable superState, boolean sI, boolean pV) { - super(superState); - mShowingIcon = sI; - mPasswordVisible = pV; - } - - private SavedState(Parcel in) { - super(in); - mShowingIcon = in.readByte() != 0; - mPasswordVisible = in.readByte() != 0; - } - - public boolean isShowingIcon() { - return mShowingIcon; - } - - public boolean isPasswordVisible() { - return mPasswordVisible; - } - - @Override - public void writeToParcel(Parcel destination, int flags) { - super.writeToParcel(destination, flags); - destination.writeByte((byte) (mShowingIcon ? 1 : 0)); - destination.writeByte((byte) (mPasswordVisible ? 1 : 0)); - } - - public static final Creator CREATOR = new Creator() { - - @Override - public PassEdittext2.SavedState createFromParcel(Parcel in) { - return new PassEdittext2.SavedState(in); - } - - @Override - public PassEdittext2.SavedState[] newArray(int size) { - return new PassEdittext2.SavedState[size]; - } - - }; - } -} diff --git a/app/src/main/java/com/project/survey/widget/edittext/materialedittext/MaterialEditText.java b/app/src/main/java/com/project/survey/widget/edittext/materialedittext/MaterialEditText.java deleted file mode 100644 index 3576b11..0000000 --- a/app/src/main/java/com/project/survey/widget/edittext/materialedittext/MaterialEditText.java +++ /dev/null @@ -1,1788 +0,0 @@ -package com.project.survey.widget.edittext.materialedittext; - -import android.animation.ArgbEvaluator; -import android.animation.ObjectAnimator; -import android.content.Context; -import android.content.res.ColorStateList; -import android.content.res.TypedArray; -import android.graphics.Bitmap; -import android.graphics.BitmapFactory; -import android.graphics.Canvas; -import android.graphics.Color; -import android.graphics.Paint; -import android.graphics.PorterDuff; -import android.graphics.Typeface; -import android.graphics.drawable.Drawable; -import android.os.Build; -import android.text.Editable; -import android.text.Layout; -import android.text.StaticLayout; -import android.text.TextPaint; -import android.text.TextUtils; -import android.text.TextWatcher; -import android.text.method.PasswordTransformationMethod; -import android.text.method.TransformationMethod; -import android.util.AttributeSet; -import android.view.Gravity; -import android.view.MotionEvent; -import android.view.View; - -import androidx.annotation.DrawableRes; -import androidx.annotation.IntDef; -import androidx.annotation.Keep; -import androidx.annotation.NonNull; -import androidx.annotation.Nullable; -import androidx.appcompat.widget.AppCompatEditText; - - -import com.project.survey.R; -import com.project.survey.util.DensityUtils; -import com.project.survey.util.DrawableUtils; -import com.project.survey.util.ResUtils; -import com.project.survey.util.ThemeUtils; -import com.project.survey.widget.XUI; -import com.project.survey.widget.edittext.AsteriskPasswordTransformationMethod; -import com.project.survey.widget.edittext.materialedittext.validation.METLengthChecker; -import com.project.survey.widget.edittext.materialedittext.validation.METValidator; -import com.project.survey.widget.edittext.materialedittext.validation.NotAllowEmptyValidator; -import com.project.survey.widget.edittext.materialedittext.validation.RegexpValidator; -import com.project.survey.widget.util.Utils; - -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.util.ArrayList; - -import java.util.Iterator; -import java.util.List; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -import io.github.inflationx.calligraphy3.HasTypeface; - - -/** - * Material Design 输入框 - * - * @author XUE - * @since 2019/3/20 16:47 - */ -@Keep -public class MaterialEditText extends AppCompatEditText implements HasTypeface { - - @Retention(RetentionPolicy.SOURCE) - @IntDef({FLOATING_LABEL_NONE, FLOATING_LABEL_NORMAL, FLOATING_LABEL_HIGHLIGHT}) - public @interface FloatingLabelType { - } - - public static final int FLOATING_LABEL_NONE = 0; - public static final int FLOATING_LABEL_NORMAL = 1; - public static final int FLOATING_LABEL_HIGHLIGHT = 2; - - /** - * the spacing between the main text and the inner top padding. - */ - private int extraPaddingTop; - - /** - * the spacing between the main text and the inner bottom padding. - */ - private int extraPaddingBottom; - - /** - * the extra spacing between the main text and the left, actually for the left icon. - */ - private int extraPaddingLeft; - - /** - * the extra spacing between the main text and the right, actually for the right icon. - */ - private int extraPaddingRight; - - /** - * the floating label's text size. - */ - private int floatingLabelTextSize; - - /** - * the floating label's text color. - */ - private int floatingLabelTextColor; - - /** - * the bottom texts' size. - */ - private int bottomTextSize; - - /** - * the spacing between the main text and the floating label. - */ - private int floatingLabelPadding; - - /** - * the spacing between the main text and the bottom components (bottom ellipsis, helper/error text, characters counter). - */ - private int bottomSpacing; - - /** - * whether the floating label should be shown. default is false. - */ - private boolean floatingLabelEnabled; - - /** - * whether to highlight the floating label's text color when focused (with the main color). default is true. - */ - private boolean highlightFloatingLabel; - - /** - * the base color of the line and the texts. default is black. - */ - private int baseColor; - - /** - * inner top padding - */ - private int innerPaddingTop; - - /** - * inner bottom padding - */ - private int innerPaddingBottom; - - /** - * inner left padding - */ - private int innerPaddingLeft; - - /** - * inner right padding - */ - private int innerPaddingRight; - - /** - * the underline's highlight color, and the highlight color of the floating label if app:highlightFloatingLabel is set true in the xml. default is black(when app:darkTheme is false) or white(when app:darkTheme is true) - */ - private int primaryColor; - - /** - * the color for when something is wrong.(e.g. exceeding max characters) - */ - private int errorColor; - - /** - * min characters count limit. 0 means no limit. default is 0. NOTE: the character counter will increase the View's height. - */ - private int minCharacters; - - /** - * max characters count limit. 0 means no limit. default is 0. NOTE: the character counter will increase the View's height. - */ - private int maxCharacters; - - /** - * whether to show the bottom ellipsis in singleLine mode. default is false. NOTE: the bottom ellipsis will increase the View's height. - */ - private boolean singleLineEllipsis; - - /** - * Always show the floating label, instead of animating it in/out. False by default. - */ - private boolean floatingLabelAlwaysShown; - - /** - * Always show the helper text, no matter if the edit text is focused. False by default. - */ - private boolean helperTextAlwaysShown; - - /** - * bottom ellipsis's height - */ - private int bottomEllipsisSize; - - /** - * min bottom lines count. - */ - private int minBottomLines; - - /** - * reserved bottom text lines count, no matter if there is some helper/error text. - */ - private int minBottomTextLines; - - /** - * real-time bottom lines count. used for bottom extending/collapsing animation. - */ - private float currentBottomLines; - - /** - * bottom lines count. - */ - private float bottomLines; - - /** - * Helper text at the bottom - */ - private String helperText; - - /** - * Helper text color - */ - private int helperTextColor = -1; - - /** - * error text for manually invoked - */ - private String tempErrorText; - - /** - * animation fraction of the floating label (0 as totally hidden). - */ - private float floatingLabelFraction; - - /** - * whether the floating label is being shown. - */ - private boolean floatingLabelShown; - - /** - * the floating label's focusFraction - */ - private float focusFraction; - - /** - * The font used for the accent texts (floating label, error/helper text, character counter, etc.) - */ - private Typeface accentTypeface; - - /** - * Text for the floatLabel if different from the hint - */ - private CharSequence floatingLabelText; - - /** - * Whether or not to show the underline. Shown by default - */ - private boolean hideUnderline; - - /** - * Underline's color - */ - private int underlineColor; - /** - * Underline's height - */ - private int underlineHeight; - private int underlineHeightFocused; - /** - * Whether to validate as soon as the text has changed. False by default - */ - private boolean autoValidate; - - /** - * Whether the characters count is valid - */ - private boolean charactersCountValid; - - /** - * Whether use animation to show/hide the floating label. - */ - private boolean floatingLabelAnimating; - - /** - * Whether check the characters count at the beginning it's shown. - */ - private boolean checkCharactersCountAtBeginning; - - /** - * Left Icon - */ - private Bitmap[] iconLeftBitmaps; - - /** - * Right Icon - */ - private Bitmap[] iconRightBitmaps; - - /** - * Clear Button - */ - private Bitmap[] clearButtonBitmaps; - /** - * showPwIcon Button - */ - private Bitmap[] showPwIconBitmaps; - /** - * hidePwIcon Button - */ - private Bitmap[] hidePwIconBitmaps; - - private boolean passwordVisible; - - /** - * Auto validate when focus lost. - */ - private boolean validateOnFocusLost; - - private boolean showClearButton; - private boolean showPasswordButton; - private boolean firstShown; - private int iconSize; - private int iconOuterWidth; - private int iconOuterHeight; - private int iconPadding; - private boolean actionButtonTouched; - private boolean actionButtonClicking; - private ColorStateList textColorStateList; - private ColorStateList textColorHintStateList; - private ArgbEvaluator focusEvaluator = new ArgbEvaluator(); - Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG); - TextPaint textPaint = new TextPaint(Paint.ANTI_ALIAS_FLAG); - StaticLayout textLayout; - ObjectAnimator labelAnimator; - ObjectAnimator labelFocusAnimator; - ObjectAnimator bottomLinesAnimator; - OnFocusChangeListener innerFocusChangeListener; - OnFocusChangeListener outerFocusChangeListener; - private List validators = new ArrayList<>(); - private METLengthChecker lengthChecker; - private PasswordTransformationMethod mTransformationMethod; - - public MaterialEditText(Context context) { - this(context, null); - } - - public MaterialEditText(Context context, AttributeSet attrs) { - this(context, attrs, R.attr.MaterialEditTextStyle); - } - - public MaterialEditText(Context context, AttributeSet attrs, int defStyleAttr) { - super(context, attrs, defStyleAttr); - init(context, attrs, defStyleAttr); - } - - private void init(Context context, AttributeSet attrs, int defStyleAttr) { - iconSize = getPixel(32); - iconOuterWidth = getPixel(24); - iconOuterHeight = getPixel(32); - - bottomSpacing = getResources().getDimensionPixelSize(R.dimen.default_edittext_components_spacing); - bottomEllipsisSize = getResources().getDimensionPixelSize(R.dimen.default_bottom_ellipsis_height); - - // default baseColor is black - int defaultBaseColor = Color.BLACK; - - TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.MaterialEditText, defStyleAttr, 0); - textColorStateList = ResUtils.getColorStateListAttrRes(context, typedArray, R.styleable.MaterialEditText_met_textColor); - textColorHintStateList = ResUtils.getColorStateListAttrRes(context, typedArray, R.styleable.MaterialEditText_met_textColorHint); - baseColor = typedArray.getColor(R.styleable.MaterialEditText_met_baseColor, defaultBaseColor); - - primaryColor = typedArray.getColor(R.styleable.MaterialEditText_met_primaryColor, ThemeUtils.resolveColor(getContext(), R.attr.colorPrimary, baseColor)); - setFloatingLabelInternal(typedArray.getInt(R.styleable.MaterialEditText_met_floatingLabel, 0)); - errorColor = typedArray.getColor(R.styleable.MaterialEditText_met_errorColor, ThemeUtils.resolveColor(getContext(), R.attr.xui_config_color_error_text)); - - boolean allowEmpty = typedArray.getBoolean(R.styleable.MaterialEditText_met_allowEmpty, true); - if (!allowEmpty) { - String errorEmpty = typedArray.getString(R.styleable.MaterialEditText_met_errorEmpty); - if (!TextUtils.isEmpty(errorEmpty)) { - validators.add(new NotAllowEmptyValidator(errorEmpty)); - } else { - validators.add(new NotAllowEmptyValidator(ResUtils.getString(context, R.string.xui_met_not_allow_empty))); - } - } - minCharacters = typedArray.getInt(R.styleable.MaterialEditText_met_minCharacters, 0); - maxCharacters = typedArray.getInt(R.styleable.MaterialEditText_met_maxCharacters, 0); - singleLineEllipsis = typedArray.getBoolean(R.styleable.MaterialEditText_met_singleLineEllipsis, false); - helperText = typedArray.getString(R.styleable.MaterialEditText_met_helperText); - helperTextColor = typedArray.getColor(R.styleable.MaterialEditText_met_helperTextColor, -1); - minBottomTextLines = typedArray.getInt(R.styleable.MaterialEditText_met_minBottomTextLines, 0); - String fontPathForAccent = typedArray.getString(R.styleable.MaterialEditText_met_accentTypeface); - if (fontPathForAccent != null) { - accentTypeface = XUI.getDefaultTypeface(fontPathForAccent); - textPaint.setTypeface(accentTypeface); - } - String fontPathForView = typedArray.getString(R.styleable.MaterialEditText_met_typeface); - if (fontPathForView != null) { - Typeface typeface = XUI.getDefaultTypeface(fontPathForView); - setTypeface(typeface); - } - floatingLabelText = typedArray.getString(R.styleable.MaterialEditText_met_floatingLabelText); - if (floatingLabelText == null) { - floatingLabelText = getHint(); - } - floatingLabelPadding = typedArray.getDimensionPixelSize(R.styleable.MaterialEditText_met_floatingLabelPadding, bottomSpacing); - floatingLabelTextSize = typedArray.getDimensionPixelSize(R.styleable.MaterialEditText_met_floatingLabelTextSize, getResources().getDimensionPixelSize(R.dimen.default_floating_label_text_size)); - floatingLabelTextColor = typedArray.getColor(R.styleable.MaterialEditText_met_floatingLabelTextColor, -1); - floatingLabelAnimating = typedArray.getBoolean(R.styleable.MaterialEditText_met_floatingLabelAnimating, true); - bottomTextSize = typedArray.getDimensionPixelSize(R.styleable.MaterialEditText_met_bottomTextSize, getResources().getDimensionPixelSize(R.dimen.default_bottom_text_size)); - hideUnderline = typedArray.getBoolean(R.styleable.MaterialEditText_met_hideUnderline, false); - underlineColor = typedArray.getColor(R.styleable.MaterialEditText_met_underlineColor, -1); - underlineHeight = typedArray.getDimensionPixelSize(R.styleable.MaterialEditText_met_underlineHeight, getPixel(1)); - underlineHeightFocused = typedArray.getDimensionPixelSize(R.styleable.MaterialEditText_met_underlineHeightFocused, getPixel(2)); - autoValidate = typedArray.getBoolean(R.styleable.MaterialEditText_met_autoValidate, false); - iconLeftBitmaps = generateIconBitmaps(typedArray.getResourceId(R.styleable.MaterialEditText_met_iconLeft, -1)); - iconRightBitmaps = generateIconBitmaps(typedArray.getResourceId(R.styleable.MaterialEditText_met_iconRight, -1)); - - showClearButton = typedArray.getBoolean(R.styleable.MaterialEditText_met_clearButton, false); - clearButtonBitmaps = generateIconBitmaps(DrawableUtils.getBitmapByDrawableId(getContext(), R.drawable.xui_ic_default_clear_btn)); - showPasswordButton = typedArray.getBoolean(R.styleable.MaterialEditText_met_passWordButton, false); - boolean isAsteriskStyle = typedArray.getBoolean(R.styleable.MaterialEditText_met_isAsteriskStyle, false); - if (isAsteriskStyle) { - mTransformationMethod = AsteriskPasswordTransformationMethod.getInstance(); - } else { - mTransformationMethod = PasswordTransformationMethod.getInstance(); - } - if (showPasswordButton) { - handleSwitchPasswordInputVisibility(); - } - - showPwIconBitmaps = generateIconBitmaps(DrawableUtils.getBitmapByDrawableId(getContext(), R.drawable.pet_icon_visibility_24dp)); - hidePwIconBitmaps = generateIconBitmaps(DrawableUtils.getBitmapByDrawableId(getContext(), R.drawable.pet_icon_visibility_off_24dp)); - - String regexp = typedArray.getString(R.styleable.MaterialEditText_met_regexp); - if (!TextUtils.isEmpty(regexp)) { - String errorMessage = typedArray.getString(R.styleable.MaterialEditText_met_errorMessage); - if (!TextUtils.isEmpty(errorMessage)) { - validators.add(new RegexpValidator(errorMessage, regexp)); - } else { - validators.add(new RegexpValidator(ResUtils.getString(context, R.string.xui_met_input_error), regexp)); - } - } - - iconPadding = typedArray.getDimensionPixelSize(R.styleable.MaterialEditText_met_iconPadding, getPixel(8)); - floatingLabelAlwaysShown = typedArray.getBoolean(R.styleable.MaterialEditText_met_floatingLabelAlwaysShown, false); - helperTextAlwaysShown = typedArray.getBoolean(R.styleable.MaterialEditText_met_helperTextAlwaysShown, false); - validateOnFocusLost = typedArray.getBoolean(R.styleable.MaterialEditText_met_validateOnFocusLost, false); - checkCharactersCountAtBeginning = typedArray.getBoolean(R.styleable.MaterialEditText_met_checkCharactersCountAtBeginning, true); - typedArray.recycle(); - - int[] paddings = new int[]{ - android.R.attr.padding, // 0 - android.R.attr.paddingLeft, // 1 - android.R.attr.paddingTop, // 2 - android.R.attr.paddingRight, // 3 - android.R.attr.paddingBottom // 4 - }; - TypedArray paddingsTypedArray = context.obtainStyledAttributes(attrs, paddings); - int padding = paddingsTypedArray.getDimensionPixelSize(0, 0); - innerPaddingLeft = paddingsTypedArray.getDimensionPixelSize(1, padding); - innerPaddingTop = paddingsTypedArray.getDimensionPixelSize(2, padding); - innerPaddingRight = paddingsTypedArray.getDimensionPixelSize(3, padding); - innerPaddingBottom = paddingsTypedArray.getDimensionPixelSize(4, padding); - paddingsTypedArray.recycle(); - - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) { - setBackground(null); - } else { - setBackgroundDrawable(null); - } - if (singleLineEllipsis) { - TransformationMethod transformationMethod = getTransformationMethod(); - setSingleLine(); - setTransformationMethod(transformationMethod); - } - initMinBottomLines(); - initPadding(); - initText(); - initFloatingLabel(); - initTextWatcher(); - checkCharactersCount(); - } - - private void initText() { - if (!TextUtils.isEmpty(getText())) { - CharSequence text = getText(); - setText(null); - resetHintTextColor(); - setText(text); - setSelection(text != null ? text.length() : 0); - floatingLabelFraction = 1; - floatingLabelShown = true; - } else { - resetHintTextColor(); - } - resetTextColor(); - } - - private void initTextWatcher() { - addTextChangedListener(new TextWatcher() { - @Override - public void beforeTextChanged(CharSequence s, int start, int count, int after) { - } - - @Override - public void onTextChanged(CharSequence s, int start, int before, int count) { - } - - @Override - public void afterTextChanged(Editable s) { - checkCharactersCount(); - if (autoValidate) { - validate(); - } else { - setError(null); - } - postInvalidate(); - } - }); - } - - public MaterialEditText setIconLeft(@DrawableRes int res) { - iconLeftBitmaps = generateIconBitmaps(res); - initPadding(); - return this; - } - - public MaterialEditText setIconLeft(Drawable drawable) { - iconLeftBitmaps = generateIconBitmaps(drawable); - initPadding(); - return this; - } - - public MaterialEditText setIconLeft(Bitmap bitmap) { - iconLeftBitmaps = generateIconBitmaps(bitmap); - initPadding(); - return this; - } - - public MaterialEditText setIconRight(@DrawableRes int res) { - iconRightBitmaps = generateIconBitmaps(res); - initPadding(); - return this; - } - - public MaterialEditText setIconRight(Drawable drawable) { - iconRightBitmaps = generateIconBitmaps(drawable); - initPadding(); - return this; - } - - public MaterialEditText setIconRight(Bitmap bitmap) { - iconRightBitmaps = generateIconBitmaps(bitmap); - initPadding(); - return this; - } - - public boolean isShowClearButton() { - return showClearButton; - } - - public boolean isShowPasswordButton() { - return showPasswordButton; - } - - public MaterialEditText setShowClearButton(boolean show) { - showClearButton = show; - correctPaddings(); - return this; - } - - /** - * 设置密码输入框的样式 - * - * @param transformationMethod - * @return - */ - public MaterialEditText setPasswordTransformationMethod(PasswordTransformationMethod transformationMethod) { - mTransformationMethod = transformationMethod; - return this; - } - - private Bitmap[] generateIconBitmaps(@DrawableRes int origin) { - if (origin == -1) { - return null; - } - BitmapFactory.Options options = new BitmapFactory.Options(); - options.inJustDecodeBounds = true; - int size = Math.max(options.outWidth, options.outHeight); - options.inSampleSize = size > iconSize ? size / iconSize : 1; - options.inJustDecodeBounds = false; - return generateIconBitmaps(BitmapFactory.decodeResource(getResources(), origin, options)); - } - - private Bitmap[] generateIconBitmaps(Drawable drawable) { - if (drawable == null) { - return null; - } - Bitmap bitmap = Bitmap.createBitmap(drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight(), Bitmap.Config.ARGB_8888); - Canvas canvas = new Canvas(bitmap); - drawable.setBounds(0, 0, canvas.getWidth(), canvas.getHeight()); - drawable.draw(canvas); - return generateIconBitmaps(Bitmap.createScaledBitmap(bitmap, iconSize, iconSize, false)); - } - - private Bitmap[] generateIconBitmaps(Bitmap origin) { - if (origin == null) { - return null; - } - Bitmap[] iconBitmaps = new Bitmap[4]; - origin = scaleIcon(origin); - iconBitmaps[0] = origin.copy(Bitmap.Config.ARGB_8888, true); - Canvas canvas = new Canvas(iconBitmaps[0]); - canvas.drawColor(baseColor & 0x00ffffff | (Utils.isLight(baseColor) ? 0xff000000 : 0x8a000000), PorterDuff.Mode.SRC_IN); - iconBitmaps[1] = origin.copy(Bitmap.Config.ARGB_8888, true); - canvas = new Canvas(iconBitmaps[1]); - canvas.drawColor(primaryColor, PorterDuff.Mode.SRC_IN); - iconBitmaps[2] = origin.copy(Bitmap.Config.ARGB_8888, true); - canvas = new Canvas(iconBitmaps[2]); - canvas.drawColor(baseColor & 0x00ffffff | (Utils.isLight(baseColor) ? 0x4c000000 : 0x42000000), PorterDuff.Mode.SRC_IN); - iconBitmaps[3] = origin.copy(Bitmap.Config.ARGB_8888, true); - canvas = new Canvas(iconBitmaps[3]); - canvas.drawColor(errorColor, PorterDuff.Mode.SRC_IN); - return iconBitmaps; - } - - private Bitmap scaleIcon(Bitmap origin) { - int width = origin.getWidth(); - int height = origin.getHeight(); - int size = Math.max(width, height); - if (size == iconSize) { - return origin; - } else if (size > iconSize) { - int scaledWidth; - int scaledHeight; - if (width > iconSize) { - scaledWidth = iconSize; - scaledHeight = (int) (iconSize * ((float) height / width)); - } else { - scaledHeight = iconSize; - scaledWidth = (int) (iconSize * ((float) width / height)); - } - return Bitmap.createScaledBitmap(origin, scaledWidth, scaledHeight, false); - } else { - return origin; - } - } - - public float getFloatingLabelFraction() { - return floatingLabelFraction; - } - - public MaterialEditText setFloatingLabelFraction(float floatingLabelFraction) { - this.floatingLabelFraction = floatingLabelFraction; - invalidate(); - return this; - } - - public float getFocusFraction() { - return focusFraction; - } - - public MaterialEditText setFocusFraction(float focusFraction) { - this.focusFraction = focusFraction; - invalidate(); - return this; - } - - public float getCurrentBottomLines() { - return currentBottomLines; - } - - public MaterialEditText setCurrentBottomLines(float currentBottomLines) { - this.currentBottomLines = currentBottomLines; - initPadding(); - return this; - } - - public boolean isFloatingLabelAlwaysShown() { - return floatingLabelAlwaysShown; - } - - public MaterialEditText setFloatingLabelAlwaysShown(boolean floatingLabelAlwaysShown) { - this.floatingLabelAlwaysShown = floatingLabelAlwaysShown; - invalidate(); - return this; - } - - public boolean isHelperTextAlwaysShown() { - return helperTextAlwaysShown; - } - - public MaterialEditText setHelperTextAlwaysShown(boolean helperTextAlwaysShown) { - this.helperTextAlwaysShown = helperTextAlwaysShown; - invalidate(); - return this; - } - - @Nullable - public Typeface getAccentTypeface() { - return accentTypeface; - } - - /** - * Set typeface used for the accent texts (floating label, error/helper text, character counter, etc.) - */ - public MaterialEditText setAccentTypeface(Typeface accentTypeface) { - this.accentTypeface = accentTypeface; - this.textPaint.setTypeface(accentTypeface); - postInvalidate(); - return this; - } - - public boolean isHideUnderline() { - return hideUnderline; - } - - /** - * Set whether or not to hide the underline (shown by default). - *

- * The positions of text below will be adjusted accordingly (error/helper text, character counter, ellipses, etc.) - *

- * NOTE: You probably don't want to hide this if you have any subtext features of this enabled, as it can look weird to not have a dividing line between them. - */ - public MaterialEditText setHideUnderline(boolean hideUnderline) { - this.hideUnderline = hideUnderline; - initPadding(); - postInvalidate(); - return this; - } - - /** - * get the color of the underline for normal state - */ - public int getUnderlineColor() { - return underlineColor; - } - - /** - * Set the color of the underline for normal state - * - * @param color - */ - public MaterialEditText setUnderlineColor(int color) { - this.underlineColor = color; - postInvalidate(); - return this; - } - - public CharSequence getFloatingLabelText() { - return floatingLabelText; - } - - /** - * Set the floating label text. - *

- * Pass null to force fallback to use hint's value. - * - * @param floatingLabelText - */ - public MaterialEditText setFloatingLabelText(@Nullable CharSequence floatingLabelText) { - this.floatingLabelText = floatingLabelText == null ? getHint() : floatingLabelText; - postInvalidate(); - return this; - } - - public int getFloatingLabelTextSize() { - return floatingLabelTextSize; - } - - public MaterialEditText setFloatingLabelTextSize(int size) { - floatingLabelTextSize = size; - initPadding(); - return this; - } - - public int getFloatingLabelTextColor() { - return floatingLabelTextColor; - } - - public MaterialEditText setFloatingLabelTextColor(int color) { - this.floatingLabelTextColor = color; - postInvalidate(); - return this; - } - - public int getBottomTextSize() { - return bottomTextSize; - } - - public void setBottomTextSize(int size) { - bottomTextSize = size; - initPadding(); - } - - private int getPixel(int dp) { - return DensityUtils.dp2px(getContext(), dp); - } - - private void initPadding() { - extraPaddingTop = floatingLabelEnabled ? floatingLabelTextSize + floatingLabelPadding : floatingLabelPadding; - textPaint.setTextSize(bottomTextSize); - Paint.FontMetrics textMetrics = textPaint.getFontMetrics(); - extraPaddingBottom = (int) ((textMetrics.descent - textMetrics.ascent) * currentBottomLines) + (hideUnderline ? bottomSpacing : bottomSpacing * 2); - extraPaddingLeft = getStartIcon() == null ? 0 : (iconOuterWidth + iconPadding); - extraPaddingRight = getEndIcon() == null ? 0 : (iconOuterWidth + iconPadding); - correctPaddings(); - } - - /** - * calculate {@link #minBottomLines} - */ - private void initMinBottomLines() { - boolean extendBottom = minCharacters > 0 || maxCharacters > 0 || singleLineEllipsis || tempErrorText != null || helperText != null; - currentBottomLines = minBottomLines = minBottomTextLines > 0 ? minBottomTextLines : extendBottom ? 1 : 0; - } - - /** - * use {@link #setPaddings(int, int, int, int)} instead, or the paddingTop and the paddingBottom may be set incorrectly. - */ - @Deprecated - @Override - public final void setPadding(int left, int top, int right, int bottom) { - super.setPadding(left, top, right, bottom); - } - - /** - * Use this method instead of {@link #setPadding(int, int, int, int)} to automatically set the paddingTop and the paddingBottom correctly. - */ - public MaterialEditText setPaddings(int left, int top, int right, int bottom) { - innerPaddingTop = top; - innerPaddingBottom = bottom; - innerPaddingLeft = left; - innerPaddingRight = right; - correctPaddings(); - return this; - } - - /** - * Set paddings to the correct values - */ - private void correctPaddings() { - int buttonsWidthLeft = 0, buttonsWidthRight = 0; - int buttonsWidth = iconOuterWidth * getButtonsCount(); - if (isRTL()) { - buttonsWidthLeft = buttonsWidth; - } else { - buttonsWidthRight = buttonsWidth; - } - super.setPaddingRelative(innerPaddingLeft + extraPaddingLeft + buttonsWidthLeft, innerPaddingTop + extraPaddingTop, innerPaddingRight + extraPaddingRight + buttonsWidthRight, innerPaddingBottom + extraPaddingBottom); - } - - private int getButtonsCount() { - return isShowClearButton() || isShowPasswordButton() ? 1 : 0; - } - - @Override - protected void onAttachedToWindow() { - super.onAttachedToWindow(); - if (!firstShown) { - firstShown = true; - } - } - - @Override - protected void onLayout(boolean changed, int left, int top, int right, int bottom) { - super.onLayout(changed, left, top, right, bottom); - if (changed) { - adjustBottomLines(); - } - } - - /** - * @return True, if adjustments were made that require the view to be invalidated. - */ - private boolean adjustBottomLines() { - // Bail out if we have a zero width; lines will be adjusted during next layout. - if (getWidth() == 0) { - return false; - } - int destBottomLines; - textPaint.setTextSize(bottomTextSize); - if (tempErrorText != null || helperText != null) { - Layout.Alignment alignment = (getGravity() & Gravity.END) == Gravity.END || isRTL() ? - Layout.Alignment.ALIGN_OPPOSITE : (getGravity() & Gravity.START) == Gravity.START ? - Layout.Alignment.ALIGN_NORMAL : Layout.Alignment.ALIGN_CENTER; - textLayout = new StaticLayout(tempErrorText != null ? tempErrorText : helperText, textPaint, getWidth() - getBottomTextLeftOffset() - getBottomTextRightOffset() - getPaddingLeft() - getPaddingRight(), alignment, 1.0f, 0.0f, true); - destBottomLines = Math.max(textLayout.getLineCount(), minBottomTextLines); - } else { - destBottomLines = minBottomLines; - } - if (bottomLines != destBottomLines) { - getBottomLinesAnimator(destBottomLines).start(); - } - bottomLines = destBottomLines; - return true; - } - - /** - * get inner top padding, not the real paddingTop - */ - public int getInnerPaddingTop() { - return innerPaddingTop; - } - - /** - * get inner bottom padding, not the real paddingBottom - */ - public int getInnerPaddingBottom() { - return innerPaddingBottom; - } - - /** - * get inner left padding, not the real paddingLeft - */ - public int getInnerPaddingLeft() { - return innerPaddingLeft; - } - - /** - * get inner right padding, not the real paddingRight - */ - public int getInnerPaddingRight() { - return innerPaddingRight; - } - - private void initFloatingLabel() { - // observe the text changing - addTextChangedListener(new TextWatcher() { - @Override - public void beforeTextChanged(CharSequence s, int start, int count, int after) { - } - - @Override - public void onTextChanged(CharSequence s, int start, int before, int count) { - } - - @Override - public void afterTextChanged(Editable s) { - if (floatingLabelEnabled) { - if (s.length() == 0) { - if (floatingLabelShown) { - floatingLabelShown = false; - getLabelAnimator().reverse(); - } - } else if (!floatingLabelShown) { - floatingLabelShown = true; - getLabelAnimator().start(); - } - } - } - }); - // observe the focus state to animate the floating label's text color appropriately - innerFocusChangeListener = new OnFocusChangeListener() { - @Override - public void onFocusChange(View v, boolean hasFocus) { - if (floatingLabelEnabled && highlightFloatingLabel) { - if (hasFocus) { - getLabelFocusAnimator().start(); - } else { - getLabelFocusAnimator().reverse(); - } - } - if (validateOnFocusLost && !hasFocus) { - validate(); - } - if (outerFocusChangeListener != null) { - outerFocusChangeListener.onFocusChange(v, hasFocus); - } - } - }; - super.setOnFocusChangeListener(innerFocusChangeListener); - } - - public boolean isValidateOnFocusLost() { - return validateOnFocusLost; - } - - public MaterialEditText setValidateOnFocusLost(boolean validate) { - this.validateOnFocusLost = validate; - return this; - } - - public MaterialEditText setBaseColor(int color) { - if (baseColor != color) { - baseColor = color; - } - initText(); - postInvalidate(); - return this; - } - - public MaterialEditText setPrimaryColor(int color) { - primaryColor = color; - postInvalidate(); - return this; - } - - /** - * Same function as {@link #setTextColor(int)}. (Directly overriding the built-in one could cause some error, so use this method instead.) - */ - public MaterialEditText setMetTextColor(int color) { - textColorStateList = ColorStateList.valueOf(color); - resetTextColor(); - return this; - } - - /** - * Same function as {@link #setTextColor(ColorStateList)}. (Directly overriding the built-in one could cause some error, so use this method instead.) - */ - public MaterialEditText setMetTextColor(ColorStateList colors) { - textColorStateList = colors; - resetTextColor(); - return this; - } - - private void resetTextColor() { - if (textColorStateList == null) { - textColorStateList = new ColorStateList(new int[][]{new int[]{android.R.attr.state_enabled}, EMPTY_STATE_SET}, new int[]{baseColor & 0x00ffffff | 0xdf000000, baseColor & 0x00ffffff | 0x44000000}); - setTextColor(textColorStateList); - } else { - setTextColor(textColorStateList); - } - } - - /** - * Same function as {@link #setHintTextColor(int)}. (The built-in one is a final method that can't be overridden, so use this method instead.) - */ - public MaterialEditText setMetHintTextColor(int color) { - textColorHintStateList = ColorStateList.valueOf(color); - resetHintTextColor(); - return this; - } - - /** - * Same function as {@link #setHintTextColor(ColorStateList)}. (The built-in one is a final method that can't be overridden, so use this method instead.) - */ - public MaterialEditText setMetHintTextColor(ColorStateList colors) { - textColorHintStateList = colors; - resetHintTextColor(); - return this; - } - - private void resetHintTextColor() { - if (textColorHintStateList == null) { - setHintTextColor(baseColor & 0x00ffffff | 0x44000000); - } else { - setHintTextColor(textColorHintStateList); - } - } - - private void setFloatingLabelInternal(int mode) { - switch (mode) { - case FLOATING_LABEL_NORMAL: - floatingLabelEnabled = true; - highlightFloatingLabel = false; - break; - case FLOATING_LABEL_HIGHLIGHT: - floatingLabelEnabled = true; - highlightFloatingLabel = true; - break; - default: - floatingLabelEnabled = false; - highlightFloatingLabel = false; - break; - } - } - - public MaterialEditText setFloatingLabel(@FloatingLabelType int mode) { - setFloatingLabelInternal(mode); - initPadding(); - return this; - } - - public int getFloatingLabelPadding() { - return floatingLabelPadding; - } - - public MaterialEditText setFloatingLabelPadding(int padding) { - floatingLabelPadding = padding; - postInvalidate(); - return this; - } - - public boolean isFloatingLabelAnimating() { - return floatingLabelAnimating; - } - - public MaterialEditText setFloatingLabelAnimating(boolean animating) { - floatingLabelAnimating = animating; - return this; - } - - public MaterialEditText setSingleLineEllipsis() { - return setSingleLineEllipsis(true); - } - - public MaterialEditText setSingleLineEllipsis(boolean enabled) { - singleLineEllipsis = enabled; - initMinBottomLines(); - initPadding(); - postInvalidate(); - return this; - } - - public int getMaxCharacters() { - return maxCharacters; - } - - public MaterialEditText setMaxCharacters(int max) { - maxCharacters = max; - initMinBottomLines(); - initPadding(); - postInvalidate(); - return this; - } - - public int getMinCharacters() { - return minCharacters; - } - - public MaterialEditText setMinCharacters(int min) { - minCharacters = min; - initMinBottomLines(); - initPadding(); - postInvalidate(); - return this; - } - - public int getMinBottomTextLines() { - return minBottomTextLines; - } - - public MaterialEditText setMinBottomTextLines(int lines) { - minBottomTextLines = lines; - initMinBottomLines(); - initPadding(); - postInvalidate(); - return this; - } - - public boolean isAutoValidate() { - return autoValidate; - } - - public MaterialEditText setAutoValidate(boolean autoValidate) { - this.autoValidate = autoValidate; - if (autoValidate) { - validate(); - } - return this; - } - - public int getErrorColor() { - return errorColor; - } - - public MaterialEditText setErrorColor(int color) { - errorColor = color; - postInvalidate(); - return this; - } - - public MaterialEditText setHelperText(CharSequence helperText) { - this.helperText = helperText == null ? null : helperText.toString(); - if (adjustBottomLines()) { - postInvalidate(); - } - return this; - } - - public String getHelperText() { - return helperText; - } - - public int getHelperTextColor() { - return helperTextColor; - } - - public MaterialEditText setHelperTextColor(int color) { - helperTextColor = color; - postInvalidate(); - return this; - } - - /** - * 设置输入框是否允许为空 - * - * @param allowEmpty - * @param errorEmpty - * @return - */ - public MaterialEditText setAllowEmpty(boolean allowEmpty, String errorEmpty) { - boolean updateError = false; - Iterator it = validators.iterator(); - while (it.hasNext()) { - METValidator item = it.next(); - if (item instanceof NotAllowEmptyValidator) { - if (allowEmpty) { - it.remove(); - } else { - if (!TextUtils.isEmpty(errorEmpty)) { - item.setErrorMessage(errorEmpty); - } else { - item.setErrorMessage(ResUtils.getString(getContext(), R.string.xui_met_not_allow_empty)); - } - updateError = true; - } - break; - } - } - if (!allowEmpty && !updateError) { - if (!TextUtils.isEmpty(errorEmpty)) { - validators.add(new NotAllowEmptyValidator(errorEmpty)); - } else { - validators.add(new NotAllowEmptyValidator(ResUtils.getString(getContext(), R.string.xui_met_not_allow_empty))); - } - } - return this; - } - - @Override - public void setError(CharSequence errorText) { - tempErrorText = errorText == null ? null : errorText.toString(); - if (adjustBottomLines()) { - postInvalidate(); - } - } - - @Override - public CharSequence getError() { - return tempErrorText; - } - - /** - * only used to draw the bottom line - */ - private boolean isInternalValid() { - return tempErrorText == null && isCharactersCountValid(); - } - - /** - * if the main text matches the regex - * - * @deprecated use the new validator interface to add your own custom validator - */ - @Deprecated - public boolean isValid(String regex) { - if (regex == null) { - return false; - } - Pattern pattern = Pattern.compile(regex); - Matcher matcher = pattern.matcher(getText()); - return matcher.matches(); - } - - /** - * check if the main text matches the regex, and set the error text if not. - * - * @return true if it matches the regex, false if not. - * @deprecated use the new validator interface to add your own custom validator - */ - @Deprecated - public boolean validate(String regex, CharSequence errorText) { - boolean isValid = isValid(regex); - if (!isValid) { - setError(errorText); - } - postInvalidate(); - return isValid; - } - - /** - * Run validation on a single validator instance - * - * @param validator Validator to check - * @return True if valid, false if not - */ - public boolean validateWith(@NonNull METValidator validator) { - CharSequence text = getText(); - boolean isValid = validator.isValid(text, text.length() == 0); - if (!isValid) { - setError(validator.getErrorMessage()); - } - postInvalidate(); - return isValid; - } - - /** - * Check all validators, sets the error text if not - *

- * NOTE: this stops at the first validator to report invalid. - * - * @return True if all validators pass, false if not - */ - public boolean validate() { - if (validators == null || validators.isEmpty()) { - return true; - } - - CharSequence text = getText(); - boolean isEmpty = TextUtils.isEmpty(text); - - boolean isValid = true; - for (METValidator validator : validators) { - //noinspection ConstantConditions - isValid = isValid && validator.isValid(text, isEmpty); - if (!isValid) { - setError(validator.getErrorMessage()); - break; - } - } - if (isValid) { - setError(null); - } - - postInvalidate(); - return isValid; - } - - public boolean hasValidators() { - return this.validators != null && !this.validators.isEmpty(); - } - - /** - * Adds a new validator to the View's list of validators - *

- * This will be checked with the others in {@link #validate()} - * - * @param validator Validator to add - * @return This instance, for easy chaining - */ - public MaterialEditText addValidator(METValidator validator) { - if (validators == null) { - this.validators = new ArrayList<>(); - } - this.validators.add(validator); - return this; - } - - public MaterialEditText clearValidators() { - if (this.validators != null) { - this.validators.clear(); - } - return this; - } - - @Nullable - public List getValidators() { - return this.validators; - } - - public MaterialEditText setLengthChecker(METLengthChecker lengthChecker) { - this.lengthChecker = lengthChecker; - return this; - } - - /** - * 清除内容 - */ - public void clear() { - if (!TextUtils.isEmpty(getText())) { - setText(null); - } - } - - /** - * 获取输入的内容 - * - * @return - */ - public String getEditValue() { - return getEditableText().toString().trim(); - } - - @Override - public void setEnabled(boolean enabled) { - super.setFocusable(enabled); - super.setFocusableInTouchMode(enabled); - super.setEnabled(enabled); - } - - /** - * 输入的内容是否为空 - * - * @return - */ - public boolean isEmpty() { - return TextUtils.isEmpty(getEditValue()); - } - - /** - * 输入的内容是否不为空 - * - * @return - */ - public boolean isNotEmpty() { - return !TextUtils.isEmpty(getEditValue()); - } - - @Override - public void setOnFocusChangeListener(OnFocusChangeListener listener) { - if (innerFocusChangeListener == null) { - super.setOnFocusChangeListener(listener); - } else { - outerFocusChangeListener = listener; - } - } - - private ObjectAnimator getLabelAnimator() { - if (labelAnimator == null) { - labelAnimator = ObjectAnimator.ofFloat(this, "floatingLabelFraction", 0f, 1f); - } - labelAnimator.setDuration(floatingLabelAnimating ? 300 : 0); - return labelAnimator; - } - - private ObjectAnimator getLabelFocusAnimator() { - if (labelFocusAnimator == null) { - labelFocusAnimator = ObjectAnimator.ofFloat(this, "focusFraction", 0f, 1f); - } - return labelFocusAnimator; - } - - private ObjectAnimator getBottomLinesAnimator(float destBottomLines) { - if (bottomLinesAnimator == null) { - bottomLinesAnimator = ObjectAnimator.ofFloat(this, "currentBottomLines", destBottomLines); - } else { - bottomLinesAnimator.cancel(); - bottomLinesAnimator.setFloatValues(destBottomLines); - } - return bottomLinesAnimator; - } - - @Override - protected void onDraw(@NonNull Canvas canvas) { - - int startX = getScrollX() + (getStartIcon() == null ? 0 : iconOuterWidth + iconPadding); - int endX = getScrollX() + (getEndIcon() == null ? getWidth() : getWidth() - iconOuterWidth - iconPadding); - int lineStartY = getScrollY() + getHeight() - getPaddingBottom(); - - // draw the icon(s) - drawIcons(canvas, startX, endX, lineStartY); - - // draw the action button - drawActionButton(canvas, startX, endX, lineStartY); - - // draw the underline - lineStartY = drawUnderline(canvas, startX, endX, lineStartY); - - textPaint.setTextSize(bottomTextSize); - Paint.FontMetrics textMetrics = textPaint.getFontMetrics(); - float relativeHeight = -textMetrics.ascent - textMetrics.descent; - float bottomTextPadding = bottomTextSize + textMetrics.ascent + textMetrics.descent; - - // draw the characters counter - if ((hasFocus() && hasCharactersCounter()) || !isCharactersCountValid()) { - textPaint.setColor(isCharactersCountValid() ? (baseColor & 0x00ffffff | 0x44000000) : errorColor); - String charactersCounterText = getCharactersCounterText(); - canvas.drawText(charactersCounterText, isRTL() ? startX : endX + getPaddingEnd() - textPaint.measureText(charactersCounterText), lineStartY + bottomSpacing + relativeHeight, textPaint); - } - - // draw the bottom text - drawBottomText(canvas, startX, endX, lineStartY, bottomTextPadding); - - // draw the floating label - drawFloatingLabel(canvas, startX, endX); - - // draw the bottom ellipsis - drawBottomEllipsis(canvas, startX, endX, lineStartY); - - // draw the original things - super.onDraw(canvas); - } - - private Bitmap[] getStartIcon() { - return isRTL() ? iconRightBitmaps : iconLeftBitmaps; - } - - private Bitmap[] getEndIcon() { - return isRTL() ? iconLeftBitmaps : iconRightBitmaps; - } - - /** - * 画图标 - * - * @param canvas - * @param startX - * @param endX - * @param lineStartY - */ - private void drawIcons(@NonNull Canvas canvas, int startX, int endX, int lineStartY) { - paint.setAlpha(255); - if (getStartIcon() != null) { - Bitmap icon = getStartIcon()[!isInternalValid() ? 3 : !isEnabled() ? 2 : hasFocus() ? 1 : 0]; - int iconLeft = startX - iconPadding - iconOuterWidth + (iconOuterWidth - icon.getWidth()) / 2; - int iconTop = lineStartY + bottomSpacing - iconOuterHeight + (iconOuterHeight - icon.getHeight()) / 2; - canvas.drawBitmap(icon, iconLeft, iconTop, paint); - } - if (getEndIcon() != null) { - Bitmap icon = getEndIcon()[!isInternalValid() ? 3 : !isEnabled() ? 2 : hasFocus() ? 1 : 0]; - int iconRight = endX + iconPadding + (iconOuterWidth - icon.getWidth()) / 2; - int iconTop = lineStartY + bottomSpacing - iconOuterHeight + (iconOuterHeight - icon.getHeight()) / 2; - canvas.drawBitmap(icon, iconRight, iconTop, paint); - } - } - - /** - * 画清除按钮 - * - * @param canvas - * @param startX - * @param endX - * @param lineStartY - */ - private void drawActionButton(@NonNull Canvas canvas, int startX, int endX, int lineStartY) { - if (hasFocus() && isEnabled() && !TextUtils.isEmpty(getText()) && (showClearButton || showPasswordButton)) { - paint.setAlpha(255); - int buttonLeft = isRTL() ? startX : endX - iconOuterWidth; - Bitmap actionButtonBitmap; - if (showClearButton) { - actionButtonBitmap = clearButtonBitmaps[0]; - } else { - actionButtonBitmap = passwordVisible ? showPwIconBitmaps[0] : hidePwIconBitmaps[0]; - } - int iconTop = lineStartY + bottomSpacing - iconOuterHeight + (iconOuterHeight - actionButtonBitmap.getHeight()) / 2; - canvas.drawBitmap(actionButtonBitmap, buttonLeft, iconTop, paint); - } - } - - /** - * 画下划线 - * - * @param canvas - * @param startX - * @param endX - * @param lineStartY - * @return - */ - private int drawUnderline(@NonNull Canvas canvas, int startX, int endX, int lineStartY) { - if (!hideUnderline) { - lineStartY += bottomSpacing; - if (!isInternalValid()) { // not valid - paint.setColor(errorColor); - canvas.drawRect(startX, lineStartY, endX, lineStartY + underlineHeightFocused, paint); - } else if (!isEnabled()) { // disabled - paint.setColor(underlineColor != -1 ? underlineColor : baseColor & 0x00ffffff | 0x44000000); - float interval = getPixel(1); - for (float xOffset = 0; xOffset < getWidth(); xOffset += interval * 3) { - canvas.drawRect(startX + xOffset, lineStartY, startX + xOffset + interval, lineStartY + underlineHeight, paint); - } - } else if (hasFocus()) { // focused - paint.setColor(primaryColor); - canvas.drawRect(startX, lineStartY, endX, lineStartY + underlineHeightFocused, paint); - } else { // normal - paint.setColor(underlineColor != -1 ? underlineColor : baseColor & 0x00ffffff | 0x1E000000); - canvas.drawRect(startX, lineStartY, endX, lineStartY + underlineHeight, paint); - } - } - return lineStartY; - } - - /** - * 画底部文字 - * - * @param canvas - * @param startX - * @param endX - * @param lineStartY - * @param bottomTextPadding - */ - private void drawBottomText(@NonNull Canvas canvas, int startX, int endX, int lineStartY, float bottomTextPadding) { - if (textLayout != null) { - if (tempErrorText != null || ((helperTextAlwaysShown || hasFocus()) && !TextUtils.isEmpty(helperText))) { // error text or helper text - textPaint.setColor(tempErrorText != null ? errorColor : helperTextColor != -1 ? helperTextColor : (baseColor & 0x00ffffff | 0x44000000)); - canvas.save(); - if (isRTL()) { - canvas.translate(endX - textLayout.getWidth(), lineStartY + bottomSpacing - bottomTextPadding); - } else { - canvas.translate(startX + getBottomTextLeftOffset(), lineStartY + bottomSpacing - bottomTextPadding); - } - textLayout.draw(canvas); - canvas.restore(); - } - } - } - - private void drawFloatingLabel(@NonNull Canvas canvas, int startX, int endX) { - if (floatingLabelEnabled && !TextUtils.isEmpty(floatingLabelText)) { - textPaint.setTextSize(floatingLabelTextSize); - // calculate the text color - textPaint.setColor((Integer) focusEvaluator.evaluate(focusFraction * (isEnabled() ? 1 : 0), floatingLabelTextColor != -1 ? floatingLabelTextColor : (baseColor & 0x00ffffff | 0x44000000), primaryColor)); - - // calculate the horizontal position - float floatingLabelWidth = textPaint.measureText(floatingLabelText.toString()); - int floatingLabelStartX; - if ((getGravity() & Gravity.RIGHT) == Gravity.RIGHT || isRTL()) { - floatingLabelStartX = (int) (endX - floatingLabelWidth); - } else if ((getGravity() & Gravity.LEFT) == Gravity.LEFT) { - floatingLabelStartX = startX; - } else { - floatingLabelStartX = startX + (int) (getInnerPaddingLeft() + (getWidth() - getInnerPaddingLeft() - getInnerPaddingRight() - floatingLabelWidth) / 2); - } - - // calculate the vertical position - int distance = floatingLabelPadding; - int floatingLabelStartY = (int) (innerPaddingTop + floatingLabelTextSize + floatingLabelPadding - distance * (floatingLabelAlwaysShown ? 1 : floatingLabelFraction) + getScrollY()); - - // calculate the alpha - int alpha = ((int) ((floatingLabelAlwaysShown ? 1 : floatingLabelFraction) * 0xff * (0.74f * focusFraction * (isEnabled() ? 1 : 0) + 0.26f) * (floatingLabelTextColor != -1 ? 1 : Color.alpha(floatingLabelTextColor) / 255F))); - textPaint.setAlpha(alpha); - - // draw the floating label - canvas.drawText(floatingLabelText.toString(), floatingLabelStartX, floatingLabelStartY, textPaint); - } - } - - private void drawBottomEllipsis(@NonNull Canvas canvas, int startX, int endX, int lineStartY) { - if (hasFocus() && singleLineEllipsis && getScrollX() != 0) { - paint.setColor(isInternalValid() ? primaryColor : errorColor); - float startY = lineStartY + bottomSpacing; - int ellipsisStartX; - if (isRTL()) { - ellipsisStartX = endX; - } else { - ellipsisStartX = startX; - } - int signum = isRTL() ? -1 : 1; - canvas.drawCircle(ellipsisStartX + signum * bottomEllipsisSize / 2F, startY + bottomEllipsisSize / 2F, bottomEllipsisSize / 2F, paint); - canvas.drawCircle(ellipsisStartX + signum * bottomEllipsisSize * 5 / 2F, startY + bottomEllipsisSize / 2F, bottomEllipsisSize / 2F, paint); - canvas.drawCircle(ellipsisStartX + signum * bottomEllipsisSize * 9 / 2F, startY + bottomEllipsisSize / 2F, bottomEllipsisSize / 2F, paint); - } - } - - private boolean isRTL() { - return getLayoutDirection() == LAYOUT_DIRECTION_RTL; - } - - private int getBottomTextLeftOffset() { - return isRTL() ? getCharactersCounterWidth() : getBottomEllipsisWidth(); - } - - private int getBottomTextRightOffset() { - return isRTL() ? getBottomEllipsisWidth() : getCharactersCounterWidth(); - } - - private int getCharactersCounterWidth() { - return hasCharactersCounter() ? (int) textPaint.measureText(getCharactersCounterText()) : 0; - } - - private int getBottomEllipsisWidth() { - return singleLineEllipsis ? (bottomEllipsisSize * 5 + getPixel(4)) : 0; - } - - private void checkCharactersCount() { - if ((!firstShown && !checkCharactersCountAtBeginning) || !hasCharactersCounter()) { - charactersCountValid = true; - } else { - CharSequence text = getText(); - int count = text == null ? 0 : checkLength(text); - charactersCountValid = (count >= minCharacters && (maxCharacters <= 0 || count <= maxCharacters)); - } - } - - public boolean isCharactersCountValid() { - return charactersCountValid; - } - - private boolean hasCharactersCounter() { - return minCharacters > 0 || maxCharacters > 0; - } - - private String getCharactersCounterText() { - String text; - if (minCharacters <= 0) { - text = isRTL() ? maxCharacters + " / " + checkLength(getText()) : checkLength(getText()) + " / " + maxCharacters; - } else if (maxCharacters <= 0) { - text = isRTL() ? "+" + minCharacters + " / " + checkLength(getText()) : checkLength(getText()) + " / " + minCharacters + "+"; - } else { - text = isRTL() ? maxCharacters + "-" + minCharacters + " / " + checkLength(getText()) : checkLength(getText()) + " / " + minCharacters + "-" + maxCharacters; - } - return text; - } - - @Override - public boolean onTouchEvent(MotionEvent event) { - if (singleLineEllipsis && getScrollX() > 0 && event.getAction() == MotionEvent.ACTION_DOWN && event.getX() < getPixel(4 * 5) && event.getY() > getHeight() - extraPaddingBottom - innerPaddingBottom && event.getY() < getHeight() - innerPaddingBottom) { - setSelection(0); - return false; - } - if (hasFocus() && (showClearButton || showPasswordButton) && isEnabled()) { - switch (event.getAction()) { - case MotionEvent.ACTION_DOWN: - if (insideActionButton(event)) { - actionButtonTouched = true; - actionButtonClicking = true; - return true; - } - case MotionEvent.ACTION_MOVE: - if (actionButtonClicking && !insideActionButton(event)) { - actionButtonClicking = false; - } - if (actionButtonTouched) { - return true; - } - break; - case MotionEvent.ACTION_UP: - if (actionButtonClicking) { - if (showClearButton) { - if (!TextUtils.isEmpty(getText())) { - setText(null); - } - } else { - togglePasswordIconVisibility(); - } - actionButtonClicking = false; - } - if (actionButtonTouched) { - actionButtonTouched = false; - return true; - } - actionButtonTouched = false; - break; - case MotionEvent.ACTION_CANCEL: - actionButtonTouched = false; - actionButtonClicking = false; - break; - default: - break; - } - } - return super.onTouchEvent(event); - } - - private boolean insideActionButton(MotionEvent event) { - float x = event.getX(); - float y = event.getY(); - int startX = getStartIcon() == null ? 0 : iconOuterWidth + iconPadding; - int endX = getEndIcon() == null ? getWidth() : getWidth() - iconOuterWidth - iconPadding; - int buttonLeft = isRTL() ? startX : endX - iconOuterWidth; - int buttonTop = getScrollY() + getHeight() - getPaddingBottom() + bottomSpacing - iconOuterHeight; - return (x >= buttonLeft && x < buttonLeft + iconOuterWidth && y >= buttonTop && y < buttonTop + iconOuterHeight); - } - - /** - * 密码显示切换 - */ - private void handleSwitchPasswordInputVisibility() { - int selectionStart = getSelectionStart(); - int selectionEnd = getSelectionEnd(); - if (passwordVisible) { - setTransformationMethod(null); - } else { - setTransformationMethod(mTransformationMethod); - - } - setSelection(selectionStart, selectionEnd); - } - - /** - * 密码显示切换 - */ - private void togglePasswordIconVisibility() { - passwordVisible = !passwordVisible; - handleSwitchPasswordInputVisibility(); - } - - private int checkLength(CharSequence text) { - if (lengthChecker == null) { - return text.length(); - } - return lengthChecker.getLength(text); - } - - @Override - public void setTypeface(Typeface typeface) { - super.setTypeface(typeface); - if (textPaint != null) { - textPaint.setTypeface(typeface); - } - } -} \ No newline at end of file diff --git a/app/src/main/java/com/project/survey/widget/edittext/materialedittext/validation/METLengthChecker.java b/app/src/main/java/com/project/survey/widget/edittext/materialedittext/validation/METLengthChecker.java deleted file mode 100644 index 6ac786f..0000000 --- a/app/src/main/java/com/project/survey/widget/edittext/materialedittext/validation/METLengthChecker.java +++ /dev/null @@ -1,13 +0,0 @@ -package com.project.survey.widget.edittext.materialedittext.validation; - -/** - * 长度验证 - * - * @author xuexiang - * @since 2018/11/26 下午5:06 - */ -public abstract class METLengthChecker { - - public abstract int getLength(CharSequence text); - -} diff --git a/app/src/main/java/com/project/survey/widget/edittext/materialedittext/validation/METValidator.java b/app/src/main/java/com/project/survey/widget/edittext/materialedittext/validation/METValidator.java deleted file mode 100644 index af86cd5..0000000 --- a/app/src/main/java/com/project/survey/widget/edittext/materialedittext/validation/METValidator.java +++ /dev/null @@ -1,43 +0,0 @@ -package com.project.survey.widget.edittext.materialedittext.validation; - -import androidx.annotation.NonNull; - -/** - * 自定义校验器 - * - * @author xuexiang - * @since 2018/11/26 下午5:06 - */ -public abstract class METValidator { - - /** - * Error message that the view will display if validation fails. - *

- * This is protected, so you can change this dynamically in your {@link #isValid(CharSequence, boolean)} - * implementation. If necessary, you can also interact with this via its getter and setter. - */ - protected String errorMessage; - - public METValidator(@NonNull String errorMessage) { - this.errorMessage = errorMessage; - } - - public void setErrorMessage(@NonNull String errorMessage) { - this.errorMessage = errorMessage; - } - - @NonNull - public String getErrorMessage() { - return this.errorMessage; - } - - /** - * Abstract method to implement your own validation checking. - * - * @param text The CharSequence representation of the text in the EditText field. Cannot be null, but may be empty. - * @param isEmpty Boolean indicating whether or not the text param is empty - * @return True if valid, false if not - */ - public abstract boolean isValid(@NonNull CharSequence text, boolean isEmpty); - -} diff --git a/app/src/main/java/com/project/survey/widget/edittext/materialedittext/validation/NotAllowEmptyValidator.java b/app/src/main/java/com/project/survey/widget/edittext/materialedittext/validation/NotAllowEmptyValidator.java deleted file mode 100644 index f3614dd..0000000 --- a/app/src/main/java/com/project/survey/widget/edittext/materialedittext/validation/NotAllowEmptyValidator.java +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Copyright (C) 2019 xuexiangjys(xuexiangjys@163.com) - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.project.survey.widget.edittext.materialedittext.validation; - -import androidx.annotation.NonNull; - -/** - * 非空检验 - * - * @author xuexiang - * @since 2019/5/14 10:27 - */ -public class NotAllowEmptyValidator extends METValidator { - - public NotAllowEmptyValidator(@NonNull String errorMessage) { - super(errorMessage); - } - - @Override - public boolean isValid(@NonNull CharSequence text, boolean isEmpty) { - return !isEmpty; - } -} diff --git a/app/src/main/java/com/project/survey/widget/edittext/materialedittext/validation/RegexpValidator.java b/app/src/main/java/com/project/survey/widget/edittext/materialedittext/validation/RegexpValidator.java deleted file mode 100644 index be787b5..0000000 --- a/app/src/main/java/com/project/survey/widget/edittext/materialedittext/validation/RegexpValidator.java +++ /dev/null @@ -1,31 +0,0 @@ -package com.project.survey.widget.edittext.materialedittext.validation; - -import androidx.annotation.NonNull; - -import java.util.regex.Pattern; - -/** - * 正则表达式验证 - * - * @author xuexiang - * @since 2018/11/26 下午5:06 - */ -public class RegexpValidator extends METValidator { - - private Pattern pattern; - - public RegexpValidator(@NonNull String errorMessage, @NonNull String regex) { - super(errorMessage); - pattern = Pattern.compile(regex); - } - - public RegexpValidator(@NonNull String errorMessage, @NonNull Pattern pattern) { - super(errorMessage); - this.pattern = pattern; - } - - @Override - public boolean isValid(@NonNull CharSequence text, boolean isEmpty) { - return pattern.matcher(text).matches(); - } -} diff --git a/app/src/main/res/color/text_color_enable_sc.xml b/app/src/main/res/color/text_color_enable_sc.xml new file mode 100644 index 0000000..ef0f05b --- /dev/null +++ b/app/src/main/res/color/text_color_enable_sc.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_btn_eanble_sc.xml b/app/src/main/res/drawable/bg_btn_eanble_sc.xml new file mode 100644 index 0000000..08a5711 --- /dev/null +++ b/app/src/main/res/drawable/bg_btn_eanble_sc.xml @@ -0,0 +1,7 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_btn_enable.xml b/app/src/main/res/drawable/bg_btn_enable.xml new file mode 100644 index 0000000..69157e5 --- /dev/null +++ b/app/src/main/res/drawable/bg_btn_enable.xml @@ -0,0 +1,6 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_btn_enable_not.xml b/app/src/main/res/drawable/bg_btn_enable_not.xml new file mode 100644 index 0000000..651d8f7 --- /dev/null +++ b/app/src/main/res/drawable/bg_btn_enable_not.xml @@ -0,0 +1,6 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_forget_pwd.xml b/app/src/main/res/layout/activity_forget_pwd.xml new file mode 100644 index 0000000..e6d65d4 --- /dev/null +++ b/app/src/main/res/layout/activity_forget_pwd.xml @@ -0,0 +1,67 @@ + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_forget_pwd_input_code.xml b/app/src/main/res/layout/activity_forget_pwd_input_code.xml new file mode 100644 index 0000000..4b23221 --- /dev/null +++ b/app/src/main/res/layout/activity_forget_pwd_input_code.xml @@ -0,0 +1,40 @@ + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_login.xml b/app/src/main/res/layout/activity_login.xml index be99bca..527f4e9 100644 --- a/app/src/main/res/layout/activity_login.xml +++ b/app/src/main/res/layout/activity_login.xml @@ -59,36 +59,9 @@ android:textColor="@color/c_727778" android:textSize="@dimen/sw_11sp" /> - - - - - - - - - - - - + diff --git a/app/src/main/res/layout/activity_set_new_pwd.xml b/app/src/main/res/layout/activity_set_new_pwd.xml new file mode 100644 index 0000000..531c108 --- /dev/null +++ b/app/src/main/res/layout/activity_set_new_pwd.xml @@ -0,0 +1,59 @@ + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/item_input_pwd.xml b/app/src/main/res/layout/item_input_pwd.xml new file mode 100644 index 0000000..b4ef93d --- /dev/null +++ b/app/src/main/res/layout/item_input_pwd.xml @@ -0,0 +1,31 @@ + + + + + + + + + + + + + diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index a5de7c3..f3131dd 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -39,7 +39,13 @@ 输入不符合要求! 输入不能为空! 请输入验证码 - 验证码已发送至%1$s的手机,如您已更换手机,请联系管理员。 - + 验证码已发送至%1$s的手机,如您已更换手机,请联系管理员。 + 验证码已发送至%1$s的手机,请输入6位数验证码。 + 身份验证 + 请输入账号。 + 发送验证码 + 设置新密码 + 请输入新的密码。 + 确认密码 \ No newline at end of file