使用 Android Kotlin 中的画布(Canvas)对输入的文本进行遮罩处理

huangapple 未分类评论50阅读模式
英文:

Masking inputted text using canvas on android kotlin

问题

我目前正在进行自定义的PIN码功能使用了Canvas和Paint来实现不幸的是我似乎无法复制`inputType="numberPassword"`所做的事情并应用于我的自定义设计我希望在将数字遮盖并继续输入下一个PIN码之前暂时显示数字

以下是我的CustomEditTextPinView类的代码

```kotlin
class CustomEditTextPinViewMask : AppCompatEditText {
    // 构造函数和其他变量的初始化...
    
    override fun onDraw(canvas: Canvas) {
        // super.onDraw(canvas)  // 注释掉这一行
        // 绘制PIN码的逻辑...
    }
}

这是如何在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"/>

这是在手机上显示的外观示例:

使用 Android Kotlin 中的画布(Canvas)对输入的文本进行遮罩处理

如果你想要遮盖PIN码,你可以在CustomEditTextPinViewMask类的onDraw方法中的相应位置添加遮盖逻辑。一种常见的做法是使用圆点(•)或其他遮盖字符来代替实际的数字。

希望这对你有帮助!如果你有其他问题或建议,欢迎继续提问。```

英文:

I'm currently doing a custom pin code and doing it with a canvas and paint, Unfortunately I cant seems to copy what the iputType="numberPassword" is doing with my custom design, I want to show the number momentarily before masking it and proceed to the next pin.

Here is my 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 = &quot;http://schemas.android.com/apk/res/android&quot;

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(&quot;#969696&quot;)
    mLinesGone = Paint(paint)
    mLinesGone!!.strokeWidth = mLineStroke
    mLinesGone!!.color = Color.parseColor(&quot;#FFFFFF&quot;)
    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, &quot;maxLength&quot;, 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 -&gt;
        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(&quot;setCustomSelectionActionModeCallback() not supported.&quot;)
}

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 &lt; 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 &lt; mNumChars) {
        updateColorForLines(i == textLength)
        canvas.drawLine(
            startX.toFloat(), bottom.toFloat(), (startX + mCharSize) + letterSpacing,
            bottom.toFloat(), mLinesPaint!!
        )

        if (getText()!!.length &gt; 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 &lt; 0) {
            var mCharSizeMult = mCharSize * 2
            startX = (startX + mCharSizeMult).toInt()
        } else {
            var mCharSizeMspace = mCharSize + mSpace.toInt()
            startX = (startX + mCharSizeMspace).toInt()
        }
        i++
    }
}

}

This is how i implement it on my xml

 &lt;com.sample.ui.widget.CustomEditTextPinViewMask
        android:id=&quot;@+id/pv_pincode&quot;
        android:layout_width=&quot;260dp&quot;
        android:layout_height=&quot;wrap_content&quot;
        android:cursorVisible=&quot;false&quot;
        android:inputType=&quot;numberPassword&quot;
        android:letterSpacing=&quot;1&quot;
        android:maxLength=&quot;6&quot;
        android:textColor=&quot;@color/text_label_black&quot;
        android:textIsSelectable=&quot;false&quot;
        android:textSize=&quot;28sp&quot;/&gt;

This is how it will look like when shown on the phone 使用 Android Kotlin 中的画布(Canvas)对输入的文本进行遮罩处理

How can i mask it? I'm also open for any sugestions thank you.

答案1

得分: 0

只需使用**setTransformationMethod()** 进行掩盖。

您可以使用此方法对编辑框进行掩盖。

// 默认情况下
edittext.setTransformationMethod(new PasswordTransformationMethod());
// 您可以自定义
edittext.setTransformationMethod(new AsterPasswordTransformationMethod());

下面是AsterPasswordTransformationMethod类的代码示例:

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; // 存储字符序列
        }
        public char charAt(int index) {
            return '*'; // 这是关键部分
        }
        public int length() {
            return mSource.length(); // 返回默认值
        }
        public CharSequence subSequence(int start, int end) {
            return mSource.subSequence(start, end); // 返回默认值
        }
    }
};
英文:

Just use setTransformationMethod() for masking it.

You can use this to mask the edittext .

//by default
edittext.setTransformationMethod(new PasswordTransformationMethod());
//You can make it custom
edittext.setTransformationMethod(new AsterPasswordTransformationMethod());

here is the AsterPasswordTransformationMethod class

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 &#39;*&#39;; // 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
        }
    }
    };

huangapple
  • 本文由 发表于 2020年5月29日 14:01:07
  • 转载请务必保留本文链接:https://java.coder-hub.com/62079613.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定