java - 在Android Kotlin上使用 Canvas mask 输入的文本

标签 java android kotlin android-canvas android-paint

我目前正在做一个自定义的密码,并使用 Canvas 和颜料进行此操作,但是不幸的是,我似乎无法复制iputType =“numberPassword”在我的自定义设计中所做的事情,我想在掩盖它之前暂时显示该数字,然后继续到下一个图钉。

这是我的customEditText

class CustomEditTextPinViewMask : AppCompatEditText {
constructor(context: Context) : super(context)
constructor(context: Context, attrs: AttributeSet?) : super(context, attrs) {
    init(context, attrs!!)
}

constructor(context: Context, attrs: AttributeSet?, defStyleAttr: Int) : super(
    context,
    attrs,
    defStyleAttr
) {
    init(context, attrs!!)
}

@TargetApi(Build.VERSION_CODES.LOLLIPOP)
constructor(
    context: Context?,
    attrs: AttributeSet?,
    defStyleAttr: Int,
    defStyleRes: Int
) : super(context, attrs, defStyleAttr)

val XML_NAMESPACE_ANDROID = "http://schemas.android.com/apk/res/android"

private var mSpace = 24f//24 dp by default, space between the lines
private var mCharSize = 0f
private var mNumChars = 6f
private var mLineSpacing = 8f //8dp by default, height of the text from our lines
private var mMaxLength = 6
private var mClickListener: View.OnClickListener? = null
private var mLineStroke = 1f//1dp by default
private var mLineStrokeSelected = 2f//2dp by default
private var mLinesPaint: Paint? = null
private var mLinesGone: Paint? = null
private var mPaint: Paint? = null
val mStates = arrayOf(
    intArrayOf(R.attr.state_selected),
    intArrayOf(R.attr.state_focused),
    intArrayOf(-R.attr.state_focused)
)

val mColors = intArrayOf(
    -0x493800,//Green color = 0xFFB6C800
    -0x333334,//Gray color = 0xFFCCCCCC
    -0x333334
)

val mColorStates = ColorStateList(mStates, mColors)

private fun init(context: Context, attrs: AttributeSet) {
    val multi = context.resources.displayMetrics.density
    mLineStroke *= multi
    mLineStrokeSelected *= multi
    mLinesPaint = Paint(paint)
    mLinesPaint!!.strokeWidth = mLineStroke
    mLinesPaint!!.color = Color.parseColor("#969696")
    mLinesGone = Paint(paint)
    mLinesGone!!.strokeWidth = mLineStroke
    mLinesGone!!.color = Color.parseColor("#FFFFFF")
    mPaint = Paint(paint)
    setBackgroundResource(0)
    mSpace *= multi //convert to pixels for our density
    mLineSpacing *= multi //convert to pixels for our density
    mMaxLength = attrs.getAttributeIntValue(XML_NAMESPACE_ANDROID, "maxLength", 6)
    mNumChars = mMaxLength.toFloat()

    //Disable copy paste
    super.setCustomSelectionActionModeCallback(object : ActionMode.Callback {
        override fun onPrepareActionMode(mode: ActionMode, menu: Menu): Boolean {
            return false
        }

        override fun onDestroyActionMode(mode: ActionMode) {}
        override fun onCreateActionMode(mode: ActionMode, menu: Menu): Boolean {
            return false
        }

        override fun onActionItemClicked(mode: ActionMode, item: MenuItem): Boolean {
            return false
        }
    })
    // When tapped, move cursor to end of text.
    super.setOnClickListener(View.OnClickListener { v ->
        setSelection(text!!.length)
        if (mClickListener != null) {
            mClickListener!!.onClick(v)
        }
    })
}

override fun setOnClickListener(l: View.OnClickListener?) {
    mClickListener = l
}

override fun setCustomSelectionActionModeCallback(actionModeCallback: ActionMode.Callback?) {
    throw RuntimeException("setCustomSelectionActionModeCallback() not supported.")
}

private fun getColorForState(vararg states: Int): Int {
    return mColorStates.getColorForState(states, Color.GRAY)
}

private fun updateColorForLines(next: Boolean) {
    if (isFocused) {
        mLinesPaint!!.strokeWidth = mLineStrokeSelected
        mLinesPaint!!.color = getColorForState(R.attr.state_focused)
        mLinesPaint!!.color = getColorForState(R.attr.state_window_focused)
        if (next) {
            mLinesPaint!!.color = getColorForState(R.attr.state_selected)
        }
    } else {
        mLinesPaint!!.strokeWidth = mLineStroke
        mLinesPaint!!.color = getColorForState(-R.attr.state_focused)
    }
}

override fun onDraw(canvas: Canvas) {
   // super.onDraw(canvas)
    val availableWidth = width - paddingRight - paddingLeft
    if (mSpace < 0) {
        mCharSize = availableWidth / (mNumChars * 2 - 1)
    } else {
        mCharSize = (availableWidth - mSpace * (mNumChars - 1)) / mNumChars
    }
    var startX = paddingLeft
    val bottom = height - paddingBottom

    //Text Width
    val text: Editable? = text
    val textLength = text?.length
    val textWidths = FloatArray(textLength!!)
    paint.getTextWidths(getText(), 0, textLength, textWidths)

    //If Wanted to change text Color
    var i = 0
    while (i < mNumChars) {
        updateColorForLines(i == textLength)
        canvas.drawLine(
            startX.toFloat(), bottom.toFloat(), (startX + mCharSize) + letterSpacing,
            bottom.toFloat(), mLinesPaint!!
        )

        if (getText()!!.length > i) {
            val middle = startX + mCharSize / 2

            canvas.drawText(text, i, i + 1, middle - textWidths[0] / 2,
                bottom - mLineSpacing, paint)

            mLinesGone!!.strokeWidth = mLineStrokeSelected

            canvas.drawLine(
                startX.toFloat(), bottom.toFloat(),
                startX + mCharSize, bottom.toFloat(), mLinesGone!!
            )
            canvas.drawLine(
                startX.toFloat(), bottom.toFloat(),
                startX + mCharSize, bottom.toFloat(), mLinesGone!!
            )
            canvas.drawLine(
                startX.toFloat(), bottom.toFloat(),
                startX + mCharSize, bottom.toFloat(), mLinesGone!!
            )
        }
        if (mSpace < 0) {
            var mCharSizeMult = mCharSize * 2
            startX = (startX + mCharSizeMult).toInt()
        } else {
            var mCharSizeMspace = mCharSize + mSpace.toInt()
            startX = (startX + mCharSizeMspace).toInt()
        }
        i++
    }
}

}

这就是我在xml上实现它的方式
 <com.sample.ui.widget.CustomEditTextPinViewMask
        android:id="@+id/pv_pincode"
        android:layout_width="260dp"
        android:layout_height="wrap_content"
        android:cursorVisible="false"
        android:inputType="numberPassword"
        android:letterSpacing="1"
        android:maxLength="6"
        android:textColor="@color/text_label_black"
        android:textIsSelectable="false"
        android:textSize="28sp"/>

这是在手机上显示时的样子enter image description here

我该如何遮盖它?我也随时欢迎您的到来。

最佳答案

只需使用 setTransformationMethod() 对其进行屏蔽即可。
您可以使用它来掩盖edittext。

//by default
edittext.setTransformationMethod(new PasswordTransformationMethod());
//You can make it custom
edittext.setTransformationMethod(new AsterPasswordTransformationMethod());
这是Aster PasswordTransformationMethod类
public class AsterPasswordTransformationMethod extends PasswordTransformationMethod {
    @Override
    public CharSequence getTransformation(CharSequence source, View view) {
        return new PasswordCharSequence(source);
    }

    private class PasswordCharSequence implements CharSequence {
        private CharSequence mSource;
        public PasswordCharSequence(CharSequence source) {
            mSource = source; // Store char sequence
        }
        public char charAt(int index) {
            return '*'; // This is the important part
        }
        public int length() {
            return mSource.length(); // Return default
        }
        public CharSequence subSequence(int start, int end) {
            return mSource.subSequence(start, end); // Return default
        }
    }
    };

关于java - 在Android Kotlin上使用 Canvas mask 输入的文本,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62079613/

相关文章:

java - jar 内的类的上次更新时间

android - 为什么我不能在 Service 的构造函数中使用 Context.getPackageManager

Java 帧动画损害性能

java - 同时打开多个套接字

android - 将视频流式传输到 iOS、Android 应用程序的相同技术

android - Firebase Unresolved reference

file - 如何将文件上传到restful api kotlin

protocol-buffers - Kotlin 重写 protobuf 类型 toString

java - 如何将 spring-boot war 部署到 debian jetty8

java - 如何在没有 numpy 的情况下将 Python 代码转换为 Java