uniapp外接USB扫码枪并获取扫码数据

1. 原理

说明:项目中使用的是标准的扫码枪,标准的意思就是它都不给开发文档。走的标准“输入事件”,和外接键盘是一样的。扫码枪扫描到的条形码每一位会触发一次onkeydown事件。比如扫描条码位‘1234567890’的条形码,会连续执行10次onkeydown事件,条码扫描到最后一位,会直接触发Enter(标准扫描枪扫描数据会触发KEYCODE_ENTER键)。

拓展
扫码枪的种类有蓝牙、USB、串口等等,目前USB的扫码枪主流的就是以下两种:

  • USB HID-KBW:支持 Android 热插拔USB扫描枪会在有EditText时,扫描枪扫描内容自动输入到编辑框了,即扫码器会将扫描出来的内容转化为键盘事件,就是Android中KeyEvent里面对应的常量(KeyEvent.KEYCODE_*)。但是有很多输入法兼容的问题,比如搜狗输入法识别到HID设备时会隐藏无法弹出,如果输入法切换成中文时会输入中文等等。
  • USB 虚拟串口:通过串口的方式直接获取原始数据,不再跟输入法产生冲突。可使用android-serialport-api连接到UsbDevice进行通信,读取数据;但扫码枪设备要支持串口(扫码枪若是USB HID则不支持串口)。

2. 优缺点

(1) 优点:

  • 不需要额外供电以及价格便宜
  • 即插即用:实质其实就是相当于设备的外接键盘,也就是它必须在有光标的地方才能进行扫码,且是直接把扫到的内容自动输入到输入框中,并不受我们的控制
  • 直接通过串口读取流里面的数据

(2) 缺点:需要知道每一款扫码器的型号以获取波特率及Android设备的串口地址。
备注:我的项目在实现获取扫码枪数据的过程中并未体现该缺点。

3. 监听扫码枪事件获取数据

备注:扫码枪就是 = 键盘 + 回车,即外接接盘。所以建个txt文本文档或者doc随便,打开,然后连接扫码枪,开始扫描,扫码结果就会自动填入你的文档。

  • 方案一:监听键盘的keydown事件(监听js键盘事件)
    分析:uniapp无document对象,无法获取keydown事件。无键盘事件,不支持键盘修饰符。
  • 方案二:通过native.js调用安卓原生类库,通过广播方式实现扫码结果的接收。参考1参考2参考三
    分析:需从厂商那里获取到android开发文档,查看扫码广播标识(意图action)对应的字段。
var main,receiver,filter;  

① 在过滤器中添加扫码广播标识(意图action)

var IntentFilter = plus.android.importClass('android.content.IntentFilter');  
filter = new IntentFilter();  
filter.addAction("com.se4500.onDecodeComplete");  //监听扫描
//filter.addAction("com.zkc.scancode");//监听扫描  

注意:不同厂商扫码广播标识action对应的字段不一样,这里以com.se4500.onDecodeComplete为例。
② 注册广播接受者BroadcastReceiver并重写onReceive()方法

receiver = plus.android.implements('io.dcloud.feature.internal.reflect.BroadcastReceiver',{  
    onReceive : function(context, intent) {  
        plus.android.importClass(intent);  //通过intent实例引入intent类,方便以后的‘.’操作  
       /*这个se4500很坑,不同的手机或pda,这个值就不一样,要具体去查硬件api*/  
        var code = intent.getStringExtra("se4500");  
       // var code = intent.getStringExtra("code");  
        console.log('条码:',code); 
    }});  

注意:获取扫码数据时,此处key为se4500仅为示例,不同手机或pda,这个值不一样,具体要去查硬件api。
③ 注册监听

main = plus.android.runtimeMainActivity();//获取activity  
main.registerReceiver(receiver,filter);  //注册监听

④ 注销监听

main.unregisterReceiver(receiver);  //取消监听
  • 方案三:使用 5+ 的api监听键盘事件
    分析:H5 和小程序不能监听键盘事件,但是app端可通过使用 5+ 的api监听键盘事件。经测试,app端使用 5+ 的api未能监听到键盘事件。

这种方案应该是最合适的,但是测试未成功,这里仅提供一个思路,可能我的实现方法错了,虚心求教有思路的小伙伴。

<template>
    <view>
        plus监听原生扩展事件:扫码结果{{resultValue}}
    </view>
</template>

<script>
var _self;
export default {
    data() {
        return {
            resultValue:""
        }
    },
    methods: {
    
    },
    onLoad:function(){
        _self = this;

        // #ifdef APP-PLUS
        /* plus.key.addEventListener('backbutton',function(KeyEvent){
            console.log("点击了返回键:" + JSON.stringify(KeyEvent));
            console.log("点击了返回键:" + KeyEvent.keyCode);
        }); */
        plus.key.addEventListener('keydown',function(KeyEvent){
            console.log("按下了键:" + JSON.stringify(KeyEvent));
            console.log("按下了键:" + KeyEvent.keyCode);
            if(KeyEvent.keyCode == 9){
                //plus.nativeUI.toast("Tab结束符");
                plus.nativeUI.toast("resultValue:" + _self.resultValue);
                _self.resultValue = "";
            }else if(KeyEvent.keyCode == 10){
                //plus.nativeUI.toast("换行结束符");
                plus.nativeUI.toast("resultValue:" + _self.resultValue);
                _self.resultValue = "";
            }else if(KeyEvent.keyCode == 13){
                //plus.nativeUI.toast("按下了回车键");
                plus.nativeUI.toast("resultValue:" + _self.resultValue);
                _self.resultValue = "";
            }else if(KeyEvent.keyCode == 48){
                _self.resultValue = _self.resultValue + "0";
            }else if(KeyEvent.keyCode == 49){
                _self.resultValue = _self.resultValue + "1";
            }else if(KeyEvent.keyCode == 50){
                _self.resultValue = _self.resultValue + "2";
            }else if(KeyEvent.keyCode == 51){
                _self.resultValue = _self.resultValue + "3";
            }else if(KeyEvent.keyCode == 52){
                _self.resultValue = _self.resultValue + "4";
            }else if(KeyEvent.keyCode == 53){
                _self.resultValue = _self.resultValue + "5";
            }else if(KeyEvent.keyCode == 54){
                _self.resultValue = _self.resultValue + "6";
            }else if(KeyEvent.keyCode == 55){
                _self.resultValue = _self.resultValue + "7";
            }else if(KeyEvent.keyCode == 56){
                _self.resultValue = _self.resultValue + "8";
            }else if(KeyEvent.keyCode == 57){
                _self.resultValue = _self.resultValue + "9";
            }else if(KeyEvent.keyCode == 65){
                _self.resultValue = _self.resultValue + "A";
            }else if(KeyEvent.keyCode == 66){
                _self.resultValue = _self.resultValue + "B";
            }else if(KeyEvent.keyCode == 67){
                _self.resultValue = _self.resultValue + "C";
            }else if(KeyEvent.keyCode == 68){
                _self.resultValue = _self.resultValue + "D";
            }else if(KeyEvent.keyCode == 69){
                _self.resultValue = _self.resultValue + "E";
            }else if(KeyEvent.keyCode == 70){
                _self.resultValue = _self.resultValue + "F";
            }else if(KeyEvent.keyCode == 71){
                _self.resultValue = _self.resultValue + "G";
            }else if(KeyEvent.keyCode == 72){
                _self.resultValue = _self.resultValue + "H";
            }else if(KeyEvent.keyCode == 73){
                _self.resultValue = _self.resultValue + "I";
            }else if(KeyEvent.keyCode == 74){
                _self.resultValue = _self.resultValue + "J";
            }else if(KeyEvent.keyCode ==75){
                _self.resultValue = _self.resultValue + "K";
            }else if(KeyEvent.keyCode == 76){
                _self.resultValue = _self.resultValue + "L";
            }else if(KeyEvent.keyCode == 77){
                _self.resultValue = _self.resultValue + "M";
            }else if(KeyEvent.keyCode == 78){
                _self.resultValue = _self.resultValue + "N";
            }else if(KeyEvent.keyCode == 79){
                _self.resultValue = _self.resultValue + "O";
            }else if(KeyEvent.keyCode == 80){
                _self.resultValue = _self.resultValue + "P";
            }else if(KeyEvent.keyCode == 81){
                _self.resultValue = _self.resultValue + "Q";
            }else if(KeyEvent.keyCode == 82){
                _self.resultValue = _self.resultValue + "R";
            }else if(KeyEvent.keyCode == 83){
                _self.resultValue = _self.resultValue + "S";
            }else if(KeyEvent.keyCode == 84){
                _self.resultValue = _self.resultValue + "T";
            }else if(KeyEvent.keyCode == 85){
                _self.resultValue = _self.resultValue + "U";
            }else if(KeyEvent.keyCode == 86){
                _self.resultValue = _self.resultValue + "V";
            }else if(KeyEvent.keyCode == 87){
                _self.resultValue = _self.resultValue + "W";
            }else if(KeyEvent.keyCode == 88){
                _self.resultValue = _self.resultValue + "X";
            }else if(KeyEvent.keyCode == 89){
                _self.resultValue = _self.resultValue + "Y";
            }else if(KeyEvent.keyCode == 96){
                _self.resultValue = _self.resultValue + "0";
            }else if(KeyEvent.keyCode == 97){
                _self.resultValue = _self.resultValue + "1";
            }else if(KeyEvent.keyCode == 98){
                _self.resultValue = _self.resultValue + "2";
            }else if(KeyEvent.keyCode == 99){
                _self.resultValue = _self.resultValue + "3";
            }else if(KeyEvent.keyCode == 100){
                _self.resultValue = _self.resultValue + "4";
            }else if(KeyEvent.keyCode == 101){
                _self.resultValue = _self.resultValue + "5";
            }else if(KeyEvent.keyCode == 102){
                _self.resultValue = _self.resultValue + "6";
            }else if(KeyEvent.keyCode == 103){
                _self.resultValue = _self.resultValue + "7";
            }else if(KeyEvent.keyCode == 104){
                _self.resultValue = _self.resultValue + "8";
            }else if(KeyEvent.keyCode == 105){
                _self.resultValue = _self.resultValue + "9";
            }else if(KeyEvent.keyCode == 108){
                //plus.nativeUI.toast("按下了回车键");
                plus.nativeUI.toast("resultValue:" + _self.resultValue);
                _self.resultValue = "0";
            }else{
                _self.resultValue = _self.resultValue + "y";
            }
        });
        /* plus.key.addEventListener('keyup',function(KeyEvent){
            console.log("松开了键:" + JSON.stringify(KeyEvent));
            console.log("松开了键:" + KeyEvent.keyCode);
        }); */
        
        // #endif   
    },
    
}
</script>

<style>

</style>

监听设备键盘事件可参考:监听事件(系统事件+设备按键事件+自定义事件)

  • 方案四:参考原生Android外接USB扫码枪,生成插件在uniapp中使用。
    分析:原生实现中是通过拦截dispatchKeyEvent(KeyEvent event)方法来自己处理键盘的输入事件。是否能封装成插件尚在研究中。
  • 方案五:使用 input 输入框控件来接收
    分析:输入框可直接接收扫码枪数据
    方案:主要通过使用 input 的 @input 和 @confirm 事件来实现
    备注:页面其实并不需要显示input控件,这里只作为接受数据的作用,所以尽可能在界面中隐藏该控件,从而达到既不影响用户体验又能实现我们的功能
<input v-if="isUseScanGun" class="jk-footer" style="width: 1px;" :value="inputValue" :focus="isFocus" maxlength="-1" 
@input="onInput" @focus="onFocus" @blur="onBlur" @confirm="onConfirm"/>

说明:具体实现过程中有一些细节问题需要处理,详情见下问题汇总

4. 问题汇总

4.1 失焦导致无法获取扫码数据

说明:输入框聚焦后扫码枪才可以把内容输出到输入框中,失去焦点将导致不能获取到扫码数据,或者说是需手动聚焦后才能获取到扫码数据。
(1) 失焦描述1:虽然设置了输入框的聚焦属性,扫码一次后就会失去焦点
解决方案:输入框失焦时重新在 @blur 事件中重新设置焦点
注意:此时需在输入事件中设置焦点属性为false,之后 @blur 事件会自动被调用,从而获取到焦点。

onInput:function(e){
    console.log("键盘输入:" + e.detail.value);
    _self.isFocus = false;          
},
onFocus:function(){
    console.log("输入框聚焦");                   
},
onBlur:function(){
    console.log("输入框失去焦点");
    _self.isFocus = true;
},

(2) 失焦描述2:点击界面上除输入框的其他位置,也会导致输入框失去焦点
解决方案:给整个页面的根节点设置点击事件,重新获取焦点。
注意:此时需设置焦点属性为false,之后 @blur 事件会自动被调用,从而获取到焦点。

<template>
    <view class="uni-flex uni-column" style="height: 100%;" @tap="setFocus()">
        <view class="uni-flex uni-row jk-bg-blue uni-center" style="height: 12%;">
            <input class="jk-footer" style="width: 1px;" :value="inputValue" :focus="isFocus" maxlength="-1" @input="input" @focus="focus" @blur="blur" @confirm="confirm"/>
        </view>
        
        <view class="uni-flex" style="height: 88%;">    
            <view class="uni-flex justify-center align-center uni-column" style="width: 100%;height: 100%;">
            </view>
        </view>
        
    </view>
</template>
setFocus:function(){
    console.log("setFocus-1: " + _self.isFocus + "");
    _self.isFocus = false;
    console.log("setFocus-2: " + _self.isFocus + "");
},

备注:经验证,还需在manifest.json配置文件关闭沉浸式,否则无法重新获取焦点(刚好项目之前因需去掉原生导航故关闭了沉浸式,所以开始的没发现需关闭沉浸式才能重新聚焦的问题)。原因未知,望知道的小伙伴告知一下。

/* 5+App特有相关 */
    "app-plus": {
        "statusbar" : {
            "immersed" : false //关闭沉浸式:解决去掉原生导航后,主内容顶到状态栏的问题;扫码枪-输入框聚焦问题(原因未知)
        },
    },

拓展:窗体默认是沉浸式(即全屏可写内容)。若不启用原生导航,手机顶部状态栏区域会被页面内容覆盖;而系统导航栏会自动处理状态栏高度占位问题,不会出现手机顶部状态栏区域被页面内容覆盖的问题。参考自定义导航栏使用注意

4.2 聚集导致屏幕弹出软键盘问题

描述:连接扫码枪后,每次聚焦操作都会引起页面弹出软键盘
尝试:使用官网的隐藏软键盘api并不能完全禁用软键盘

onFocus:function(){
    console.log("输入框聚焦");
    // 并不能完全禁用软键盘
    setTimeout(function(){
        uni.hideKeyboard();//隐藏软键盘:隐藏已经显示的软键盘,如果软键盘没有显示则不做任何操作
        // plus.key.hideSoftKeybord();//隐藏软键盘:隐藏已经显示的软键盘,如果软键盘没有显示则不做任何操作
    },250);                     
},

分析:系统设置中,连接到实体键盘时,虚拟键盘默认在屏幕上保持显示状态
解决方案:设置当连接到实体键盘时,关闭虚拟键盘(无实体键盘时才会弹出软键盘)
步骤:设置 -> 语言和输入法 -> 实体键盘 -> 关闭显示虚拟键盘

关闭软键盘.png

说明:这种系统设置的方案,仅能解决在外接设备的情况下禁用软键盘,但是在没有外接设备的情况下,输入框聚焦还是会弹出软键盘,用户体验不好。
备注:已找到解决软键盘弹出问题的办法,并替代上面的系统设置的方案。

4.3 输入法默认为中文导致扫码数据乱码问题

说明:系统默认输入法是谷歌拼音输入法(中文输入法),导致扫码扫出来中文,扫码数据不对
解决方案:切换输入法为英文输入法。
步骤:设置 -> 语言和输入法 -> 虚拟键盘 -> 管理键盘 -> 打开Android键盘(英文输入法)

切换为英文输入法.png

注意:虽然系统设置为英文输入法,但是若在登录输入时(或其他情况的输入)软键盘需要切换为中文进行手动输入,仍会导致之后的扫码乱码。解决办法就是输入后软键盘再切换为英文。
软键盘输入法.png

4.4 字符截取问题

说明:每次扫码数据都会拼接到输入框中(输入框默认最大输入长度maxlength为140),但是我们只需要每次的扫码数据。
解决方案1(双向绑定未成功):使用双向绑定,并监听每次扫码的完成事件 @confirm,获取当次扫码数据后清空输入框数据。
分析:在输入完成事件中清空输入框将导致下次扫码获取到错误数据,可能和输入框的输入事件@input 是一个字符一个字符读取有关。
解决方案2(扫码位数有局限性):设置不限制输入框的最大长度(maxlength = -1),在输入完成事件中截取最后约定的位数作为扫码结果。
分析:所要扫的有效二维码位数已固定。

onConfirm:function(e){
    console.log("点击完成按钮");
    var str = e.detail.value;
    var result = str.substring(str.length-13);//截取后13位
    uni.showToast({
        title: result
     });    
},

解决方案3(成功截取每次扫码结果):通过当前扫码输入框字符串减去上次扫码输入框字符串,获取到每次扫码结果

data() {
    return {
        lastInputValue:"",
    }
},
methods: {
    onConfirm:function(e){
        console.log("点击完成按钮");
        var currentInputValue = e.detail.value;
        var newValue = "";
        if(_self.lastInputValue == ""){
            newValue = currentInputValue;
        }else{
            //newValue = currentInputValue.replace(_self.lastInputValue,"");
            newValue = currentInputValue.substring(_self.lastInputValue.length);
        }
        _self.lastInputValue = currentInputValue;
        console.log("扫码结果:" + newValue);
        uni.showToast({
            title: newValue
        });
            
    },          
},

4.5 应用重启问题

关注帖子:在APP上接入USB扫描枪到导致重启 (UNI-APP)
描述: 当应用打开时,插拔键盘或扫码枪会导致应用重启,连接扫码枪时扫码枪恢复出厂设置也会导致应用重启
分析:可能是检测到键盘类型改变引起的,类似android中屏幕旋转导致activity销毁又重建
解决方案:先接线,后打开应用
注意:接线时,若转接头和平板连接后再连接扫码枪,无法给扫码枪供电;正确的接线顺序为,转接头和扫码枪连接后再连接平板。
备注:该方案仅能规避连接扫码枪时应用重启问题,尚未找到解决断开扫码枪时应用重启问题的方案。

插拔重启.png

更新HbuilderX版本后问题解决,经查证2.4.1.20191114版本修复了该问题。

2.4.1.20191114版本解决插拔重启问题.png

拓展:热插拔
备注:完整代码示例

<template>
    <view class="uni-flex uni-column" style="height: 100%;" @tap="setFocus()">
        <view class="uni-flex uni-row uni-bg-blue uni-center" style="height: 12%;">
            <!-- <input style="width: 1px;font-size: 15px;align-self: center;" v-model="inputValue" :focus="isFocus" maxlength="-1" @input="input" @focus="focus" @blur="blur" @confirm="confirm"/> -->
            <input style="width: 1px;font-size: 15px;align-self: center;" :value="inputValue" :focus="isFocus" maxlength="-1" @input="input" @focus="focus" @blur="blur" @confirm="confirm"/>
        </view>
        
        <view class="uni-flex" style="height: 88%;">    
            <view class="uni-flex justify-center align-center uni-column" style="width: 100%;height: 100%;">
            </view>
        </view>
        
    </view>
</template>

<script>
var _self;
export default {
    data() {
        return {
            isFocus:true,
            inputValue:"",
            lastInputValue:"",
        }
    },
    methods: {
        setFocus:function(){
            console.log("setFocus-1: " + _self.isFocus + "");
            _self.isFocus = false;
            console.log("setFocus-2: " + _self.isFocus + "");
        },
        input:function(e){
            console.log("键盘输入:" + e.detail.value);
            _self.isFocus = false;
            
        },
        focus:function(){
            console.log("输入框聚焦:" + _self.isFocus);
            // 并不能完全禁用软键盘
            setTimeout(function(){
                uni.hideKeyboard();//隐藏软键盘:隐藏已经显示的软键盘,如果软键盘没有显示则不做任何操作
                // plus.key.hideSoftKeybord();//隐藏软键盘:隐藏已经显示的软键盘,如果软键盘没有显示则不做任何操作
            },250); 
            
        },
        blur:function(){
            console.log("输入框失去焦点:" + _self.isFocus);
            _self.isFocus = true;
        },
        confirm:function(e){
            console.log("点击完成按钮");
            //(1)双向绑定来获取扫码结果:未成功
            /* var ticketNo = _self.inputValue;
            _self.inputValue = "";
            uni.showModal({
                title: ticketNo,
                content: _self.inputValue + "h"
            }); */
            
            //(2)截取扫码结果:扫码位数固定,有局限性
            /* var str = e.detail.value;
            var result = str.substring(str.length-13);//截取后13位
            console.log("扫码结果:" + newValue);
            uni.showToast({
                title: result
            }); */
            
            //(3)截取每次扫码结果:成功
            var currentInputValue = e.detail.value;
            var newValue = "";
            if(_self.lastInputValue == ""){
                newValue = currentInputValue;
            }else{
                //newValue = currentInputValue.replace(_self.lastInputValue,"");
                newValue = currentInputValue.substring(_self.lastInputValue.length);
            }
            _self.lastInputValue = currentInputValue;
            console.log("扫码结果:" + newValue);
            uni.showToast({
                title: newValue
            });
            
            
        },
    },
    onLoad:function(){
        _self = this;
    }
}
</script>

<style>

</style>

5. 使用插件—外接键盘扫描枪监听获取输入内容

(1) 在uniapp插件市场购买插件并绑定项目
(2) 在HBuilderX里找到项目,在manifest的app原生插件配置中勾选模块


插件配置.png

(3) 在代码中引用插件并调用插件功能

<template>
    <view>

        <view class="c-hint margin-l-r" style="margin-top: 10rpx;margin-bottom: 50rpx;color: #ff0000;font-size: 24rpx;">Tips:返回结果在页尾打印展示。先点击设置监听,按下数组键
            1 或者字母键 a,页面会打印返回数据,供查看数据结构。输入完成,点击 Enter 键,页面会显示拼接结果。</view>

        <view class="c-hint margin-l-r" style="margin-top: 30rpx;">tag 字段,不用理会,固定 1 就好</view>
        <input v-model="tag" class="margin-l-r" placeholder="请输入" />

        <view class="button-sp-area">
            <button type="primary" plain="true" @click="onBtn1()">设置监听</button>
        </view>

        <view class="button-sp-area">
            <button type="primary" plain="true" @click="onBtn2()">取消某个监听</button>
        </view>

        <view class="button-sp-area">
            <button type="primary" plain="true" @click="onBtn3()">获取所有监听的tag</button>
        </view>

        <view class="button-sp-area">
            <button type="primary" plain="true" @click="onBtn4()">取消所有监听</button>
        </view>

        <view class="c-hint margin-l-r text-wrapper" style="margin-top: 30rpx;width: 700rpx;word-break:break-all;">以下打印监听内容。</view>

        <view class="c-hint margin-l-r text-wrapper" style="margin-top: 30rpx;width: 700rpx;word-break:break-all;">拼接结果:{{resultStrFinal}}</view>

        <view class="c-hint margin-l-r text-wrapper" style="margin-top: 30rpx;margin-bottom: 30rpx;width: 700rpx;word-break:break-all;">{{resultStr}}</view>
    </view>
</template>

<script>
    var longyoungKeyEventListen;
    var preKeyCode = '';
    var allKeyCodeTemp = '';
    var KEY_MAP = {
        "KEYCODE_GRAVE": {
            "normalChar": "`",
            "shiftChar": "~"
        },
        "KEYCODE_0": {
            "normalChar": "0",
            "shiftChar": ")"
        },
        "KEYCODE_1": {
            "normalChar": "1",
            "shiftChar": "!"
        },
        "KEYCODE_2": {
            "normalChar": "2",
            "shiftChar": "@"
        },
        "KEYCODE_3": {
            "normalChar": "3",
            "shiftChar": "#"
        },
        "KEYCODE_4": {
            "normalChar": "4",
            "shiftChar": "$"
        },
        "KEYCODE_5": {
            "normalChar": "5",
            "shiftChar": "%"
        },
        "KEYCODE_6": {
            "normalChar": "6",
            "shiftChar": "^"
        },
        "KEYCODE_7": {
            "normalChar": "7",
            "shiftChar": "&"
        },
        "KEYCODE_8": {
            "normalChar": "8",
            "shiftChar": "*"
        },
        "KEYCODE_9": {
            "normalChar": "9",
            "shiftChar": "("
        },
        "KEYCODE_MINUS": {
            "normalChar": "-",
            "shiftChar": "_"
        },
        "KEYCODE_EQUALS": {
            "normalChar": "=",
            "shiftChar": "+"
        },
        "KEYCODE_LEFT_BRACKET": {
            "normalChar": "[",
            "shiftChar": "{"
        },
        "KEYCODE_RIGHT_BRACKET": {
            "normalChar": "]",
            "shiftChar": "}"
        },
        "KEYCODE_BACKSLASH": {
            "normalChar": "\\",
            "shiftChar": "|"
        },
        "KEYCODE_SEMICOLON": {
            "normalChar": ";",
            "shiftChar": ":"
        },
        "KEYCODE_APOSTROPHE": {
            "normalChar": "'",
            "shiftChar": "\""
        },
        "KEYCODE_COMMA": {
            "normalChar": ",",
            "shiftChar": "<"
        },
        "KEYCODE_PERIOD": {
            "normalChar": ".",
            "shiftChar": ">"
        },
        "KEYCODE_SLASH": {
            "normalChar": "/",
            "shiftChar": "?"
        },
        "KEYCODE_A": {
            "normalChar": "a",
            "shiftChar": "A"
        },
        "KEYCODE_B": {
            "normalChar": "b",
            "shiftChar": "B"
        },
        "KEYCODE_C": {
            "normalChar": "c",
            "shiftChar": "C"
        },
        "KEYCODE_D": {
            "normalChar": "d",
            "shiftChar": "D"
        },
        "KEYCODE_E": {
            "normalChar": "e",
            "shiftChar": "E"
        },
        "KEYCODE_F": {
            "normalChar": "f",
            "shiftChar": "F"
        },
        "KEYCODE_G": {
            "normalChar": "g",
            "shiftChar": "G"
        },
        "KEYCODE_H": {
            "normalChar": "h",
            "shiftChar": "H"
        },
        "KEYCODE_I": {
            "normalChar": "i",
            "shiftChar": "I"
        },
        "KEYCODE_J": {
            "normalChar": "j",
            "shiftChar": "J"
        },
        "KEYCODE_K": {
            "normalChar": "k",
            "shiftChar": "K"
        },
        "KEYCODE_L": {
            "normalChar": "l",
            "shiftChar": "L"
        },
        "KEYCODE_M": {
            "normalChar": "m",
            "shiftChar": "M"
        },
        "KEYCODE_N": {
            "normalChar": "n",
            "shiftChar": "N"
        },
        "KEYCODE_O": {
            "normalChar": "o",
            "shiftChar": "O"
        },
        "KEYCODE_P": {
            "normalChar": "p",
            "shiftChar": "P"
        },
        "KEYCODE_Q": {
            "normalChar": "q",
            "shiftChar": "Q"
        },
        "KEYCODE_R": {
            "normalChar": "r",
            "shiftChar": "R"
        },
        "KEYCODE_S": {
            "normalChar": "s",
            "shiftChar": "S"
        },
        "KEYCODE_T": {
            "normalChar": "t",
            "shiftChar": "T"
        },
        "KEYCODE_U": {
            "normalChar": "u",
            "shiftChar": "U"
        },
        "KEYCODE_V": {
            "normalChar": "v",
            "shiftChar": "V"
        },
        "KEYCODE_W": {
            "normalChar": "w",
            "shiftChar": "W"
        },
        "KEYCODE_X": {
            "normalChar": "x",
            "shiftChar": "X"
        },
        "KEYCODE_Y": {
            "normalChar": "y",
            "shiftChar": "Y"
        },
        "KEYCODE_Z": {
            "normalChar": "z",
            "shiftChar": "Z"
        }
    };
    export default {
        data() {
            return {
                resultStr: "",
                tag: "1", //不必理会,固定 1 就好
                resultStrFinal: ""
            }
        },
        onLoad() {
            let that = this;
            // #ifdef APP-PLUS
            //引用插件
            longyoungKeyEventListen = uni.requireNativePlugin('longyoung-KeyEventListen');

            // //设置监听,可设置多个,回调按 tag 区分哪个监听返回。
            // longyoungKeyEventListen.setOnKeyEventListenerLy({
            //  tag: that.tag
            // }, result => {
            //  console.log('lygg.result=' + JSON.stringify(result));
            //  if (result && result.return_code == 'SUCCESS') {
            //      if (result.return_type == 'dataBack') {//return_type=dataBack是返回数据标识,返回的数据在此获取

            //          //页面只显示1,供查看数据结构
            //          if (result.keyCode == 'KEYCODE_1') {
            //              that.resultStr += '\n' + JSON.stringify(result) + '\n';
            //          }

            //          uni.showToast({
            //              title: '成功,' + JSON.stringify(result)
            //          });
            //      }
            //  }
            // });

            // #endif
        },
        onUnload() {
            let that = this;
            // #ifdef APP-PLUS
            if (longyoungKeyEventListen) {
                //取消所有监听
                longyoungKeyEventListen.disableAllOnKeyEventListenerLy({}, result => {
                    console.log('lygg.result=' + JSON.stringify(result));
                    if (result && result.return_code == 'SUCCESS') {
                        uni.showToast({
                            title: '成功'
                        })
                    }
                });
            }
            // #endif
        },
        methods: {
            onBtn1() {
                let that = this;
                //设置监听,可设置多个,回调按 tag 区分哪个监听返回。
                longyoungKeyEventListen.setOnKeyEventListenerLy({
                    tag: that.tag //不必理会,固定 1 就好
                }, result => {
                    console.log('lygg.result=' + JSON.stringify(result));

                    if (!result.keyCode) {
                        that.resultStr += '\n' + JSON.stringify(result) + '\n';
                    }

                    if (result && result.return_code == 'SUCCESS') {
                        if (result.return_type == 'dataBack') { //return_type=dataBack是返回数据标识,返回的数据在此获取

                            //页面只显示1和a,供查看数据结构
                            if (result.keyCode == 'KEYCODE_1' || result.keyCode == 'KEYCODE_A') {
                                that.resultStr += '\n' + JSON.stringify(result) + '\n';
                            }

                            that.handleData(result);
                        }
                    }
                });
            },
            onBtn2() {
                let that = this;
                //取消某个 tag 监听
                longyoungKeyEventListen.disableOnKeyEventListenerLy({
                    tag: that.tag //不必理会,固定 1 就好
                }, result => {
                    console.log('lygg.result=' + JSON.stringify(result));
                    that.resultStr += '\n' + JSON.stringify(result) + '\n';
                    if (result && result.return_code == 'SUCCESS') {
                        uni.showToast({
                            title: '成功'
                        })
                    }
                });
            },
            onBtn3() {
                let that = this;
                //获取所有监听的tag
                longyoungKeyEventListen.getAllKeyEventListenerTagLy({}, result => {
                    console.log('lygg.result=' + JSON.stringify(result));
                    that.resultStr += '\n' + JSON.stringify(result) + '\n';
                    if (result && result.return_code == 'SUCCESS') {
                        uni.showToast({
                            title: '成功'
                        })
                    }
                });
            },
            onBtn4() {
                let that = this;
                //取消所有监听
                longyoungKeyEventListen.disableAllOnKeyEventListenerLy({}, result => {
                    console.log('lygg.result=' + JSON.stringify(result));
                    that.resultStr += '\n' + JSON.stringify(result) + '\n';
                    if (result && result.return_code == 'SUCCESS') {
                        uni.showToast({
                            title: '成功'
                        })
                    }
                });
            },

            handleData(result) {
                let that = this;
                console.log('lygg.handleData=' + JSON.stringify(result));
                if (result.return_type == 'dataBack') {
                    if (result.action == 'ACTION_UP') { //只取弹起事件
                        let keyCode = result.keyCode;
                        if (keyCode == 'KEYCODE_ENTER') { //扫码结束
                            that.resultStrFinal = allKeyCodeTemp; //最终拼接的字符串赋值
                            allKeyCodeTemp = '';
                            preKeyCode = '';
                        } else if (keyCode == 'KEYCODE_SHIFT_LEFT' || keyCode == 'KEYCODE_SHIFT_RIGHT') { //转换键
                            preKeyCode = 'KEYCODE_SHIFT_RIGHT';
                        } else {
                            if (preKeyCode == 'KEYCODE_SHIFT_RIGHT') { //转换键,拿大写
                                if (keyCode && KEY_MAP[keyCode]) {
                                    allKeyCodeTemp += KEY_MAP[keyCode].shiftChar;
                                }
                            } else {
                                if (keyCode && KEY_MAP[keyCode]) {
                                    allKeyCodeTemp += KEY_MAP[keyCode].normalChar;
                                }
                            }
                            preKeyCode = '';
                        }

                    }
                }
            }

        }
    }
</script>

<style>
    .content {
        width: 100%;
        /* padding: 20rpx; */
    }

    button {
        margin-top: 30rpx;
        margin-bottom: 30rpx;
    }

    .button-sp-area {
        margin: 0 auto;
        width: 60%;
    }

    .c-hint {
        color: #808080;
    }

    .margin-l-r {
        margin-left: 20rpx;
        margin-right: 20rpx;
    }

    .uni-list-cell {
        justify-content: flex-start
    }

    /* 列表 */
    .uni-list {
        background-color: #FFFFFF;
        position: relative;
        width: 100%;
        display: flex;
        flex-direction: column;
    }

    .uni-list:after {
        position: absolute;
        z-index: 10;
        right: 0;
        bottom: 0;
        left: 0;
        height: 1px;
        content: '';
        -webkit-transform: scaleY(.5);
        transform: scaleY(.5);
        background-color: #c8c7cc;
    }

    .uni-list::before {
        position: absolute;
        z-index: 10;
        right: 0;
        top: 0;
        left: 0;
        height: 1px;
        content: '';
        -webkit-transform: scaleY(.5);
        transform: scaleY(.5);
        background-color: #c8c7cc;
    }

    .uni-list-cell {
        position: relative;
        display: flex;
        flex-direction: row;
        justify-content: space-between;
        align-items: center;
    }

    .uni-list-cell-hover {
        background-color: #eee;
    }

    .uni-list-cell-pd {
        padding: 22upx 30upx;
    }

    .uni-list-cell-left {
        font-size: 28upx;
        padding: 0 30upx;
    }

    .uni-list-cell-db,
    .uni-list-cell-right {
        flex: 1;
    }

    .uni-list-cell::after {
        position: absolute;
        z-index: 3;
        right: 0;
        bottom: 0;
        left: 30upx;
        height: 1px;
        content: '';
        -webkit-transform: scaleY(.5);
        transform: scaleY(.5);
        background-color: #c8c7cc;
    }

    .uni-list .uni-list-cell:last-child::after {
        height: 0upx;
    }

    .uni-list-cell-last.uni-list-cell::after {
        height: 0upx;
    }

    .uni-list-cell-divider {
        position: relative;
        display: flex;
        color: #999;
        background-color: #f7f7f7;
        padding: 15upx 20upx;
    }

    .uni-list-cell-divider::before {
        position: absolute;
        right: 0;
        top: 0;
        left: 0;
        height: 1px;
        content: '';
        -webkit-transform: scaleY(.5);
        transform: scaleY(.5);
        background-color: #c8c7cc;
    }

    .uni-list-cell-divider::after {
        position: absolute;
        right: 0;
        bottom: 0;
        left: 0upx;
        height: 1px;
        content: '';
        -webkit-transform: scaleY(.5);
        transform: scaleY(.5);
        background-color: #c8c7cc;
    }

    .uni-list-cell-navigate {
        font-size: 30upx;
        padding: 22upx 30upx;
        line-height: 48upx;
        position: relative;
        display: flex;
        box-sizing: border-box;
        width: 100%;
        flex: 1;
        justify-content: space-between;
        align-items: center;
    }

    .uni-list-cell-navigate {
        padding-right: 36upx;
    }

    .uni-navigate-badge {
        padding-right: 50upx;
    }

    .uni-list-cell-navigate.uni-navigate-right:after {
        font-family: uniicons;
        content: '\e583';
        position: absolute;
        right: 24upx;
        top: 50%;
        color: #bbb;
        -webkit-transform: translateY(-50%);
        transform: translateY(-50%);
    }

    .uni-list-cell-navigate.uni-navigate-bottom:after {
        font-family: uniicons;
        content: '\e581';
        position: absolute;
        right: 24upx;
        top: 50%;
        color: #bbb;
        -webkit-transform: translateY(-50%);
        transform: translateY(-50%);
    }

    .uni-list-cell-navigate.uni-navigate-bottom.uni-active::after {
        font-family: uniicons;
        content: '\e580';
        position: absolute;
        right: 24upx;
        top: 50%;
        color: #bbb;
        -webkit-transform: translateY(-50%);
        transform: translateY(-50%);
    }

    .uni-collapse.uni-list-cell {
        flex-direction: column;
    }

    .uni-list-cell-navigate.uni-active {
        background: #eee;
    }

    .uni-list.uni-collapse {
        box-sizing: border-box;
        height: 0;
        overflow: hidden;
    }

    .uni-collapse .uni-list-cell {
        padding-left: 20upx;
    }

    .uni-collapse .uni-list-cell::after {
        left: 52upx;
    }

    .uni-list.uni-active {
        height: auto;
    }

    /*换行*/
    .text-wrapper {
        white-space: pre-wrap;
    }
</style>

(4) 重新制作自定义基座,然后选择自定义基座运行调试
(5) 开发完毕后正式云打包

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 159,015评论 4 362
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,262评论 1 292
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,727评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,986评论 0 205
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,363评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,610评论 1 219
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,871评论 2 312
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,582评论 0 198
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,297评论 1 242
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,551评论 2 246
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,053评论 1 260
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,385评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,035评论 3 236
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,079评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,841评论 0 195
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,648评论 2 274
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,550评论 2 270

推荐阅读更多精彩内容