Android 在编辑文本字段中输入之前捕获扫描数据

Android capturing scan data before entered in edittext field

实际发生的是设备在扫描后根据它是设置为发送标签还是输入发送 2 个输入或标签。

我使用 xamarin Android 命名空间构建

我已经尝试了所有可能的方法,我已将我的片段设置为 textwatcher

public class SearchFragment : BaseFragment, IDialogInterfaceOnDismissListener, ITextWatcher

并设置监听器

this._theEditText.AddTextChangedListener(this);

并在 BeforeTextChanged 事件中设置它,但是无法从 char 序列中获取值,尽管在测试用例中扫描有 8 个字符,+2 表示 2 个回车键,但它显示为 8。

    public void BeforeTextChanged(ICharSequence s, int start, int count, int after)
    {
        this._scanCount = _scanCount + (after - start);
        if (this._scanCount > 4)
        {
            string text = s.ToString();
            //need remove carriage returns and line feeds here if exist
            //then add single carriage return or advance to next field
        }

        if (this._scanTimer != null) this._scanTimer.Dispose();
        this._scanTimer = new Timer(delegate (object state)
        {
            this._scanCount = 0;
            this._scanTimer = null;
        }, false, 100, 0);
    }

我使用的下一个方法是捕获按键并使用内置在 beforetextchanged 事件处理程序中的 editText(我单独使用了所有这些不同的方法,而不是一起使用)

this._theEditText.KeyPress += EditText_KeyPress;
this._theEditText.BeforeTextChanged += EditText_BeforeTextChanged;

在按键事件中我得到了一堆标签和 f4(我可能会添加这些标签并没有足够奇怪地推进字段)

再次使用 BeforeTextChanged 事件我无法获取字符序列,尽管在 8 之前和之后存在差异(再次在末尾输入不算数)尽管实际文本存在 8 差异 e.Text 是“”

    private void EditText_BeforeTextChanged(object sender, TextChangedEventArgs e)
    {
        this._scanCount = _scanCount + (e.AfterCount - e.BeforeCount);
        if (this._scanCount > 4)
        {
            SpannableStringBuilder stringBuilder = (SpannableStringBuilder)e.Text;

            ((SpannableStringBuilder)e.Text).ToString();
        }

        if (this._scanTimer != null) this._scanTimer.Dispose();
        this._scanTimer = new Timer(delegate (object state)
        {
            this._scanCount = 0;
            this._scanTimer = null;
        }, false, 100, 0);
    }

是的,键盘扫描仪和 Android 相当混乱 together.The 我不得不处理的扫描仪过去常常发送 Down+Enter 作为他们完成扫描的标志。这是有效的 Java 代码(我相信将其转换为 C# 并将 Down/Enter 更改为您的两个键不会有任何问题)

public class ScannerView extends View implements View.OnKeyListener {
    private StringBuilder scannedCode = new StringBuilder();
    private Callback scanCallback;


    public void setCallback(Callback scanCallback) {
        this.scanCallback = scanCallback;
    }

    public ScannerView(Context context) {
        super(context);
        init();
    }

    public ScannerView(Context context, AttributeSet attrs) {
        super(context, attrs);
        init();
    }

    public ScannerView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init();
    }

    @TargetApi(Build.VERSION_CODES.LOLLIPOP)
    public ScannerView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
        super(context, attrs, defStyleAttr, defStyleRes);
        init();
    }

    private void init() {
        setFocusable(true);
        setFocusableInTouchMode(true);
        requestFocus();
        setOnKeyListener(this);
    }

    @Override
    public boolean onKey(View v, int keyCode, KeyEvent event) {
        boolean consumed = false;
        if (event.getAction() != KeyEvent.ACTION_UP) {
            return consumed;
        }

        switch (keyCode) {
            case KeyEvent.KEYCODE_0:
            case KeyEvent.KEYCODE_1:
            case KeyEvent.KEYCODE_2:
            case KeyEvent.KEYCODE_3:
            case KeyEvent.KEYCODE_4:
            case KeyEvent.KEYCODE_5:
            case KeyEvent.KEYCODE_6:
            case KeyEvent.KEYCODE_7:
            case KeyEvent.KEYCODE_8:
            case KeyEvent.KEYCODE_9:
                scannedCode.append(keyCode - 7);
                consumed = true;
                break;
            case KeyEvent.KEYCODE_ENTER:
                if (scanCallback != null) {
                    scanCallback.onBarcodeScanned(scannedCode.toString());
                }
                scannedCode = new StringBuilder();
                consumed = true;
                break;

            case KeyEvent.KEYCODE_DPAD_DOWN:
                consumed = true;
                break;
        }

        return consumed;
    }

    interface Callback {
        void onBarcodeScanned(String barCode);
    }
}

根据我的了解,这与您使用扫描仪获得类似零售业的良好体验一样接近。然后您可以使用回调并将文本设置为您需要的任何编辑或处理它。请记住始终将焦点设置到您的扫描视图:父生命周期事件、它自己的焦点更改回调等等,您将在测试时找出其余部分。

我了解到没有以相同方式发送数据的条码扫描仪。正如 Nick 的回答所指出的,有些发送键码,但我处理过的发送制表符、换行符、回车 returns,甚至 prefix/postfix 条形码字符串的空格,你得到整个一杆成串。

文本观察者可以干净利落地处理这些。

子类化 Java 对象并实现 ITextWatcher:

public class StripperTextWatcher : Java.Lang.Object, ITextWatcher
{
    char[] stripThese = new char[] { '\n', '\t', '\r', ' ' };

    public void AfterTextChanged(IEditable s)
    {
        for (int i = 0; i < s.Length(); i++)
        {
            if (stripThese.Contains(s.ElementAt(i)))
            {
                s.Replace(i, i + 1, "");
                return; // AfterTextChanged is called recursively for each change.... 
            }
        }

    }

    public void BeforeTextChanged(ICharSequence s, int start, int count, int after)
    {
    }

    public void OnTextChanged(ICharSequence s, int start, int before, int count)
    {
    }
}

用法:

var editText = FindViewById<EditText>(Resource.Id.editText1);
editText.AddTextChangedListener(new StripperTextWatcher());