【React】使用自定義hook解決安卓鍵盤彈起遮擋

前言

  • 在遇到要輸入input時,安卓系統的瀏覽器會彈起鍵盤但頁面原樣。ios系統彈起鍵盤後可以滾動。所以這個優化只對安卓生效。

原理

  • 安卓的鍵盤彈起就是個resize事件。通過監聽resize事件,以及判斷瀏覽器ua來進行處理。
  • 另外還有個activeElement可以拿到激活的input,通過scrollIntoView更好的來進行優化可視效果。

最終效果

  • 這個是真機連chrome進行測試,chrome看不見手機鍵盤。
    在這裏插入圖片描述

代碼

import {useState,useEffect}from 'react'

interface DomArgs{
	height: number;
	bottom: number;
}
/**
 *
 *
 * @param {string} 滾動dom
 * @param {DomArgs} 滾動dom高和底部高,異步獲取
 * @param {number} difference 滾動dom高最後需要減去的差值
 * @param {number} fixDifference 絕對定位元素,隨着鍵盤一起移動高度
 */
export function useKeyBoardSolve(name: string,domargs: DomArgs,difference: number,fixDifference: number){
	const [originHeight]=useState(document.documentElement.clientHeight||document.body.clientHeight)
	const [scrollOrigin,setScrollOrigin]=useState({
		sign:true,
		height:0,
	})
	const [origin,setOrigin]=useState({
		height:0,
		bottom:0
	})
	const resizeHandler=()=>{
		const resizeHeight = document.documentElement.clientHeight||document.body.clientHeight
		const activeElement =document.activeElement
		const scrollDom =document.querySelector<HTMLFormElement>(`.${name}`)
		const scrollHeight = scrollDom?.getBoundingClientRect().height
		if(resizeHeight<originHeight){
			if(activeElement&&(activeElement.tagName==='INPUT'||activeElement.tagName==='TEXTAREA')){
				if(scrollDom&&scrollHeight){
					setScrollOrigin({
						sign:false,
						height:originHeight-resizeHeight,
					})
					setTimeout(() => {
						activeElement.scrollIntoView({block:"center"})	
					});
				}
			}
		}else{
			if(scrollDom&&scrollHeight){
				setScrollOrigin({
					sign:true,
					height:0
				})
			}
		}
	}
	useEffect(()=>{
		setOrigin({
			height:domargs.height,
			bottom:domargs.bottom
		})
	},[domargs])
	useEffect(()=>{
		const scrollDom =document.querySelector<HTMLFormElement>(`.${name}`)
		if(scrollOrigin.sign){//原始高度
			if(scrollDom&&origin.height!==0){
				scrollDom.style.height=origin.height+'px'
				scrollDom.style.overflow='scroll'
			}
		}else{//給改變高度
			if(scrollDom){//如果鍵盤高度比dom底部高度大,應該dom原本高度減去底部高度與鍵盤高度的差
				if(origin.bottom<(scrollOrigin.height+difference+fixDifference)){
					scrollDom.style.height = origin.height-(scrollOrigin.height-origin.bottom+difference+fixDifference) +'px'
					scrollDom.style.overflow='scroll'
				}//鍵盤沒dom底部長不需要捲曲
			}
		}
	},[scrollOrigin])
	useEffect(()=>{
		const ua = window.navigator.userAgent.toLocaleLowerCase()
		// const isIOS = /iphone|ipad|ipod/.test(ua);
		const isAndroid = ua.includes('android')
		if(isAndroid){
			window.addEventListener('resize',resizeHandler)
		}
	},[])
}
  • 使用:
	useKeyBoardSolve('ant-form',useheight,parseFloat(document.documentElement.style.fontSize)*1.2,
		parseFloat(document.documentElement.style.fontSize)*2
	)
  • 註釋都有,自己看就行。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章