2024-1.19 软键盘功能

业务需求:由于甲方想要一个触摸使用后台管理系统,需要用到软件盘功能;

没开发过软件盘第一次软键盘开发踩坑史。。。

使用输入框没问题,下拉选择至今还有一个需要优化的点存在;

好接下来开始附上图文代码;

这是基于tdesign-vue-next和simple-keyboard开发的功能

写一个软件盘功能的组件,需引入软件盘插件

<template>
  <div :class="keyboardClass"></div>
</template>
<script>
  import Keyboard from 'simple-keyboard'
  import 'simple-keyboard/build/css/index.css'
  import layout from 'simple-keyboard-layouts/build/layouts/chinese' // 中文输入法
  export default {
    name: 'SimpleKeyboard',
    props: {
      keyboardClass: {
        default: 'simple-keyboard',
        type: String,
      },
      input: {
        default: '',
      },
      maxLength: {
        default: ''
      },
    },
    data: () => ({
      keyboard: null,
      displayDefault: {
        '{bksp}': 'backspace',
        '{lock}': 'caps',
        '{enter}': '> enter',
        '{tab}': 'tab',
        '{shift}': 'shift',
        '{change}': '英文',
        '{space}': ' ',
        '{clear}': '清空',
        '{close}': '关闭',
      },
    }),
    mounted() {
      this.keyboard = new Keyboard(this.keyboardClass, {
        onChange: this.onChange,
        onKeyPress: this.onKeyPress,
        layoutCandidates: null,
        layout: {
          // 默认布局
          default: [
            '` 1 2 3 4 5 6 7 8 9 0 - = {bksp}',
            '{tab} q w e r t y u i o p [ ] \\',
            "{lock} a s d f g h j k l ; ' {enter}",
            '{shift} z x c v b n m , . / {clear}',
            '{change} {space} {close}',
          ],
          // shift布局
          shift: [
            '~ ! @ # $ % ^ & * ( ) _ + {bksp}',
            '{tab} Q W E R T Y U I O P { } |',
            '{lock} A S D F G H J K L : " {enter}',
            '{shift} Z X C V B N M < > ? {clear}',
            '{change} {space} {close}',
          ],
        },
        // 按钮展示文字
        display: this.displayDefault,
        // 按钮样式
        buttonTheme: [{
            class: 'hg-red close',
            buttons: '{close}',
          },
          {
            class: 'change',
            buttons: '{change}',
          },
        ],
        // 输入限制长度
        maxLength: this.maxLength,
      })
    },
    methods: {
      onChange(input) {
        this.keyboard.setInput(input)
        this.$emit('onChange', input)
      },
      // 点击键盘
      onKeyPress(button, $event) {
        console.log(button)
        // 点击关闭
        if (button === '{close}') {
          // let keyboard = $event.path[3]
          // 子组件调用父组件的关闭按钮方法
          this.$parent.closekeyboard()
          // keyboard.style.visibility = 'hidden'
          return false
        } else if (button === '{change}') {
          // 切换中英文输入法
          if (this.keyboard.options.layoutCandidates !== null) {
            // this.$set(this.displayDefault, '{change}', '英文')
            this.displayDefault['{change}'] = '英文'
            // 切换至英文
            this.keyboard.setOptions({
              layoutCandidates: null,
              display: this.displayDefault,
            })
          } else {
            // 切换至中文
            // this.$set(this.displayDefault, '{change}', '中文')
            this.displayDefault['{change}'] = '中文'
            this.keyboard.setOptions({
              layoutCandidates: layout.layoutCandidates,
              display: this.displayDefault,
            })
          }
        } else if (button === '{clear}') {
          this.keyboard.clearInput()
        } else {
          let value =
            $event.target.offsetParent.parentElement.children[0].children[0].value
          // 输入框有默认值时,覆写
          if (value) {
            this.keyboard.setInput(value)
          }
          this.$emit('onKeyPress', button)
        }
        if (button === '{shift}' || button === '{lock}') this.handleShift()
      },
      // 切换shift/默认布局
      handleShift() {
        let currentLayout = this.keyboard.options.layoutName
        let shiftToggle = currentLayout === 'default' ? 'shift' : 'default'
        this.keyboard.setOptions({
          layoutName: shiftToggle,
        })
      },
    },
    watch: {
      input(input) {
        this.keyboard.setInput(input)
      },
    },
  }

</script>
<style lang="less">
  @deep: ~'>>>';

  .simple_keyboard {
    position: fixed;
    width: 100%;
    bottom: 0;
    left: 0;
    z-index: 9999;
  }

  .hg-theme-default {
    width: 100%;

    .hg-button {
      &.hg-red {
        background: #2d98ff;
        color: white;

        &.close {
          max-width: 200px;
        }
      }

      &.change {
        max-width: 200px;
      }
    }
  }

</style>

引用组件:

以下先拿t-input当例子(换成e-input 或者input都可以):

<t-input v-model="form.spell" @focus="onInputFocus('spell')" style="width: 550px !important" placeholder="拼音缩写" />

//页面上显示组件,先是隐藏的状态,唤起输入状态时再显示
<div class="simple_keyboard" v-show="showKeyboard">
    <SimpleKeyboard ref="SimpleKeyboard" @onChange="onChangeKeyboard" />
</div>


引入组件:
import SimpleKeyboard from '../../components/simpleKeyboard.vue';

changeIpt: '',
showKeyboard: false,


// inpuit获取焦点显示虚拟键盘
  onInputFocus(e) {
    this.showKeyboard = true
    this.changeIpt = e
    // 父组件调用子组件的方法
    this.$refs.SimpleKeyboard.onKeyPress('{clear}')
},

// 给输入框赋值
      onChangeKeyboard(input) {
        if (this.changeIpt == 'name') {
          this.form.name = input
          
        } else {
          this.form.spell = input
        }
      },

// 点击关闭隐藏键盘 这里子组件里会调用到
      closekeyboard() {
        this.showKeyboard = false
      }

好,接下来展示下拉选择的用法:

<t-select
            ref="select"
            v-model="package"
            value-type="object"
            filterable
            :options="list"
            :keys="{ value: 'id', label: 'packageName' }"
            placeholder="通过中文/拼音首字母检索"
            :loading="loading"
            reserve-keyword
            style="width: 100%"
            :filter="filterMethod"
            @focus="onInputFocus('package')"
            @change="focusChange"
            @click="focusClick"
            @search="remoteMethod"
          >
            <option v-for="item in list" :key="item.id" :label="item.packageName" :value="item.id"></option>
          </t-select>





    focusChange() {
      if (this.showKeyboard) {
        this.$refs.select.blur();
        this.showKeyboard = false;
        const byClass = document.getElementsByClassName('t-popup')[0].style;
        byClass.cssText = 'display:none !important;';
      }
    },
    focusClick() {
      if (!this.showKeyboard) {
        this.$refs.select.focus();
        this.showKeyboard = true;
      }
    },
    // inpuit获取焦点显示虚拟键盘
    onInputFocus(e) {
      this.showKeyboard = true;
      this.changeIpt = e;
      // 父组件调用子组件的方法
      this.$refs.SimpleKeyboard.onKeyPress('{clear}');
    },
    // 给输入框赋值
    onChangeKeyboard(input) {
      if (document.getElementsByClassName('t-popup')[0]) {
        const codeStatusSet = setInterval(() => {
          const byClass = document.getElementsByClassName('t-popup')[0].style;
          byClass.cssText = 'display:block !important;transform:translate3d(140px, 356.25px, 0px);';
          clearInterval(codeStatusSet);
        }, 500);
        if (this.changeIpt == 'package') {
          this.package = '';
          this.package = input;
        }
      }
      this.remoteMethod(input);
    },
    // 点击关闭隐藏键盘
    closekeyboard() {
      this.showKeyboard = false;
    },

    remoteMethod(searchStr) {
      this.loading = true;
      this.list = [];
      this.dataList(searchStr);
    },
    filterMethod(search, option) {
      return option.packageName.indexOf(search) !== -1 ||     option.nameFirstSpell.indexOf(search) !== -1;
    },

这里讲下拉选择的坑在哪:

1.唤起下拉框方法找了好久的解决方案,解决了唤起的问题;但是下拉框唤起来后,点击软键盘输入要远程搜索的内容的时候就隐藏了,我用js语句动态唤起的;问题点就是定位的样式是写死的,兼容上有问题,如果把定位的样式做成动态的就没问题了;目前还没有去做这个优化;

希望能给到有需要的朋友们一点参考叭;

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值