H5軟鍵盤兼容方案

可能這些是你想要的H5軟鍵盤兼容方案

前言

輸入框獲取焦點晦鞋,軟鍵盤彈起,要求輸入框吸附(或頂)在輸入法框上棺克。需求很明確悠垛,看似很簡單,其實不然娜谊。從實驗過一些機型上看确买,發(fā)現(xiàn)主要存在以下問題:

在?Android?和?IOS?上,獲知軟鍵盤彈起和收起狀態(tài)存在差異纱皆,且頁面?webview?表現(xiàn)不同拇惋。

在IOS12?上,微信版本?v6.7.4?及以上抹剩,輸入框獲取焦點,鍵盤彈起蓉坎,頁面(webview)整體往上滾動澳眷,當(dāng)鍵盤收起后,不回到原位蛉艾,導(dǎo)致鍵盤原來所在位置是空白的钳踊。

在?IOS?上,使用第三方輸入法勿侯,高度計算存在偏差拓瞪,導(dǎo)致在有些輸入法彈起,將輸入框擋住一部分助琐。

在有些瀏覽器上使用一些操作技巧祭埂,還是存在輸入框被輸入法遮擋。

下面就上述發(fā)現(xiàn)的問題兵钮,逐個探索一下解決方案蛆橡。

獲知軟鍵盤彈起和收起狀態(tài)

獲知軟鍵盤的彈起還是收起狀態(tài)很重要,后面的兼容處理都要以此為前提掘譬。然而泰演,H5?并沒有直接監(jiān)聽軟鍵盤的原生事件,只能通過軟鍵盤彈起或收起葱轩,引發(fā)頁面其他方面的表現(xiàn)間接監(jiān)聽睦焕,曲線救國藐握。并且,在?IOS?和?Android上的表現(xiàn)不盡相同垃喊。

IOS 軟鍵盤彈起表現(xiàn)

在?IOS?上猾普,輸入框(input、textarea?或 富文本)獲取焦點缔御,鍵盤彈起抬闷,頁面(webview)并沒有被壓縮,或者說高度(height)沒有改變耕突,只是頁面(webview)整體往上滾了笤成,且最大滾動高度(scrollTop)為軟鍵盤高度。

Android 軟鍵盤彈起表現(xiàn)

同樣眷茁,在?Android?上炕泳,輸入框獲取焦點,鍵盤彈起上祈,但是頁面(webview)高度會發(fā)生改變培遵,一般來說,高度為可視區(qū)高度(原高度減去軟鍵盤高度)登刺,除了因為頁面內(nèi)容被撐開可以產(chǎn)生滾動籽腕,webview?本身不能滾動。

IOS 軟鍵盤收起表現(xiàn)

觸發(fā)軟鍵盤上的“收起”按鈕鍵盤或者輸入框以外的頁面區(qū)域時纸俭,輸入框失去焦點皇耗,軟鍵盤收起。

Android 軟鍵盤收起表現(xiàn)

觸發(fā)輸入框以外的區(qū)域時揍很,輸入框失去焦點郎楼,軟鍵盤收起。但是窒悔,觸發(fā)鍵盤上的收起按鈕鍵盤時呜袁,輸入框并不會失去焦點,同樣軟鍵盤收起简珠。

監(jiān)聽軟鍵盤彈起和收起


綜合上面鍵盤彈起和收起在?IOS?和?Android?上的不同表現(xiàn)阶界,我們可以分開進行如下處理來監(jiān)聽軟鍵盤的彈起和收起:

在?IOS?上,監(jiān)聽輸入框的?focus?事件來獲知軟鍵盤彈起聋庵,監(jiān)聽輸入框的?blur?事件獲知軟鍵盤收起荐操。

在?Android?上,監(jiān)聽?webview?高度會變化珍策,高度變小獲知軟鍵盤彈起托启,否則軟鍵盤收起。

//?判斷設(shè)備類型

var?judgeDeviceType?=?function?()?{

??var?ua?=?window.navigator.userAgent.toLocaleLowerCase();

??var?isIOS?=?/iphone|ipad|ipod/.test(ua);

??var?isAndroid?=?/android/.test(ua);

??return?{

????isIOS:?isIOS,

????isAndroid:?isAndroid

??}

}()

//?監(jiān)聽輸入框的軟鍵盤彈起和收起事件

function?listenKeybord($input)?{

??if?(judgeDeviceType.isIOS)?{

????//?IOS?鍵盤彈起:IOS?和?Android?輸入框獲取焦點鍵盤彈起

????$input.addEventListener('focus',?function?()?{

??????console.log('IOS?鍵盤彈起啦攘宙!');

??????//?IOS?鍵盤彈起后操作

????},?false)

????//?IOS?鍵盤收起:IOS?點擊輸入框以外區(qū)域或點擊收起按鈕屯耸,輸入框都會失去焦點拐迁,鍵盤會收起,

????$input.addEventListener('blur',?()?=>?{

??????console.log('IOS?鍵盤收起啦疗绣!');

??????//?IOS?鍵盤收起后操作

????})

??}

??//?Andriod?鍵盤收起:Andriod?鍵盤彈起或收起頁面高度會發(fā)生變化线召,以此為依據(jù)獲知鍵盤收起

??if?(judgeDeviceType.isAndroid)?{

????var?originHeight?=?document.documentElement.clientHeight?||?document.body.clientHeight;

????window.addEventListener('resize',?function?()?{

??????var?resizeHeight?=?document.documentElement.clientHeight?||?document.body.clientHeight;

??????if?(originHeight?<?resizeHeight)?{

????????console.log('Android?鍵盤收起啦!');

????????//?Android?鍵盤收起后操作

??????}?else?{

????????console.log('Android?鍵盤彈起啦多矮!');

????????//?Android?鍵盤彈起后操作

??????}

??????originHeight?=?resizeHeight;

????},?false)

??}

}

var?$inputs?=?document.querySelectorAll('.input');

for?(var?i?=?0;?i?<?$inputs.length;?i++)?{

??listenKeybord($inputs[i]);

}

彈起軟鍵盤始終讓輸入框滾動到可視區(qū)

有時我們會做一個輸入表單缓淹,有很多輸入項,輸入框獲取焦點塔逃,彈起軟鍵盤讯壶。當(dāng)輸入框位于頁面下部位置時,在?IOS?上湾盗,會將?webview?整體往上滾一段距離伏蚊,使得該獲取焦點的輸入框自動處于可視區(qū),而在?Android?則不會這樣格粪,它只會改變頁面高度躏吊,而不會去滾動到當(dāng)前焦點元素到可視區(qū)。

由于上面已經(jīng)實現(xiàn)監(jiān)聽?IOS?和?Android?鍵盤彈起和收起帐萎,在這里比伏,只需在?Android?鍵盤彈起后,將焦點元素滾動(scrollIntoView())到可視區(qū)疆导。查看效果凳怨,可以戳這里。

//?獲取到焦點元素滾動到可視區(qū)

function?activeElementScrollIntoView(activeElement,?delay)?{

??var?editable?=?activeElement.getAttribute('contenteditable')

??//?輸入框是鬼、textarea或富文本獲取焦點后沒有將該元素滾動到可視區(qū)

??if?(activeElement.tagName?==?'INPUT'?||?activeElement.tagName?==?'TEXTAREA'?||?editable?===?''?||?editable)?{

????setTimeout(function?()?{

??????activeElement.scrollIntoView();

????},?delay)

??}

}

//?...

//?Android?鍵盤彈起后操作

activeElementScrollIntoView($input,?1000);

//?...

喚起純數(shù)字軟鍵盤

上面的表單輸入框有要求輸入電話號碼,類似這樣就要彈出一個數(shù)字軟鍵盤了紫新,既然說到了軟鍵盤兼容均蜜,在這里就安插一下。比較好的解決方案如下:

<p>請輸入手機號</p>

<input?type="tel"?novalidate="novalidate"?pattern="[0-9]*"?class="input">

type="tel"芒率, 是?HTML5?的一個屬性囤耳,表示輸入框類型為電話號碼,在?Android?和?IOS?上表現(xiàn)差不多偶芍,都會有數(shù)字鍵盤充择,但是也會有字母,略顯多余匪蟀。

pattern="[0-9]"椎麦,?pattern?用于驗證表單輸入的內(nèi)容,通常HTML5?的?type?屬性材彪,比如?email观挎、tel琴儿、number、data類嘁捷、url?等造成,已經(jīng)自帶了簡單的數(shù)據(jù)格式驗證功能了,加上?pattern后雄嚣,前端部分的驗證更加簡單高效了晒屎。IOS?中,只有?[0-9]*?才可以調(diào)起九宮格數(shù)字鍵盤缓升,\d?無效鼓鲁,Android 4.4?以下(包括X5內(nèi)核),兩者都調(diào)起數(shù)字鍵盤仔沿。

novalidate="novalidate"坐桩,novalidate?屬性規(guī)定當(dāng)提交表單時不對其進行驗證,由于?pattern?校驗兼容性不好封锉,可以不讓其校驗绵跷,只讓其喚起純數(shù)字鍵盤,校驗工作由?js?去做成福。

兼容 IOS12 + V6.7.4+

如果你在用?IOS12?和?V6.7.4+版本的微信瀏覽器打開上面表單輸入的demo?碾局,就會驚奇的發(fā)現(xiàn)鍵盤收起后,原本被滾動頂起的頁面并沒有回到底部位置奴艾,導(dǎo)致原來鍵盤彈起的位置“空”了净当。

其實這是?Apple?在?IOS?的?bug,會出現(xiàn)在所有的?Xcode10?打包的IOS12?的設(shè)備上蕴潦。微信官方已給出解決方案像啼,只需在軟鍵盤收起后,將頁面(webview)滾回到窗口最底部位置(clientHeight位置)潭苞。修復(fù)后的上面表單輸入?demo?可以戳這里

console.log('IOS?鍵盤收起啦忽冻!');

//?IOS?鍵盤收起后操作

//?微信瀏覽器版本6.7.4+IOS12會出現(xiàn)鍵盤收起后,視圖被頂上去了沒有下來

var?wechatInfo?=?window.navigator.userAgent.match(/MicroMessenger\/([\d\.]+)/i);

if?(!wechatInfo)?return;

var?wechatVersion?=?wechatInfo[1];

var?version?=?(navigator.appVersion).match(/OS?(\d+)_(\d+)_?(\d+)?/);

if?(+wechatVersion.replace(/\./g,?'')?>=?674?&&?+version[1]?>=?12)?{

??setTimeout(function?()?{

????window.scrollTo(0,?Math.max(document.body.clientHeight,?document.documentElement.clientHeight));

??})

}

兼容第三方輸入法

上面說了那么多此疹,其實已經(jīng)把?H5?聊天輸入框的坑填了一大半了僧诚,接下來就先看下聊天輸入框的基本HTML結(jié)構(gòu)

<div?class="chat__content">

??<div>

????<p>一些聊天內(nèi)容1</p>

??</div>

??<!--?省略幾千行聊天內(nèi)容?-->

</div>

<div?class="input__content">

??<div?class="input"?contenteditable="true"></div>

??<button>發(fā)送</button>

</div>

樣式

/*?省略一些樣式?*/

.chat__content?{

??height:?calc(100%?-?40px);

??margin-bottom:?40px;

??overflow-y:?auto;

??overflow-x:?hidden;

}

.input__content?{

??display:?flex;

??height:?40px;

??position:?absolute;

??left:?0;

??right:?0;

??bottom:?0;

??align-items:?center;

}

/*?省略一些樣式?*/

很簡單,就是劃分內(nèi)容區(qū)和輸入?yún)^(qū)蝗碎,輸入?yún)^(qū)是絕對定位湖笨,按照上面表單輸入demo?的做法,確實大部分?Android?瀏覽器是沒問題的蹦骑,但是測試在IOS?上慈省,UC?瀏覽器配合原生輸入法和第三方輸入法(比如搜狗輸入法),輸入框都會被完全擋酌吖健辫呻;QQ?瀏覽器或微信瀏覽器清钥,配合第三方輸入法,輸入框會被遮住一半放闺;百度瀏覽器配合第三方輸入法輸入框也會被完全遮住祟昭。查看效果可以用相應(yīng)瀏覽器中訪問這里。

在?UC?瀏覽器上怖侦,軟鍵盤彈起后篡悟,瀏覽器上面的標題欄高度就有個高度變小延時動態(tài)效果,這樣導(dǎo)致?webview?往下滾了一點匾寝,底部輸入框滾到了非可視區(qū)搬葬。

? 而對于第三方輸入法,猜測本身是由于輸入法面板彈起后高度計算有誤艳悔,導(dǎo)致?webview?初始滾動定位有誤急凰。其實這兩點都是?webview?滾動不到位造成的〔履辏可以讓軟鍵盤彈起后抡锈,讓焦點元素再次滾到可視區(qū),強迫?webview滾到位乔外。

???console.log('Android?鍵盤彈起啦床三!');

???//?Android?鍵盤彈起后操作

???activeElementScrollIntoView($input,?1000);

兼容 Android 小米瀏覽器的 Hack 方案

在?Android?的小米瀏覽器上,應(yīng)用上面的方案杨幼,發(fā)現(xiàn)聊天輸入框還是被遮擋得嚴嚴實實撇簿,scrollIntoView()?仍然紋絲不動。所以猜測差购,其實是滾到底了四瘫,軟鍵盤彈起,頁面實現(xiàn)高度大于可視區(qū)高度欲逃,這樣只能在軟鍵盤彈起后找蜜,強行增加頁面高度,使輸入框可以顯示出來暖夭。綜合上面兼容第三方輸入法,查看效果可以戳這里

???//?Andriod?鍵盤收起:Andriod?鍵盤彈起或收起頁面高度會發(fā)生變化撵孤,以此為依據(jù)獲知鍵盤收起

???if?(judgeDeviceType.isAndroid)?{

?????var?originHeight?=?document.documentElement.clientHeight?||?document.body.clientHeight;

?????window.addEventListener('resize',?function?()?{

???????var?resizeHeight?=?document.documentElement.clientHeight?||?document.body.clientHeight;

???????if?(originHeight?<?resizeHeight)?{

?????????console.log('Android?鍵盤收起啦迈着!');

?????????//?Android?鍵盤收起后操作

?????????//?修復(fù)小米瀏覽器下,輸入框依舊被輸入法遮擋問題

?????????if?(judgeDeviceType.isMiuiBrowser)?{

???????????document.body.style.marginBottom?=?'0px';

?????????}

???????}?else?{

?????????console.log('Android?鍵盤彈起啦邪码!');

?????????//?Android?鍵盤彈起后操作

?????????//?修復(fù)小米瀏覽器下裕菠,輸入框依舊被輸入法遮擋問題

?????????if?(judgeDeviceType.isMiuiBrowser)?{

???????????document.body.style.marginBottom?=?'40px';

?????????}

?????????activeElementScrollIntoView($input,?1000);

???????}

???????originHeight?=?resizeHeight;

?????},?false)

???}

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市闭专,隨后出現(xiàn)的幾起案子奴潘,更是在濱河造成了極大的恐慌旧烧,老刑警劉巖,帶你破解...
    沈念sama閱讀 210,914評論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件画髓,死亡現(xiàn)場離奇詭異掘剪,居然都是意外死亡,警方通過查閱死者的電腦和手機奈虾,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 89,935評論 2 383
  • 文/潘曉璐 我一進店門夺谁,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人肉微,你說我怎么就攤上這事匾鸥。” “怎么了碉纳?”我有些...
    開封第一講書人閱讀 156,531評論 0 345
  • 文/不壞的土叔 我叫張陵勿负,是天一觀的道長。 經(jīng)常有香客問我劳曹,道長奴愉,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,309評論 1 282
  • 正文 為了忘掉前任厚者,我火速辦了婚禮躁劣,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘库菲。我一直安慰自己账忘,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 65,381評論 5 384
  • 文/花漫 我一把揭開白布熙宇。 她就那樣靜靜地躺著鳖擒,像睡著了一般。 火紅的嫁衣襯著肌膚如雪烫止。 梳的紋絲不亂的頭發(fā)上蒋荚,一...
    開封第一講書人閱讀 49,730評論 1 289
  • 那天,我揣著相機與錄音馆蠕,去河邊找鬼期升。 笑死,一個胖子當(dāng)著我的面吹牛互躬,可吹牛的內(nèi)容都是我干的播赁。 我是一名探鬼主播,決...
    沈念sama閱讀 38,882評論 3 404
  • 文/蒼蘭香墨 我猛地睜開眼吼渡,長吁一口氣:“原來是場噩夢啊……” “哼容为!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,643評論 0 266
  • 序言:老撾萬榮一對情侶失蹤坎背,失蹤者是張志新(化名)和其女友劉穎替劈,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體得滤,經(jīng)...
    沈念sama閱讀 44,095評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡陨献,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,448評論 2 325
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了耿戚。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片湿故。...
    茶點故事閱讀 38,566評論 1 339
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖膜蛔,靈堂內(nèi)的尸體忽然破棺而出坛猪,到底是詐尸還是另有隱情,我是刑警寧澤皂股,帶...
    沈念sama閱讀 34,253評論 4 328
  • 正文 年R本政府宣布墅茉,位于F島的核電站,受9級特大地震影響呜呐,放射性物質(zhì)發(fā)生泄漏就斤。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 39,829評論 3 312
  • 文/蒙蒙 一蘑辑、第九天 我趴在偏房一處隱蔽的房頂上張望洋机。 院中可真熱鬧,春花似錦洋魂、人聲如沸绷旗。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,715評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽衔肢。三九已至,卻和暖如春豁翎,著一層夾襖步出監(jiān)牢的瞬間角骤,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,945評論 1 264
  • 我被黑心中介騙來泰國打工心剥, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留邦尊,地道東北人。 一個月前我還...
    沈念sama閱讀 46,248評論 2 360
  • 正文 我出身青樓优烧,卻偏偏與公主長得像蝉揍,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子匙隔,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 43,440評論 2 348