欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

可以显示和隐藏密码的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>

有什么好的想法和交流意见欢迎留言。。。

相关标签: 密码