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());
实际发生的是设备在扫描后根据它是设置为发送标签还是输入发送 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());