可以显示和隐藏密码的EditText
程序员文章站
2022-07-09 21:47:43
...
/**
* 可以显示和隐藏密码的EditText
*
* @author xiely.
* @date 17/07/19.
*/
public class ShowHidePasswordEditText extends EditText {
private boolean isShowingPassword = false;
private Drawable drawableEnd;
private Rect bounds;
private boolean leftToRight = true;
private int tintColor = 0;
@DrawableRes
private int visiblityIndicatorShow = R.drawable.ic_visibility_off;
@DrawableRes
private int visiblityIndicatorHide = R.drawable.ic_visibility_on;
private boolean monospace;
public ShowHidePasswordEditText(Context context) {
super(context);
init(null);
}
public ShowHidePasswordEditText(Context context, AttributeSet attrs) {
super(context, attrs);
init(attrs);
}
public ShowHidePasswordEditText(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
init(attrs);
}
private void init(AttributeSet attrs) {
if (attrs != null) {
TypedArray attrsArray = getContext().obtainStyledAttributes(attrs, R.styleable.ShowHidePasswordEditText);
visiblityIndicatorShow = attrsArray.getResourceId(R.styleable.ShowHidePasswordEditText_drawable_show, visiblityIndicatorShow);
visiblityIndicatorHide = attrsArray.getResourceId(R.styleable.ShowHidePasswordEditText_drawable_hide, visiblityIndicatorHide);
monospace = attrsArray.getBoolean(R.styleable.ShowHidePasswordEditText_monospace, true);
tintColor = attrsArray.getColor(R.styleable.ShowHidePasswordEditText_tint_color, 0);
attrsArray.recycle();
}
leftToRight = isLeftToRight();
isShowingPassword = false;
setInputType(EditorInfo.TYPE_CLASS_TEXT | EditorInfo.TYPE_TEXT_VARIATION_PASSWORD, true);
if (!monospace) {
setTypeface(Typeface.DEFAULT);
}
if (!TextUtils.isEmpty(getText())) {
showPasswordVisibilityIndicator(true);
}
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) {
if (s.length() > 0) {
showPasswordVisibilityIndicator(true);
} else {
showPasswordVisibilityIndicator(false);
}
}
@Override
public void afterTextChanged(Editable s) {
}
});
}
@TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR1)
private boolean isLeftToRight() {
// If we are pre JB assume always LTR
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN_MR1) {
return true;
}
Configuration config = getResources().getConfiguration();
return !(config.getLayoutDirection() == View.LAYOUT_DIRECTION_RTL);
}
@Override
public void setCompoundDrawables(Drawable left, Drawable top,
Drawable right, Drawable bottom) {
//keep a reference to the right drawable so later on touch we can check if touch is on the drawable
if (leftToRight && right != null) {
drawableEnd = right;
} else if (!leftToRight && left != null) {
drawableEnd = left;
}
if(drawableEnd != null) // 点击范围太小了,容易点不到,故增加drawable大小
drawableEnd.setBounds(0,0, DimenUtils.dpToPxInt(35),DimenUtils.dpToPxInt(35));
super.setCompoundDrawables(left, top, right, bottom);
}
public void setTintColor(@ColorInt int tintColor) {
this.tintColor = tintColor;
}
@Override
public boolean onTouchEvent(MotionEvent event) {
if (event.getAction() == MotionEvent.ACTION_UP && drawableEnd != null) {
int eventX = (int) event.getRawX();
int eventY = (int) event.getRawY();
Rect rect = new Rect();
getGlobalVisibleRect(rect);
rect.left = rect.right - 50;
if (rect.contains(eventX, eventY)){ // 判断是否在点击范围之内
togglePasswordVisibility();
event.setAction(MotionEvent.ACTION_CANCEL); // 防止弹出软键盘
}
}
return super.onTouchEvent(event);
}
/**
* 显示或隐藏小眼睛
*
* @param show
*/
private void showPasswordVisibilityIndicator(boolean show) {
if (show) {
Drawable original = isShowingPassword ?
ContextCompat.getDrawable(getContext(), visiblityIndicatorHide) :
ContextCompat.getDrawable(getContext(), visiblityIndicatorShow);
original.mutate();
if (tintColor == 0) {
setCompoundDrawablesWithIntrinsicBounds(leftToRight ? null : original, null, leftToRight ? original : null, null);
} else {
Drawable wrapper = DrawableCompat.wrap(original);
DrawableCompat.setTint(wrapper, tintColor);
setCompoundDrawablesWithIntrinsicBounds(leftToRight ? null : wrapper, null, leftToRight ? wrapper : null, null);
}
} else {
setCompoundDrawables(null, null, null, null);
}
}
private void togglePasswordVisibility() {
if (isShowingPassword) {
setInputType(EditorInfo.TYPE_CLASS_TEXT | EditorInfo.TYPE_TEXT_VARIATION_PASSWORD, true);
} else {
setInputType(EditorInfo.TYPE_CLASS_TEXT | EditorInfo.TYPE_TEXT_VARIATION_VISIBLE_PASSWORD, true);
}
isShowingPassword = !isShowingPassword;
showPasswordVisibilityIndicator(true);
}
@Override
protected void finalize() throws Throwable {
drawableEnd = null;
bounds = null;
super.finalize();
}
private void setInputType(int inputType, boolean keepState) {
int selectionStart = -1;
int selectionEnd = -1;
if (keepState) {
selectionStart = getSelectionStart();
selectionEnd = getSelectionEnd();
}
setInputType(inputType);
if (keepState) {
setSelection(selectionStart, selectionEnd);
}
}
public
@DrawableRes
int getVisiblityIndicatorShow() {
return visiblityIndicatorShow;
}
public void setVisiblityIndicatorShow(@DrawableRes int visiblityIndicatorShow) {
this.visiblityIndicatorShow = visiblityIndicatorShow;
}
public
@DrawableRes
int getVisiblityIndicatorHide() {
return visiblityIndicatorHide;
}
public void setVisiblityIndicatorHide(@DrawableRes int visiblityIndicatorHide) {
this.visiblityIndicatorHide = visiblityIndicatorHide;
}
public boolean isShowingPassword() {
return isShowingPassword;
}
}
<declare-styleable name="ShowHidePasswordEditText">
<attr name="drawable_hide" format="integer" />
<attr name="drawable_show" format="integer" />
<attr name="monospace" format="boolean" />
<attr name="tint_color" format="color" />
</declare-styleable>
有什么好的想法和交流意见欢迎留言。。。
上一篇: sudo-为普通用户提权
下一篇: [C++] const限定符