您好,登錄后才能下訂單哦!
這篇文章將為大家詳細(xì)講解有關(guān)html5中如何實(shí)現(xiàn)手機(jī)鍵盤(pán)彈出收起,小編覺(jué)得挺實(shí)用的,因此分享給大家做個(gè)參考,希望大家閱讀完這篇文章后可以有所收獲。
問(wèn)題
在 h6 項(xiàng)目中,我們會(huì)經(jīng)常遇到一些表單頁(yè)面,在輸入框獲取焦點(diǎn)時(shí),會(huì)自動(dòng)觸發(fā)鍵盤(pán)彈起,而鍵盤(pán)彈出在 IOS 與 Android 的 webview 中表現(xiàn)并非一致,同時(shí)當(dāng)我們主動(dòng)觸發(fā)鍵盤(pán)收起時(shí)也同樣存在差異化。
鍵盤(pán)彈出
IOS:IOS系統(tǒng) 的鍵盤(pán)處在窗口的最上層,當(dāng)鍵盤(pán)彈起時(shí),webview 的高度 height 并沒(méi)有改變,只是 scrollTop 發(fā)生變化,頁(yè)面可以滾動(dòng)。且頁(yè)面可以滾動(dòng)的最大限度為彈出的鍵盤(pán)的高度,而只有鍵盤(pán)彈出時(shí)頁(yè)面恰好也滾動(dòng)到最底部時(shí),scrollTop 的變化值為鍵盤(pán)的高度,其他情況下則無(wú)法獲取。這就導(dǎo)致在 IOS 情況下難以獲取鍵盤(pán)的真實(shí)高度。
Android: 在Android系統(tǒng)中,鍵盤(pán)也是處在窗口的最上層,鍵盤(pán)彈起時(shí),如果輸入框在靠近底部的話,就會(huì)被鍵盤(pán)擋住,只有你輸入的時(shí)候輸入框才會(huì)滾動(dòng)到可視化區(qū)域。
鍵盤(pán)收起
IOS:觸發(fā)鍵盤(pán)上的按鈕收起鍵盤(pán)或者輸入框以外的頁(yè)面區(qū)域時(shí),輸入框會(huì)失去焦點(diǎn),因此會(huì)觸發(fā)輸入框的 blur 事件;當(dāng)鍵盤(pán)收起時(shí),頁(yè)面底部會(huì)出現(xiàn)一個(gè)空白區(qū)域,頁(yè)面會(huì)被頂起。
Android: 觸發(fā)鍵盤(pán)上的按鈕收起鍵盤(pán)時(shí),輸入框并不會(huì)失去焦點(diǎn),因此不會(huì)觸發(fā)頁(yè)面的 blur 事件;觸發(fā)輸入框以外的區(qū)域時(shí),輸入框會(huì)失去焦點(diǎn),觸發(fā)輸入框的 blur 事件。
期望的結(jié)果
針對(duì)不同系統(tǒng)觸發(fā)鍵盤(pán)彈出收起時(shí)的差異化,我們希望功能流暢的同時(shí),盡量保持用戶體驗(yàn)的一致性。
對(duì)癥下藥
上面我們理清了目前市面上兩大主要系統(tǒng)的差異性,接下來(lái)就需對(duì)癥下藥了。
在 h6 中目前沒(méi)有接口可以直接監(jiān)聽(tīng)鍵盤(pán)事件,但我們可以通過(guò)分析鍵盤(pán)彈出、收起的觸發(fā)過(guò)程及表現(xiàn)形式,來(lái)判斷鍵盤(pán)是彈出還是收起的狀態(tài)。
鍵盤(pán)彈出:輸入框獲取焦點(diǎn)時(shí)會(huì)自動(dòng)觸發(fā)鍵盤(pán)的彈起動(dòng)作,因此,我們可以監(jiān)聽(tīng) focusin 事件,在里面實(shí)現(xiàn)鍵盤(pán)彈出后所需的頁(yè)面邏輯。
鍵盤(pán)收起:當(dāng)觸發(fā)其他頁(yè)面區(qū)域收起鍵盤(pán)時(shí),我們可以監(jiān)聽(tīng) focusout 事件,在里面實(shí)現(xiàn)鍵盤(pán)收起后所需的頁(yè)面邏輯。而在通過(guò)鍵盤(pán)按鈕收起鍵盤(pán)時(shí)在 ios 與 android 端存在差異化表現(xiàn),下面具體分析:
IOS:觸發(fā)了 focusout 事件,仍然通過(guò)該辦法監(jiān)聽(tīng)。
Android:沒(méi)有觸發(fā) focusout 事件。在 android 中,鍵盤(pán)的狀態(tài)切換(彈出、收起)不僅和輸入框關(guān)聯(lián),同時(shí)還會(huì)影響到 webview 高度的變化,那我們就可以通過(guò)監(jiān)聽(tīng) webview height 的變化來(lái)判斷鍵盤(pán)是否收起。
系統(tǒng)判斷
在實(shí)踐中我們可以通過(guò) userAgent 來(lái)判斷目前的系統(tǒng):
const ua = window.navigator.userAgent.toLocaleLowerCase(); const isIOS = /iphone|ipad|ipod/.test(ua); const isAndroid = /android/.test(ua);
IOS 處理
let isReset = true; //是否歸位 this.focusinHandler = () => { isReset = false; //聚焦時(shí)鍵盤(pán)彈出,焦點(diǎn)在輸入框之間切換時(shí),會(huì)先觸發(fā)上一個(gè)輸入框的失焦事件,再觸發(fā)下一個(gè)輸入框的聚焦事件 }; this.focusoutHandler = () => { isReset = true; setTimeout(() => { //當(dāng)焦點(diǎn)在彈出層的輸入框之間切換時(shí)先不歸位 if (isReset) { window.scroll(0, 0); //確定延時(shí)后沒(méi)有聚焦下一元素,是由收起鍵盤(pán)引起的失焦,則強(qiáng)制讓頁(yè)面歸位 } }, 30); }; document.body.addEventListener('focusin', this.focusinHandler); document.body.addEventListener('focusout', this.focusoutHandler);
Android 處理
const originHeight = document.documentElement.clientHeight || document.body.clientHeight; this.resizeHandler = () => { const resizeHeight = document.documentElement.clientHeight || document.body.clientHeight; const activeElement = document.activeElement; if (resizeHeight < originHeight) { // 鍵盤(pán)彈起后邏輯 if (activeElement && (activeElement.tagName === "INPUT" || activeElement.tagName === "TEXTAREA")) { setTimeout(()=>{ activeElement.scrollIntoView({ block: 'center' });//焦點(diǎn)元素滾到可視區(qū)域的問(wèn)題 },0) } } else { // 鍵盤(pán)收起后邏輯 } }; window.addEventListener('resize', this.resizeHandler);
react 封裝
在 react 中我們可以寫(xiě)一個(gè)類裝飾器來(lái)修飾表單組件。
類裝飾器:類裝飾器在類聲明之前被聲明(緊靠著類聲明)。 類裝飾器應(yīng)用于類構(gòu)造函數(shù),可以用來(lái)監(jiān)視,修改或替換類定義。
// keyboard.tsx /* * @Description: 鍵盤(pán)處理裝飾器 * @Author: hzzly * @LastEditors: hzzly * @Date: 2020-01-09 09:36:40 * @LastEditTime: 2020-01-10 12:08:47 */ import React, { Component } from 'react'; const keyboard = () => (WrappedComponent: any) => class HOC extends Component { focusinHandler: (() => void) | undefined; focusoutHandler: (() => void) | undefined; resizeHandler: (() => void) | undefined; componentDidMount() { const ua = window.navigator.userAgent.toLocaleLowerCase(); const isIOS = /iphone|ipad|ipod/.test(ua); const isAndroid = /android/.test(ua); if (isIOS) { // 上面 IOS 處理 ... } if (isAndroid) { // 上面 Android 處理 ... } } componentWillUnmount() { if (this.focusinHandler && this.focusoutHandler) { document.body.removeEventListener('focusin', this.focusinHandler); document.body.removeEventListener('focusout', this.focusoutHandler); } if (this.resizeHandler) { document.body.removeEventListener('resize', this.resizeHandler); } } render() { return <WrappedComponent {...this.props} />; } }; export default keyboard;
使用
// PersonForm.tsx @keyboard() class PersonForm extends PureComponent<{}, {}> { // 業(yè)務(wù)邏輯 ... } export default PersonForm;
關(guān)于“html5中如何實(shí)現(xiàn)手機(jī)鍵盤(pán)彈出收起”這篇文章就分享到這里了,希望以上內(nèi)容可以對(duì)大家有一定的幫助,使各位可以學(xué)到更多知識(shí),如果覺(jué)得文章不錯(cuò),請(qǐng)把它分享出去讓更多的人看到。
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。