'a'
mh-two-thousand-and-two
2024-04-12 44d2c92345cd156a59fc327b3060292a282d2893
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
import {
  plusReady
} from 'uni-shared'
import emitter from './emitter'
 
let resetTimer
let isAndroid
let osVersion
let keyboardHeight
let keyboardChangeCallback
let webviewStyle
if (__PLATFORM__ === 'app-plus') {
  plusReady(() => {
    isAndroid = plus.os.name.toLowerCase() === 'android'
    osVersion = plus.os.version
  })
  document.addEventListener('keyboardchange', function (event) {
    keyboardHeight = event.height
    keyboardChangeCallback && keyboardChangeCallback()
  }, false)
}
 
/**
 * 保证iOS点击输入框外隐藏键盘
 */
function iosHideKeyboard () { }
 
function setSoftinputTemporary (vm, reset) {
  plusReady(() => {
    const MODE_ADJUSTRESIZE = 'adjustResize'
    const MODE_ADJUSTPAN = 'adjustPan'
    const MODE_NOTHING = 'nothing'
    const currentWebview = plus.webview.currentWebview()
    // iOS 14.6 调用同步方法导致键盘弹卡顿
    const style = webviewStyle || currentWebview.getStyle() || {}
    const options = {
      mode: (reset || style.softinputMode === MODE_ADJUSTRESIZE) ? MODE_ADJUSTRESIZE : (vm.adjustPosition ? MODE_ADJUSTPAN : MODE_NOTHING),
      position: {
        top: 0,
        height: 0
      }
    }
    if (options.mode === MODE_ADJUSTPAN) {
      const rect = vm.$el.getBoundingClientRect()
      options.position.top = rect.top
      options.position.height = rect.height + (Number(vm.cursorSpacing) || 0)
    }
    currentWebview.setSoftinputTemporary(options)
  })
}
 
function setSoftinputNavBar (vm) {
  if (vm.showConfirmBar === 'auto') {
    delete vm.__softinputNavBar
    return
  }
  plusReady(() => {
    const currentWebview = plus.webview.currentWebview()
    const { softinputNavBar } = currentWebview.getStyle() || {}
    const showConfirmBar = softinputNavBar !== 'none'
    if (showConfirmBar !== vm.showConfirmBar) {
      vm.__softinputNavBar = softinputNavBar || 'auto'
      currentWebview.setStyle({
        softinputNavBar: vm.showConfirmBar ? 'auto' : 'none'
      })
    } else {
      delete vm.__softinputNavBar
    }
  })
}
 
function resetSoftinputNavBar (vm) {
  const softinputNavBar = vm.__softinputNavBar
  if (softinputNavBar) {
    plusReady(() => {
      const currentWebview = plus.webview.currentWebview()
      currentWebview.setStyle({
        softinputNavBar
      })
    })
  }
}
 
export default {
  name: 'Keyboard',
  mixins: [emitter],
  props: {
    cursorSpacing: {
      type: [Number, String],
      default: 0
    },
    showConfirmBar: {
      type: [Boolean, String],
      default: 'auto'
    },
    adjustPosition: {
      type: [Boolean, String],
      default: true
    },
    autoBlur: {
      type: [Boolean, String],
      default: false
    }
  },
  computed: {
    isApple () {
      return String(navigator.vendor).indexOf('Apple') === 0
    }
  },
  directives: {
    keyboard: {
      inserted (el, binding, vnode) {
        vnode.context.initKeyboard(el)
      }
    }
  },
  methods: {
    initKeyboard (el) {
      let focus
 
      const keyboardChange = () => {
        this.$trigger('keyboardheightchange', {}, {
          height: keyboardHeight,
          duration: 0.25
        })
        // 安卓切换不同键盘类型时会导致键盘收回,需重新设置
        if (focus && keyboardHeight === 0) {
          setSoftinputTemporary(this)
        }
        // 安卓/iOS13收起键盘时主动失去焦点
        if (this.autoBlur && focus && keyboardHeight === 0 && (isAndroid || parseInt(osVersion) >= 13)) {
          document.activeElement.blur()
        }
      }
 
      el.addEventListener('focus', () => {
        focus = true
        clearTimeout(resetTimer)
        document.addEventListener('click', iosHideKeyboard, false)
 
        if (__PLATFORM__ === 'app-plus') {
          keyboardChangeCallback = keyboardChange
          if (keyboardHeight) {
            this.$trigger('keyboardheightchange', {}, {
              height: keyboardHeight,
              duration: 0
            })
          }
          setSoftinputNavBar(this)
          setSoftinputTemporary(this)
        }
      })
 
      if (__PLATFORM__ === 'app-plus') {
        // 安卓单独隐藏键盘后点击输入框不会触发 focus 事件
        if (isAndroid) {
          el.addEventListener('click', () => {
            if (!this.disabled && focus && keyboardHeight === 0) {
              setSoftinputTemporary(this)
            }
          })
        }
        if (!isAndroid) {
          // iOS12 以下系统 focus 事件设置较迟,改在 touchstart 设置
          if (parseInt(osVersion) < 12) {
            el.addEventListener('touchstart', () => {
              if (!this.disabled && !focus) {
                setSoftinputTemporary(this)
              }
            })
          }
          // iOS 14.6 调用同步方法导致键盘弹卡顿
          if (parseFloat(osVersion) >= 14.6 && !webviewStyle) {
            plusReady(() => {
              const currentWebview = plus.webview.currentWebview()
              webviewStyle = currentWebview.getStyle() || {}
            })
          }
        }
      }
 
      const onKeyboardHide = () => {
        document.removeEventListener('click', iosHideKeyboard, false)
 
        if (__PLATFORM__ === 'app-plus') {
          keyboardChangeCallback = null
          if (keyboardHeight) {
            this.$trigger('keyboardheightchange', {}, {
              height: 0,
              duration: 0
            })
          }
          resetSoftinputNavBar(this)
          if (isAndroid) {
            // 还原安卓软键盘配置,避免影响 web-view 组件
            resetTimer = setTimeout(() => {
              setSoftinputTemporary(this, true)
            }, 300)
          }
        }
 
        // 修复ios端显示与点击位置错位的Bug by:wyq
        if (this.isApple) {
          document.documentElement.scrollTo(document.documentElement.scrollLeft, document.documentElement.scrollTop)
        }
      }
 
      el.addEventListener('blur', () => {
        // 在iOS设备上,手动调用uni.hideKeyboard(),键盘收起并且触发blur,但实际并没有blur。
        // 此时如果再点击页面其他地方会重新聚焦,此处做处理
        if (this.isApple) {
          el.blur()
        }
        focus = false
        onKeyboardHide()
      })
    }
  }
}