需要帮助获取Android TextWatcher以处理传入的复合条形码数据

Bri*_*ian 6 android textwatcher

我正在编写一个使用和外部连接USB条形码/ RFID扫描仪的应用程序.正在扫描的数据是"复合"数据.这是一个例子:

=+03000=W12560712345600=%2800&>0090452359
Run Code Online (Sandbox Code Playgroud)

那是来自复合数据扫描.数据中的分隔符是等号(=)或&符号(&).第一位=+03000说扫描中有三个数据部分:

=W12560712345600

=%2800

&>0090452359
Run Code Online (Sandbox Code Playgroud)

该数据可以具有从1到N的任意数量的数据部分.

在我的Android应用程序中,我有一个包含三个EditText元素的表单.我需要对这个复合扫描数据做的是使用分隔符将其分解,并将每个数据粘贴到适当的EditText字段中.

经过多次痛苦之后,我已经意识到我不能只操纵标准输入,并且我需要TextWatcher在我的一个EditText字段上使用捕获扫描数据以便我可以操作它.

我的问题是我无法弄清楚如何做到这一点.这是我有的:

activity_main.xml中

<LinearLayout>
    <TextView />
    <EditText android:id="@+id/datafield01" />
    <EditText android:id="@+id/datafield02" />
    <EditText android:id="@+id/datafield03" />
    <Button />
</LinearLayout>
Run Code Online (Sandbox Code Playgroud)

MainActivity.java

public class MainActivity extends AppCompatActivity {
    @Override
    protected void onCreate(Bundle savedInstanceState){
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        EditText dataField01 = (EditText)findViewById(R.id.datafield01);
        EditText dataField02 = (EditText)findViewById(R.id.datafield02);
        EditText dataField02 = (EditText)findViewById(R.id.datafield03);

        dataField01.addTextChangedListener(editTextWatcher);
    }

    TextWatcher editTextWatcher = 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){
        }

        @Override
        public void afterTextChanged(CharSequence s){
        }
    };
}
Run Code Online (Sandbox Code Playgroud)

我已经尝试捕获CharSequenceStringBuffer- 使用before,on和afterTextChanged - 所以我可以操纵它并将它放入正确的EditText元素,但我没有成功.

修改了MainActivity.java

public class MainActivity extends AppCompatActivity {
    private StringBuffer stringBuffer;
    @Override
    protected void onCreate(Bundle savedInstanceState){
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        stringBuffer = new StringBuffer();

        EditText dataField01 = (EditText)findViewById(R.id.datafield01);
        EditText dataField02 = (EditText)findViewById(R.id.datafield02);
        EditText dataField02 = (EditText)findViewById(R.id.datafield03);
        dataField01.addTextChangedListener(editTextWatcher);

        System.out.println(stringBuffer.toString());
    }

    TextWatcher editTextWatcher = 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){
            stringBuffer.append(s);
        }

        @Override
        public void afterTextChanged(CharSequence s){
        }
    };
}
Run Code Online (Sandbox Code Playgroud)

每当我试着去System.out.println(stringbuffer);那里什么都没有.

扫描的代码不提供换行符或任何其他类型的分隔符,它已经结束,数据部分的数量可以是1到N,但每个数据部分确实具有已知的固定长度.

必须有其他人做这样的事情,但我的谷歌搜索没有结果.

那么,有什么方法可以完成我想做的事情,还是我完全没有运气?

谢谢.

kri*_*son 0

我确信有一种方法可以通过某些TextWatcher实现来做到这一点;当您看到分隔符等时切换焦点。

但我认为,当您知道拥有条形码扫描仪的所有输入时,处理起来会更容易。然后您可以简单地解析数据并将其放在适当的位置。

因此,关键是要弄清楚何时拥有所有扫描仪输入,以便可以解析它。

下面是一些使用我从查看 AndroidFilter适配器类中学到的技巧的代码。有一个延迟机制,可以对多次快速按键仅过滤一次。(遗憾的是,它是谷歌私有的,所以我们凡人不应该使用这个有用的功能。)

由于您的扫描仪显然就像键盘一样,因此按键暂停应该意味着扫描仪已完成输入。让我们用它来确定扫描何时完成。

首先,我们将定义一个回调接口,因为我是一个 IoC 类型的人:

    interface ScanProcessor {

       void process(CharSequence input);
    }
Run Code Online (Sandbox Code Playgroud)

现在我们将定义一个Handler类。该处理程序将在主(UI)线程上运行,因此我们不能让处理器太忙。

    public static class InputDelayHandler extends Handler {

       private static final int INPUT_MESSAGE = 0x20170308;

       private static final int PROCESS_MESSAGE = 0x20170309;

       // You'll have to tweak this value to ensure all input is entered, 
       // while the app remains responsive to the scan
       private static final long DELAY_MS = 250;

       private CharSequence mInput;

       private ScanProcessor mScanProcessor;

       InputDelayHandler(ScanProcessor scanProcessor) {
           super();  // associate the handler with the Looper for the current thread
           mScanProcessor = scanProcessor;
       }

       void setInput(CharSequence input) {

           // removing this message is the key to how this works
           // since it's delayed, we can cancel before input is complete.
           removeMessages(PROCESS_MESSAGE);
           removeMessages(INPUT_MESSAGE);
           Message inputMessage = obtainMessage(INPUT_MESSAGE);
           inputMessage.obj = input;
           sendMessage(inputMessage);
           Message startMessage = obtainMessage(PROCESS_MESSAGE);
           sendMessageDelayed(startMessage, DELAY_MS);
       }

       @Override
       public void handleMessage(Message msg) {

           switch (msg.what) {
           case INPUT_MESSAGE:
               // remember the last input
               mInput = (CharSequence) msg.obj;
               break;
           case PROCESS_MESSAGE:
               // callback
               if (/*mInput looks like valid scan data*/) {
                   mScanProcessor.process(mInput);
               }
               break;
           }
       }
   }
Run Code Online (Sandbox Code Playgroud)

具有EditText字段的类应该保留对处理程序的引用。

        private InputDelayHandler mHandler;
Run Code Online (Sandbox Code Playgroud)

现在你TextWatcher只需要告诉处理程序发生了什么事:

        @Override
        public void onTextChanged(CharSequence s, int start, int before, int count) {

            mHandler.setInput(s);
        }
Run Code Online (Sandbox Code Playgroud)

这将它们联系在一起:

            mHandler = new InputDelayHandler(new ScanProcessor() {

                @Override void process(CharSequence input) {

                    // parse the input, set the EditText fields, etc.
                }
            });
Run Code Online (Sandbox Code Playgroud)