前言:移動web開發中,安卓和IOS的input/textarea輸入框在調用鍵盤是有差別的:安卓機鍵盤覆蓋在頁面底部;IOS機鍵盤將整個頁面向頂部推。兩種實如今真機上都會致使頁面出現某些小問題,本篇主要做用是收錄這類問題(也歡迎提供各類問題或者更好的解決方案或指出本文錯誤,共勉),我會持續更新陸續將遇到到或者身邊人遇到的總結到這裏,方便本身或者用到的人須要的時候翻出來看看。javascript
IOS 6s手機中,獲取焦點時,鍵盤會將整個頁面向頂部推,輸入完成後鍵盤收回可是頁面仍是停留在鍵盤拉起的狀態,以下圖所示:html
//判斷是不是安卓仍是ios isAndroid() { let u = navigator.userAgent; let isAndroid = u.indexOf('Android') > -1 || u.indexOf('Linux') > -1; //android終端或者uc瀏覽器 let isiOS = !!u.match(/\(i[^;]+;( U;)? CPU.+Mac OS X/); //ios終端 return isAndroid === true; }
//IOS 6s鍵盤收回 blurAddr() { if (isAndroid()) return; window.scroll(0, 0);//失焦後強制讓頁面歸位 }
缺點:vue
當頁面輸入內容較多,頁面出現滾動條時,前輸入完成後頁面立馬置頂,若是還要繼續輸入其餘內容,須要手動下滑找到輸入框再次輸入java
改進:android
//IOS 6s鍵盤收回 blurAddr() { if (isAndroid()) return; setTimeout(() => { var scrollHeight = document.documentElement.scrollTop || document.body.scrollTop || 0;//當失去焦點時,獲取網頁捲去距離 window.scrollTo(0, Math.max(scrollHeight - 1, 0));//強制重置滾動位置 },100); }
獲取焦點時,鍵盤會直接從底部出來覆蓋在頁面上層,若是你的輸入框恰好在頁面下方就會被彈出的鍵盤遮擋,也沒法向上滑動使其顯示,以下圖所示:ios
"頁面根節點"設置style樣式:web
<section id="root" style="height:100%;overflow:auto;"> html代碼佈局 ... 這裏用textarea舉例 input也是一樣的 <textarea onfocus="onFocusAddr()"></textarea> </section>
//安卓鍵盤遮擋輸入 onFocusAddr() { if (!isAndroid()) return;//判斷是不是安卓機 setTimeout(() => { let div = document.getElementById("root");//獲取根節點 div.scrollTop = div.scrollHeight;//滾動條至底(這裏沒有寫的很嚴謹,須要減去輸入框自身高offsetHeight,效果都同樣) }, 500);//鍵盤拉起的延遲時間 }
缺點:移動web開發
很明顯,這個方法不通用,須要給DOM節點綁定id,複用麻煩瀏覽器
改進:app
//安卓鍵盤遮擋輸入 onFocusAddr() { if (!isAndroid()) return;//判斷是不是安卓機 window.addEventListener('resize',()=>{ setTimeout(() => { document.activeElement.scrollIntoViewIfNeeded(); //document.activeElement:文檔中當前得到焦點的元素。scrollIntoViewIfNeeded():若是元素不在可見區將其滾動到瀏覽器窗口的可見區域,負責不動,scrollIntoView()的變體。 }, 0);//鍵盤拉起的延遲時間 }) }
這是原生解決,建議結合本身使用的框架作改進,如:angularJs,vue框架能夠封裝成指令,使用更方便,如:
vue中:
directive.js:
import tools from '../../common/utils/tools'; function directives(Vue) { //form表單輸入鍵盤和滾動問題的兼容性處理 Vue.directive('compatible', (el, binding) => { el.onfocus = () => { //安卓得到焦點時鍵盤遮擋輸入 if (!tools.isAndroid()) return;//判斷是不是安卓機 window.addEventListener('resize', () => { setTimeout(() => { el.scrollIntoViewIfNeeded(); //document.activeElement:文檔中當前得到焦點的元素。 //scrollIntoViewIfNeeded():若是元素不在可見區將其滾動到瀏覽器窗口的可見區域,負責不動,scrollIntoView()的變體。 }, 0);//鍵盤拉起的延遲時間 }) }; el.onblur = () => { //IOS 6s鍵盤收回時強制置頂 if (tools.isAndroid()) return; setTimeout(() => { //當失去焦點時,獲取網頁捲去距離 var scrollHeight = document.documentElement.scrollTop || document.body.scrollTop || 0; //強制重置滾動位置 window.scrollTo(0, Math.max(scrollHeight - 1, 0)); } ,100); }; }); //禁止輸入表情 Vue.directive('no-emoji', (el, binding) => { // eslint-disable-next-line no-useless-escape var regStr = /[\uD83C|\uD83D|\uD83E][\uDC00-\uDFFF][\u200D|\uFE0F]|[\uD83C|\uD83D|\uD83E][\uDC00-\uDFFF]|[0-9|*|#]\uFE0F\u20E3|[0-9|#]\u20E3|[\u203C-\u3299]\uFE0F\u200D|[\u203C-\u3299]\uFE0F|[\u2122-\u2B55]|\u303D|[\A9|\AE]\u3030|\uA9|\uAE|\u3030/ig; if (regStr.test(el.value)) { el.value = (el.value.replace(regStr, '')).trim(); } el.focus(); }); } export default directives;
main.js:
import directive from './directive/directive'; //全局引用 Vue.use(directive);
form.vue:
<input type="text" maxlength="11" placeholder="請輸入手機號" v-compatible v-no-emoji v-model="submitInfo.phone" >
ng中:
directive.js:
angular.module("ngDirective", ["service"]) //IOS 6s鍵盤收回時強制置頂 .directive("toScrollTop", () => { return { controller: ["$scope", "$element", ($scope, $element) => { $element.bind("blur", (event) => { if (comService.isAndroid()) { setTimeout(() => { var scrollHeight = document.documentElement.scrollTop || document.body.scrollTop || 0; window.scrollTo(0, Math.max(scrollHeight - 1, 0)); }, 100); } }); } }; }]) //安卓得到焦點時鍵盤遮擋輸入 .directive("keyboardDiscover", ["comService", (comService) => { return { controller: ["$scope", "$element", ($scope, $element) => { $element.bind("focus", (event) => { if (comService.isAndroid()) { window.addEventListener('resize', () => { setTimeout(() => { $element.scrollIntoViewIfNeeded(); }, 0);//鍵盤拉起的延遲時間 }); } }); }] }; }]);
app.js:
import directive from './directive/ngDirective.js'; //全局注入 angular.module("app", [ ... "ngDirective" ])
form.html:
<input type="text" placeholder="請輸入手機號" to-scroll-top keyboard-discover ng-model="submitInfo.phone" maxlength="11">