自定义Android pin码输入小部件

时间:2012-05-10 06:31:18

标签: android widget

我正在尝试为Android创建一个自定义PIN码小部件,作为仅使用带有密码inputType属性的EditText的替代方法。我想要显示的是一排盒子,每个盒子都会在用户输入其针脚时填充。

其他人做了类似这样的事情,但事实证明这是EditText次视图的固定数量,并且在输入或删除字符时,有很多丑陋代码用于交换焦点。这不是我想采取的方法;相反,我正在设计我的可自定义长度(简单)并且表现为单一可聚焦视图(不那么容易)。

到目前为止,我的概念是LinearLayout(保持“框”)和EditText(存储用户输入)之间的某种混合。

这是迄今为止的代码......

public class PinCodeView extends LinearLayout {
    protected static final int MAX_PIN_LENGTH = 10;
    protected static final int MIN_PIN_LENGTH = 1;

    protected int pinLength;
    protected EditText mText;

    public PinCodeView(Context context, AttributeSet attrs) {
        super(context, attrs);

        TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.PinCodeView);
        try {
            pinLength = a.getInt(R.styleable.PinCodeView_pinLength, 0);
        } finally {
            a.recycle();
        }

        pinLength = Math.min(pinLength, MAX_PIN_LENGTH);
        pinLength = Math.max(pinLength, MIN_PIN_LENGTH);

        setupViews();

        Log.d(TAG, "PinCodeView initialized with pinLength = " + pinLength);
    }

    private void setupViews() {
        LayoutInflater inflater = (LayoutInflater) getContext().getSystemService(
                Context.LAYOUT_INFLATER_SERVICE);
        for (int i = 0; i < pinLength; i++) {
            // inflate an ImageView and add it
            View child = inflater.inflate(R.layout.pin_box, null, false);
            addView(child);
        }
    }

    public CharSequence getText() {
        // TODO return pin code text instead
        return null;
    }

    public int length() {
        // TODO return length of typed pin instead
        return pinLength;
    }

    @Override
    public boolean onCheckIsTextEditor() {
        return true;
    }

    @Override
    public InputConnection onCreateInputConnection(EditorInfo outAttrs) {
        // TODO return an InputConnection
        return null;
    }
}

关于这些覆盖:onCheckIsTextEditor()应返回true,onCreateInputConnection(EditorInfo outAttrs)应返回一个新的InputConnection对象与InputMethod(键盘)进行交互,但这就是我所知道的。

有人知道我是否走在正确的轨道上?是否有人之前使用InputConnection工作或制作了自己的可编辑观点,以便提供指导?

(编辑1) 在看了这个之后,似乎我应该继承BaseInputConnection并提供TextViewEditText作为其目标:

    @Override
    public InputConnection onCreateInputConnection(EditorInfo outAttrs) {
        if (!onCheckIsTextEditor()) {
            return null;
        }
        return new BaseInputConnection(mText, true);
    }

假设这确实存储了输入的文本,我仍然需要一些方法来更新视图以反映内容的变化......

(编辑2) 所以我将这个自定义视图添加到屏幕进行测试。它显示了盒子的数量,整个视图是可聚焦的,但键盘永远不会弹出。我知道它会获得/失去焦点,因为这些框显示了适当的突出显示,我设置了OnFocusChangedListener来写入logcat。

当可编辑视图成为焦点时,实际键盘出现的原因是什么?

5 个答案:

答案 0 :(得分:4)

似乎您可能正在尝试创建类似针入口视图/窗口小部件的iOS。

这是一个很有用的示例代码。但是,它是固定长度,但对某些人来说仍然有用。

https://github.com/chinloong/Android-PinView

http://madeveloper.blogspot.com/2013/02/android-ios-like-pin-entrychallenge.html

答案 1 :(得分:2)

我知道这已经得到了解答,但由于它的实现没有共享,我发现了一个类似的开源库。它看起来不错,对于所有流浪的人都可以试试

https://github.com/Philio/PinEntryView

答案 2 :(得分:1)

对我来说没问题。您可能想要做的事情是当用户在一个EditText框中键入一个字符时,找到对下一个EditText框的引用并对其执行requestFocus()。这会将文本条目移动到下一个框中。非常简单。

答案 3 :(得分:0)

我在此方面取得了相当大的进展,不再需要有关InputConnection的帮助。简而言之,您扩展BaseInputConnection并覆盖getEditable()以返回可编辑。在这种情况下,我将返回TextView内部使用的私有PinCodeViewPinCodeView也覆盖了onKey[foo]()等多种方法,并将调用转发给内部TextView。其余的只是在文本发生变化时使用TextWatcher更新其中一个子ImageView

效果很好。还有一些小问题需要加以改进,但我会将这些问题作为单独的问题来解决,并在此处关闭。

答案 4 :(得分:0)

implementation 'com.alimuzaffar.lib:pinentryedittext:1.3.10'

将此依赖项放入您的应用模块Gradle文件并进行同步。

    <com.alimuzaffar.lib.pin.PinEntryEditText

                    android:inputType="number"
                    android:id="@+id/Pin_Et"
                    android:maxLength="6"
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"/>

将此代码放入XML(布局文件)中。
使用此代码,效果很好