Android軟鍵盤彈出,覆蓋h5頁面輸入框問題

北冥有愚發表於2018-11-22

移動端專案,使用vue開發 h5 表單錄入的過程中,遇到了Android軟鍵盤彈出,覆蓋 h5頁面 輸入框 問題,在此進行回顧並分享給大家


系統:Android

條件:當輸入框在可視區底部或者偏下的位置

觸發條件:輸入框獲取焦點,彈出軟鍵盤

表現:軟鍵盤 覆蓋 h5頁面中的輸入框


問題分析:

1.發現問題:當前頁面中box為flex佈局,內容為上下固定高,中間自適應(中間區域內容過多會出現滾動條,input框在wrapper的底部),input獲取焦點,手機鍵盤彈出,input未上移到可視區內,懷疑是flex佈局導致。

h5頁面 測試程式碼如下:

<html lang="en">    
    <head>
      <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
      <meta http-equiv="Content-type" content="text/html; charset=utf-8"/>
        <style>
            html,body{              
                width:100%;              
                height:100%;              
                margin:0;              
                padding:0;            
            }
            .box{               
                display:flex;               
                flex-direction:column;               
                width:100%;               
                height:100%;            
            }
            .header{               
                height:50px;               
                width:100%;               
                background:#368CDA;               
                text-align:center;               
                line-height:50px;               
                font-size:20px;               
                color:#fff;            
            }
            .wrapper{               
                flex:1;               
                overflow:auto;               
                width:100%;            
            }
            .content {              
                margin:0;              
                padding:0;            
            }
            .content li{              
                margin:0;              
                padding:0;              
                list-style:none;              
                height:150px;              
                background:#FFCC99;              
                text-align:center;              
                line-height:150px;              
                font-size:20px;              
                color:#fff;            
            }
            .content li:nth-child(2n){              
                background:#CC99CC
            }            
            .t-input{              
                width:300px;              
                height:50px;              
                border:1px solid #FF0000;            
            }
            .footer{                
                width:100%;                
                height:48px;                
                background: #368CDA;                
                text-align:center;                
                line-height:48px;                
                font-size:18px;                
                color:#fff;            
            }
        </style>
    </head>
    <body>
        <div class="box">
            <div class="header">頭部</div>
            <div class="wrapper">
                <ul class="content">
                  <li>內容區</li>
                  <li>內容區</li>
                  <li>內容區</li>
                  <li>內容區</li>
                  <li>內容區</li>
                </ul>
                <input type="text" class="t-input" placeholder="輸入框">
            </div>
            <div class="footer">儲存</div>
        </div>
    </body>
</html>
複製程式碼

2.修改佈局:去除box中的flex佈局,將wrapper、footer通過position:absolute的方式定位在頁面中,發現input依舊不上移,判定與flex佈局無關,程式碼修改如下:

<style>
    .box{    
        /*
        display:flex;
        flex-direction:column;
        */
        width:100%;
        height:100%;
        position:relative;

    }
    .wrapper{        
        /*
        flex:1;
        */
        overflow:auto;
        width:100%;        
        // 通過同時設定top、bototm,撐開wrapper,使之佔螢幕除header和footer外的剩餘高
        position:absolute;
        top:50px;
        bottom:48px;
    }
    .footer{
        width:100%;
        height:48px;
        background: #368CDA;
        text-align:center;
        line-height:48px;
        font-size:18px;
        color:#fff;
        position:absolute;
        bottom:0;
    }
</style>
複製程式碼

3.真機模擬:進行真機與電腦連線除錯,開啟chrome的chrome://inspect,(如下圖所示),發現鍵盤未彈出時html高度為512px,鍵盤彈出後html的高度為288px(減少區域的為軟鍵盤區域),懷疑是否是因為html、body設定了height:100%的自適應佈局後,高度跟隨螢幕的可用高度改變而改變導致的。

Android軟鍵盤彈出,覆蓋h5頁面輸入框問題

4.程式碼除錯:去除body的height:100%,給body新增一個正好能讓軟鍵盤彈出後遮住輸入框的高度,body高度 = 288(軟鍵盤出現後html高度)+50(輸入框高度)+48(儲存按鈕高度) ,發現鍵盤彈出遮擋著input後,input框會自動上移到可視區內,問題定位成功

解決方案:

方案1:頁面渲染完成後,通過JS動態獲取螢幕可視區高度(注:螢幕旋轉後,需重新獲取螢幕高度並賦值),並將其賦值到body的height,這樣body的高度一直都是螢幕的高度,當軟鍵盤彈出後,會將body向上推(因為body有了固定高度,不會再繼承html的自適應高度),使輸入框置到可視區內,程式碼如下:
document.body.style.height = window.screen.availHeight +'px';
複製程式碼

方案2:我們可以藉助元素的 scrollIntoViewIfNeeded() 方法,這個方法執行後如果當前元素在可視區中不可見,則會滾動瀏覽器視窗或容器元素,最終讓它可見,如果當前元素在可視區中,這個方法什麼也不做,程式碼如下:

window.addEventListener('resize', () => {     
    if (document.activeElement.tagName == 'INPUT') {         
        //延遲出現是因為有些 Android 手機鍵盤出現的比較慢
         window.setTimeout(() => {             
            document.activeElement.scrollIntoViewIfNeeded();
         }, 100);
     }
});
複製程式碼

相關文章