移動端專案,使用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%的自適應佈局後,高度跟隨螢幕的可用高度改變而改變導致的。
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);
}
});
複製程式碼