add ClearableEditText, add new reg

androidx
Ztiany 5 years ago
parent 8261c7af25
commit 115715f2f5
  1. 19
      lib_base/src/main/java/com/android/base/utils/common/Strings.kt
  2. 290
      lib_base/src/main/java/com/android/base/widget/text/ClearableEditText.java
  3. BIN
      lib_base/src/main/res/drawable-xxhdpi/base_icon_clear.png
  4. BIN
      lib_base/src/main/res/drawable-xxhdpi/base_icon_password_close.png
  5. BIN
      lib_base/src/main/res/drawable-xxhdpi/base_icon_password_open.png
  6. 128
      lib_base/src/main/res/values/base_attrs.xml

@ -2,10 +2,11 @@
package com.android.base.utils.common
import java.util.regex.Pattern
private const val CHINA_PHONE_REG = "^1\\d{10}$"
private const val ID_CARD_REG = "[1-9]\\d{13,16}[a-zA-Z0-9]{1}"
private const val ID_CARD_REG = "(^[1-9]\\d{5}(18|19|20)\\d{2}((0[1-9])|(10|11|12))(([0-2][1-9])|10|20|30|31)\\d{3}[0-9Xx]$)|(^[1-9]\\d{5}\\d{2}((0[1-9])|(10|11|12))(([0-2][1-9])|10|20|30|31)\\d{3}$)"
private const val EMAIL_REG = "\\w+([-+.]\\w+)*@\\w+([-.]\\w+)*\\.\\w+([-.]\\w+)*"
private const val DIGIT_REG = "-?[1-9]\\d+\""
private const val URL_REG = "(https?://(w{3}\\.)?)?\\w+\\.\\w+(\\.[a-zA-Z]+)*(:\\d{1,5})?(/\\w*)*(\\??(.+=.*)?(&.+=.*)?)?"
@ -16,6 +17,8 @@ private const val CONTAINS_DIGITAL_REG = ".*[0-9]+.*"
private const val CONTAINS_LETTERS_REG = ".*[a-zA-Z]+.*"
private const val CONTAINS_LOWERCASE_LETTERS_REG = "^.*[a-z]+.*$"
private const val CONTAINS_UPPERCASE_LETTERS_REG = "^.*[A-Z]+.*$"
private const val CHINESE_HAN_NATIONALITY_NAME_REG = "^[\\u4E00-\\u9FA5]{2,4}\$"
private const val CHINESE_NAME_REG = "^[\\u4E00-\\u9FA5]+(·[\\u4E00-\\u9FA5]+)*\$"
/**
* 验证中国的手机号
@ -24,6 +27,20 @@ fun isChinaPhoneNumber(mobile: String?): Boolean {
return !isEmpty(mobile) && Pattern.matches(CHINA_PHONE_REG, mobile)
}
/**
* 验证中文姓名
*/
fun isChineseName(name: String?): Boolean {
return !isEmpty(name) && Pattern.matches(CHINESE_NAME_REG, name)
}
/**
* 验证中文汉族姓名
*/
fun isChineseHanNationalityName(name: String?): Boolean {
return !isEmpty(name) && Pattern.matches(CHINESE_HAN_NATIONALITY_NAME_REG, name)
}
/**
* 是否只包含 [1-9][a-z][A-Z]
*/

@ -0,0 +1,290 @@
package com.android.base.widget.text;
import android.annotation.SuppressLint;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.drawable.BitmapDrawable;
import android.text.Editable;
import android.text.TextUtils;
import android.text.TextWatcher;
import android.text.method.PasswordTransformationMethod;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.inputmethod.EditorInfo;
import com.android.base.R;
import com.android.base.utils.android.views.Sizes;
import org.jetbrains.annotations.NotNull;
import androidx.appcompat.widget.AppCompatEditText;
import timber.log.Timber;
public class ClearableEditText extends AppCompatEditText {
private Bitmap mClearBitmap;
private Bitmap mPasswordVisibleBitmap;
private Bitmap mPasswordInvisibleBitmap;
private Paint mBitmapPaint;
/**
* the edge offset of first bitmap
*/
private int mBitmapRightEdgeOffset;
/**
* the margin between clearing bitmap and password bitmap
*/
private int mBitmapMargin;
private int mInitPaddingRight;
private boolean mPasswordVisibleEnable;
private boolean mContentClearableEnable;
private static final int DOWN_POSITION_NONE = 1;
private static final int DOWN_POSITION_CLEAR = 2;
private static final int DOWN_POSITION_PASSWORD = 3;
private int mDownPosition = DOWN_POSITION_NONE;
private PasswordTransformationMethod mVisibleTransformation;
public ClearableEditText(Context context) {
super(context);
init(context, null);
}
public ClearableEditText(Context context, AttributeSet attrs) {
super(context, attrs);
init(context, attrs);
}
public ClearableEditText(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
init(context, attrs);
}
private void init(Context context, AttributeSet attrs) {
TypedArray typedArray = null;
try {
typedArray = context.obtainStyledAttributes(attrs, R.styleable.ClearableEditText);
BitmapDrawable clearDrawable = (BitmapDrawable) typedArray.getDrawable(R.styleable.ClearableEditText_cet_clear_drawable);
if (clearDrawable != null) {
mClearBitmap = clearDrawable.getBitmap();
} else {
mClearBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.base_icon_clear);
}
BitmapDrawable passwordVisibleDrawable = (BitmapDrawable) typedArray.getDrawable(R.styleable.ClearableEditText_cet_password_seeing_drawable);
if (passwordVisibleDrawable != null) {
mPasswordVisibleBitmap = passwordVisibleDrawable.getBitmap();
}
BitmapDrawable passwordInvisibleDrawable = (BitmapDrawable) typedArray.getDrawable(R.styleable.ClearableEditText_cet_password_closing_drawable);
if (passwordInvisibleDrawable != null) {
mPasswordInvisibleBitmap = passwordInvisibleDrawable.getBitmap();
}
mPasswordVisibleEnable = typedArray.getBoolean(R.styleable.ClearableEditText_cet_enable_password_visibility_toggle, false) && isInputTypePassword();
mContentClearableEnable = typedArray.getBoolean(R.styleable.ClearableEditText_cet_enable_content_clearable, true);
} finally {
if (typedArray != null) {
typedArray.recycle();
}
}
mInitPaddingRight = getPaddingRight();
mBitmapRightEdgeOffset = Sizes.dip(5);
mBitmapMargin = Sizes.dip(15);
mBitmapPaint = new Paint();
mBitmapPaint.setAntiAlias(true);
adjustPadding();
addTextChangedListener(newWatcher());
}
private Bitmap getPasswordVisibleBitmap() {
if (mPasswordVisibleBitmap == null) {
mPasswordVisibleBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.base_icon_password_open);
}
return mPasswordVisibleBitmap;
}
private Bitmap getPasswordInvisibleBitmap() {
if (mPasswordInvisibleBitmap == null) {
mPasswordInvisibleBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.base_icon_password_close);
}
return mPasswordInvisibleBitmap;
}
private Bitmap getPasswordBitmap() {
if (isPasswordSeeable()) {
return getPasswordInvisibleBitmap();
} else {
return getPasswordVisibleBitmap();
}
}
private PasswordTransformationMethod getVisibleTransformation() {
if (mVisibleTransformation == null) {
mVisibleTransformation = new PasswordTransformationMethod();
}
return mVisibleTransformation;
}
private void adjustPadding() {
boolean hasClearBitmap = mContentClearableEnable && !TextUtils.isEmpty(getTextValue());
int rightPadding;
if (mPasswordVisibleEnable) {
rightPadding = mInitPaddingRight + getPasswordBitmap().getWidth() + mBitmapRightEdgeOffset;
if (hasClearBitmap) {
rightPadding += (mBitmapMargin + mClearBitmap.getWidth());
}
} else if (hasClearBitmap) {
rightPadding = mInitPaddingRight + mClearBitmap.getWidth() + mBitmapRightEdgeOffset;
} else {
rightPadding = mInitPaddingRight;
}
invalidate();
setPadding(getPaddingLeft(), getPaddingTop(), rightPadding, getPaddingBottom());
}
@NotNull
private TextWatcher newWatcher() {
return new TextWatcher() {
@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
@Override
public void afterTextChanged(Editable s) {
}
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
adjustPadding();
}
};
}
@SuppressLint("ClickableViewAccessibility")
@Override
public boolean onTouchEvent(MotionEvent event) {
int action = event.getAction();
if (action == MotionEvent.ACTION_DOWN) {
mDownPosition = detectTouchPosition(event);
} else if (action == MotionEvent.ACTION_UP) {
int upPosition = detectTouchPosition(event);
Timber.d("upPosition = %d", upPosition);
if (upPosition == mDownPosition) {
if ((upPosition == DOWN_POSITION_CLEAR)) {
setText("");
} else if (upPosition == DOWN_POSITION_PASSWORD) {
if (isPasswordSeeable()) {
setTransformationMethod(null);
} else {
setTransformationMethod(getVisibleTransformation());
}
}
}
}
return super.onTouchEvent(event);
}
private int detectTouchPosition(MotionEvent event) {
float eventX = event.getX();
if (mPasswordVisibleEnable) {
int passwordRight = getMeasuredWidth() - mInitPaddingRight - mBitmapRightEdgeOffset;
int passwordLeft = passwordRight - getPasswordBitmap().getWidth();
if (eventX >= passwordLeft && eventX <= passwordRight) {
return DOWN_POSITION_PASSWORD;
}
if (mContentClearableEnable && !TextUtils.isEmpty(getTextValue())) {
int clearRight = passwordLeft - mBitmapMargin;
int clearLeft = clearRight - mClearBitmap.getWidth();
if (eventX >= clearLeft && eventX <= clearRight) {
return DOWN_POSITION_CLEAR;
}
}
} else if (mContentClearableEnable && !TextUtils.isEmpty(getTextValue())) {
int clearRight = getMeasuredWidth() - mInitPaddingRight - mBitmapRightEdgeOffset;
int clearLeft = clearRight - mClearBitmap.getWidth();
if (eventX >= clearLeft && eventX <= clearRight) {
return DOWN_POSITION_CLEAR;
}
}
return DOWN_POSITION_NONE;
}
private String getTextValue() {
Editable text = getText();
return (text == null) ? "" : text.toString();
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
canvas.save();
canvas.translate(getMeasuredWidth() - mInitPaddingRight, 0);
if (mPasswordVisibleEnable) {
Bitmap passwordBitmap = getPasswordBitmap();
canvas.translate(-(passwordBitmap.getWidth() + mBitmapRightEdgeOffset), 0);
canvas.drawBitmap(passwordBitmap, 0, (getMeasuredHeight() - passwordBitmap.getHeight()) / 2, mBitmapPaint);
}
boolean hasClearBitmap = mContentClearableEnable && !TextUtils.isEmpty(getTextValue());
if (hasClearBitmap) {
if (mPasswordVisibleEnable) {
canvas.translate(-(mClearBitmap.getWidth() + mBitmapMargin), 0);
} else {
canvas.translate(-(mClearBitmap.getWidth() + mBitmapRightEdgeOffset), 0);
}
canvas.drawBitmap(mClearBitmap, 0, (getMeasuredHeight() - mClearBitmap.getHeight()) / 2, mBitmapPaint);
}
canvas.restore();
}
private boolean isInputTypePassword() {
int inputType = getInputType();
final int variation = inputType & (EditorInfo.TYPE_MASK_CLASS | EditorInfo.TYPE_MASK_VARIATION);
final boolean passwordInputType = variation == (EditorInfo.TYPE_CLASS_TEXT | EditorInfo.TYPE_TEXT_VARIATION_PASSWORD);
final boolean webPasswordInputType = variation == (EditorInfo.TYPE_CLASS_TEXT | EditorInfo.TYPE_TEXT_VARIATION_WEB_PASSWORD);
final boolean numberPasswordInputType = variation == (EditorInfo.TYPE_CLASS_NUMBER | EditorInfo.TYPE_NUMBER_VARIATION_PASSWORD);
return passwordInputType || webPasswordInputType || numberPasswordInputType;
}
private boolean isPasswordSeeable() {
return getTransformationMethod() instanceof PasswordTransformationMethod;
}
public void setInitPaddingRight(int initPaddingRight) {
mInitPaddingRight = initPaddingRight;
adjustPadding();
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 506 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 KiB

@ -2,108 +2,108 @@
<resources>
<declare-styleable name="BannerViewPager">
<attr name="zvp_pager_number_id" format="reference"/>
<attr name="zvp_item_transition_name" format="string|reference"/>
<attr name="zvp_pager_number_id" format="reference" />
<attr name="zvp_item_transition_name" format="string|reference" />
</declare-styleable>
<declare-styleable name="PageNumberView">
<attr name="pnv_text_size" format="reference|dimension"/>
<attr name="pnv_text_color" format="reference|color"/>
<attr name="pnv_text_size" format="reference|dimension" />
<attr name="pnv_text_color" format="reference|color" />
</declare-styleable>
<declare-styleable name="RatioLayout">
<attr name="layout_ratio" format="float"/>
<attr name="layout_ratio" format="float" />
</declare-styleable>
<declare-styleable name="RatioImageView">
<attr name="layout_ratio"/>
<attr name="layout_ratio" />
</declare-styleable>
<declare-styleable name="RatioTextView">
<attr name="layout_ratio"/>
<attr name="layout_ratio" />
</declare-styleable>
<declare-styleable name="MultiStateView">
<attr name="msv_disable_when_requesting" format="boolean"/>
<attr name="msv_loadingView" format="reference"/>
<attr name="msv_requestingView" format="reference"/>
<attr name="msv_emptyView" format="reference"/>
<attr name="msv_errorView" format="reference"/>
<attr name="msv_net_errorView" format="reference"/>
<attr name="msv_server_errorView" format="reference"/>
<attr name="msv_disable_when_requesting" format="boolean" />
<attr name="msv_loadingView" format="reference" />
<attr name="msv_requestingView" format="reference" />
<attr name="msv_emptyView" format="reference" />
<attr name="msv_errorView" format="reference" />
<attr name="msv_net_errorView" format="reference" />
<attr name="msv_server_errorView" format="reference" />
<attr name="msv_viewState" format="enum">
<enum name="content" value="1"/>
<enum name="loading" value="2"/>
<enum name="empty" value="3"/>
<enum name="error" value="4"/>
<enum name="net_error" value="5"/>
<enum name="server_error" value="6"/>
<enum name="requesting" value="7"/>
<enum name="blank" value="8"/>
<enum name="content" value="1" />
<enum name="loading" value="2" />
<enum name="empty" value="3" />
<enum name="error" value="4" />
<enum name="net_error" value="5" />
<enum name="server_error" value="6" />
<enum name="requesting" value="7" />
<enum name="blank" value="8" />
</attr>
</declare-styleable>
<declare-styleable name="SimpleMultiStateView">
<attr name="msv_state_processor" format="string"/>
<attr name="msv_state_processor" format="string" />
<attr name="msv_errorImg" format="reference"/>
<attr name="msv_errorText" format="string"/>
<attr name="msv_errorAction" format="string"/>
<attr name="msv_errorImg" format="reference" />
<attr name="msv_errorText" format="string" />
<attr name="msv_errorAction" format="string" />
<attr name="msv_net_errorImg" format="reference"/>
<attr name="msv_net_errorText" format="string"/>
<attr name="msv_net_errorAction" format="string"/>
<attr name="msv_net_errorImg" format="reference" />
<attr name="msv_net_errorText" format="string" />
<attr name="msv_net_errorAction" format="string" />
<attr name="msv_server_errorImg" format="reference"/>
<attr name="msv_server_errorText" format="string"/>
<attr name="msv_server_errorAction" format="string"/>
<attr name="msv_server_errorImg" format="reference" />
<attr name="msv_server_errorText" format="string" />
<attr name="msv_server_errorAction" format="string" />
<attr name="msv_emptyImg" format="reference"/>
<attr name="msv_emptyText" format="string"/>
<attr name="msv_emptyAction" format="string"/>
<attr name="msv_emptyImg" format="reference" />
<attr name="msv_emptyText" format="string" />
<attr name="msv_emptyAction" format="string" />
</declare-styleable>
<declare-styleable name="ScrollChildSwipeRefreshLayout">
<attr name="srl_target_id" format="reference"/>
<attr name="srl_target_id" format="reference" />
<!-- a array of colors -->
<attr name="srl_color_scheme" format="reference"/>
<attr name="srl_color_scheme" format="reference" />
<!--restore refresh state-->
<attr name="srl_restore_refresh_status" format="boolean"/>
<attr name="srl_restore_refresh_status" format="boolean" />
</declare-styleable>
<declare-styleable name="PullToZoomScrollView">
<attr name="psv_zoom_view" format="reference"/>
<attr name="psv_header_view" format="reference"/>
<attr name="psv_damp" format="integer"/>
<attr name="psv_max_over" format="integer"/>
<attr name="psv_zoom_factory" format="float"/>
<attr name="psv_zoom_view" format="reference" />
<attr name="psv_header_view" format="reference" />
<attr name="psv_damp" format="integer" />
<attr name="psv_max_over" format="integer" />
<attr name="psv_zoom_factory" format="float" />
</declare-styleable>
<declare-styleable name="TriangleView">
<attr name="tv_triangle_solid_color"
format="color|reference" />
<attr name="tv_triangle_bottom_color"
format="color|reference" />
<attr name="tv_triangle_stroke_color"
format="color|reference" />
<attr name="tv_triangle_stroke_width"
format="dimension|reference" />
<attr name="tv_triangle_angle_percent"
format="float" />
<attr name="tv_triangle_direction"
format="enum">
<enum name="top"
value="1" />
<enum name="down"
value="2" />
<enum name="left"
value="3" />
<enum name="right"
value="4" />
<attr name="tv_triangle_solid_color" format="color|reference" />
<attr name="tv_triangle_bottom_color" format="color|reference" />
<attr name="tv_triangle_stroke_color" format="color|reference" />
<attr name="tv_triangle_stroke_width" format="dimension|reference" />
<attr name="tv_triangle_angle_percent" format="float" />
<attr name="tv_triangle_direction" format="enum">
<enum name="top" value="1" />
<enum name="down" value="2" />
<enum name="left" value="3" />
<enum name="right" value="4" />
</attr>
</declare-styleable>
<declare-styleable name="ClearableEditText">
<attr name="cet_enable_password_visibility_toggle" format="boolean" />
<attr name="cet_enable_content_clearable" format="boolean" />
<!--must be a bitmap-->
<attr name="cet_password_seeing_drawable" format="reference" />
<!--must be a bitmap-->
<attr name="cet_password_closing_drawable" format="reference" />
<!--must be a bitmap-->
<attr name="cet_clear_drawable" format="reference" />
</declare-styleable>
</resources>
Loading…
Cancel
Save