移動web端鍵盤問題、IOS安卓機input/textarea兼容性

前言:移動web開發中,安卓和IOS的input/textarea輸入框在調用鍵盤是有差別的:安卓機鍵盤覆蓋在頁面底部;IOS機鍵盤將整個頁面向頂部推。兩種實如今真機上都會致使頁面出現某些小問題,本篇主要做用是收錄這類問題(也歡迎提供各類問題或者更好的解決方案或指出本文錯誤,共勉),我會持續更新陸續將遇到到或者身邊人遇到的總結到這裏,方便本身或者用到的人須要的時候翻出來看看。javascript

1、IOS機

(1)問題描述:

IOS 6s手機中,獲取焦點時,鍵盤會將整個頁面向頂部推,輸入完成後鍵盤收回可是頁面仍是停留在鍵盤拉起的狀態,以下圖所示:html

(2)解決方案:

0.判斷是不是IOS機

//判斷是不是安卓仍是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;
}

1.當輸入完成(輸入框失去焦點onblur)時,強制將頁面置頂

//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);
}

2、安卓機

(1)問題描述:

獲取焦點時,鍵盤會直接從底部出來覆蓋在頁面上層,若是你的輸入框恰好在頁面下方就會被彈出的鍵盤遮擋,也沒法向上滑動使其顯示,以下圖所示:ios

(2)解決思路:

1.使其能夠向上滑動顯示:

"頁面根節點"設置style樣式:web

<section id="root" style="height:100%;overflow:auto;">
html代碼佈局
...
這裏用textarea舉例  input也是一樣的
<textarea onfocus="onFocusAddr()"></textarea>
</section>

2.當輸入框得到焦點時,讓頁面滾動條至最底部:

//安卓鍵盤遮擋輸入
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);//鍵盤拉起的延遲時間
    })
}

(3)問題解決,效果以下圖:

這是原生解決,建議結合本身使用的框架作改進,如: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">
相關文章
相關標籤/搜索