react在安卓中輸入框被手機(jī)鍵盤遮擋問題的解決方法
前言
React 起源于 Facebook 的內(nèi)部項(xiàng)目,因?yàn)樵摴緦?duì)市場(chǎng)上所有 JavaScript MVC 框架,都不滿意,就決定自己寫一套,用來架設(shè) Instagram 的網(wǎng)站。做出來以后,發(fā)現(xiàn)這套東西很好用,就在2013年5月開源了。
本文主要介紹了關(guān)于react在安卓輸入框被鍵盤遮擋的相關(guān)內(nèi)容,分享出來動(dòng)大家參考學(xué)習(xí),下面話不多說了,來一起看看詳細(xì)的介紹吧
問題概述
今天遇到了一個(gè)問題,在安卓手機(jī)上,當(dāng)我要點(diǎn)擊輸入“店鋪名稱”時(shí),手機(jī)軟鍵盤彈出來剛好把輸入框擋住了;擋住就算了,關(guān)鍵是頁(yè)面還不能向上滑動(dòng),整個(gè)手機(jī)窗口被壓為原來的二分之一左右;
然后
然后找了一些方案,不過不大適用,或者是有點(diǎn)麻煩;所以需要整合一下,
首先,我想一下我要實(shí)現(xiàn)的效果(2018/9/3補(bǔ)充:評(píng)論區(qū)有更加簡(jiǎn)單的實(shí)現(xiàn)方法)
想要實(shí)現(xiàn)的效果
如圖,當(dāng)手機(jī)鍵盤出現(xiàn)時(shí),頁(yè)面是可以自由滾動(dòng)的,而且當(dāng)前聚焦的輸入框往紅線處靠齊,這樣就剛好在剩下的窗口的垂直正中間,這樣就不會(huì)出現(xiàn)輸入框被擋住,看不到自己輸入的內(nèi)容了 ;
第一步,使屏幕壓小時(shí),頁(yè)面內(nèi)容可以滾動(dòng)查看
如下圖所示,黑色框代表屏幕,藍(lán)色框代表頁(yè)面大小,當(dāng)屏幕被壓小時(shí),頁(yè)面內(nèi)容必須保持原來的高度:
實(shí)現(xiàn)原理,頁(yè)面一進(jìn)來時(shí),我就獲取窗口的高度,給最外層的div設(shè)置一個(gè)最小高度,這樣就算窗口壓小了,頁(yè)面還能維持原來的高度,可以滾動(dòng)瀏覽:
let initWindowHeight=window.innerHeight let wrapDiv=document.getElementsByClassName('animated-router-forward-enter-done')[0] wrapDiv.style.minHeight =initWindowHeight+'px'
第二步,滾到紅線處
由于我們不能直接知道軟鍵盤什么時(shí)候出來,不過軟鍵盤出來的時(shí)候窗口高度會(huì)縮小,所以我們可以通過監(jiān)聽窗口大小變化事件來判斷軟鍵盤是否彈出,比如瀏覽器窗口高度突然縮小25%以上,那么我們就認(rèn)為是軟鍵盤出來了,然后我們獲取聚焦input距離頁(yè)面頂部的距離,計(jì)算距離紅線有多少距離,假設(shè)距離是60,那么我們就讓頁(yè)面向上滾動(dòng)60,這時(shí)input就剛剛好到了紅線處;
window.onresize=function(){ if(initWindowHeight-window.innerHeight>initWindowHeight/4&&document.querySelectorAll(':focus').length>0){ //offset是封裝好的一個(gè)獲取元素距離頁(yè)面頂部滾動(dòng)距離的方法 if(offset(document.querySelectorAll(':focus')[0]).top>initWindowHeight/4){ document.body.scrollTop=offset(document.querySelectorAll(':focus')[0]).top-initWindowHeight/4 } }else if(window.innerHeight-initWindowHeight<20){ document.body.scrollTop=0 } };
完整代碼
因?yàn)榭赡苡卸鄠€(gè)頁(yè)面要調(diào)用,所以我把代碼放到一個(gè)單獨(dú)的js文件中:
function pageInputScroll() { let initWindowHeight=window.innerHeight setTimeout(() => { let wrapDiv=document.getElementsByClassName('animated-router-forward-enter-done')[0] //console.log(wrapDiv.style) wrapDiv.style.minHeight =initWindowHeight+'px' }, 500); //由于我們不能直接知道軟鍵盤什么時(shí)候出來,不過軟鍵盤出來的時(shí)候窗口高度會(huì)縮小,所以我們可以通過監(jiān)聽窗口大小變化事件來判斷軟鍵盤是否彈出 window.onresize=function(){ //如果瀏覽器窗口高度縮小25%以上,就認(rèn)為是軟鍵盤出來了 if(initWindowHeight-window.innerHeight>initWindowHeight/4&&document.querySelectorAll(':focus').length>0){ if(offset(document.querySelectorAll(':focus')[0]).top>initWindowHeight/4){ document.body.scrollTop=offset(document.querySelectorAll(':focus')[0]).top-initWindowHeight/4 } }else if(window.innerHeight-initWindowHeight<20){ document.body.scrollTop=0 } }; } function offset(element) { var offest = { top: 0, left: 0 }; var _position; getOffset(element, true); return offest; // 遞歸獲取 offset, 可以考慮使用 getBoundingClientRect function getOffset(node, init) { // 非Element 終止遞歸 if (node.nodeType !== 1) { return; } _position = window.getComputedStyle(node)['position']; // position=static: 繼續(xù)遞歸父節(jié)點(diǎn) if (typeof(init) === 'undefined' && _position === 'static') { getOffset(node.parentNode); return; } offest.top = node.offsetTop + offest.top - node.scrollTop; offest.left = node.offsetLeft + offest.left - node.scrollLeft; // position = fixed: 獲取值后退出遞歸 if (_position === 'fixed') { return; } getOffset(node.parentNode); } } export {pageInputScroll};
在react頁(yè)面中引入js并調(diào)用:
import {pageInputScroll} from '../../util/pageInputScroll' ...... componentDidMount(){ pageInputScroll() }
如果只是想在安卓下使用,可以加一個(gè)判斷:
if(/Android/i.test(navigator.userAgent)){ pageInputScroll() }
效果動(dòng)圖
我在pc端的谷歌瀏覽器模擬一下實(shí)現(xiàn)的效果:
備注
offset()方法是使用js實(shí)現(xiàn)類似jquery的offset()的一個(gè)方法,參考自:原生js實(shí)現(xiàn)offset方法
總結(jié):
以上就是這篇文章的全部?jī)?nèi)容了,希望本文的內(nèi)容對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,如果有疑問大家可以留言交流,謝謝大家對(duì)腳本之家的支持。
相關(guān)文章
深入學(xué)習(xí)TypeScript 、React、 Redux和Ant-Design的最佳實(shí)踐
這篇文章主要介紹了深入學(xué)習(xí)TypeScript 、React、 Redux和Ant-Design的最佳實(shí)踐,TypeScript 增加了代碼的可讀性和可維護(hù)性,擁有活躍的社區(qū),,需要的朋友可以參考下2019-06-06在?React?中如何從狀態(tài)數(shù)組中刪除一個(gè)元素
這篇文章主要介紹了在?React?中從狀態(tài)數(shù)組中刪除一個(gè)元素,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2023-03-03react 實(shí)現(xiàn)圖片正在加載中 加載完成 加載失敗三個(gè)階段的原理解析
這篇文章主要介紹了react 實(shí)現(xiàn)圖片正在加載中 加載完成 加載失敗三個(gè)階段的,通過使用loading的圖片來占位,具體原理解析及實(shí)現(xiàn)代碼跟隨小編一起通過本文學(xué)習(xí)吧2021-05-05使用React?SSR寫Demo一學(xué)就會(huì)
這篇文章主要為大家介紹了使用React?SSR寫Demo實(shí)現(xiàn)教程示例,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-06-06詳解react使用react-bootstrap當(dāng)輪子造車
本篇文章主要介紹了詳解react使用react-bootstrap當(dāng)輪子造車,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下。2017-08-08基于Cloud?Studio構(gòu)建React完成點(diǎn)餐H5頁(yè)面(騰訊云?Cloud?Studio?實(shí)戰(zhàn)訓(xùn)練營(yíng))
最近也是有機(jī)會(huì)參與到了騰訊云舉辦的騰訊云Cloud Studio實(shí)戰(zhàn)訓(xùn)練營(yíng),借此了解了騰訊云Cloud?Studio產(chǎn)品,下面就來使用騰訊云Cloud?Studio做一個(gè)實(shí)戰(zhàn)案例來深入了解該產(chǎn)品的優(yōu)越性吧,感興趣的朋友跟隨小編一起看看吧2023-08-08React錯(cuò)誤邊界Error Boundaries詳解
錯(cuò)誤邊界是一種React組件,這種組件可以捕獲發(fā)生在其子組件樹任何位置的JavaScript錯(cuò)誤,并打印這些錯(cuò)誤,同時(shí)展示降級(jí)UI,而并不會(huì)渲染那些發(fā)生崩潰的子組件樹2022-12-12