当最底部的输入框在安卓端会被遮住,而不会跟随键盘往上移动,
input.tsx
首先在input获取焦点的是,获取它在屏幕的位置
import { Platform, StyleSheet, Text, TouchableOpacity, TouchableWithoutFeedback, View, TextInput, findNodeHandle, UIManager, DeviceEventEmitter } from 'react-native'
onInputLayout = (target: number | React.ComponentClass<any, any> | React.Component<any, any, any> | null): any => {
if (!target) {
return false
}
const handle: any = findNodeHandle(target)
handle &&
UIManager.measure(handle, (x, y, width, height, pageX, pageY) => {
// console.log('相对父视图位置x:', x)
// console.log('相对父视图位置y:', y)
// console.log('组件宽度width:', width)
// console.log('组件高度height:', height)
// console.log('距离屏幕的绝对位置x:', pageX)
// console.log('距离屏幕的绝对位置y:', pageY)
DeviceEventEmitter.emit('onInputLayout', {
x,
y,
width,
height,
pageX,
pageY
})
})
}
onInputFocus = e => {
console.log('args', e.nativeEvent.target)
this.onInputLayout(e.nativeEvent.target)
this.props.onFocus && this.props.onFocus(e)
}
CommentKeyboardAvoidingView.tsx
import React from 'react'
import { KeyboardAvoidingView, Platform, Keyboard, View, Dimensions, DeviceEventEmitter } from 'react-native'
import debounce from 'lodash.debounce'
import { BottomTabBarHeightContext } from '@react-navigation/bottom-tabs'
import { ClassuseEngineOptionsContext } from '../../hooks/useEngineOptionsContext'
import { EdgeInsets, withSafeAreaInsets } from 'react-native-safe-area-context'
interface StateProps {
keyboardHeight: number
isKeyBoardShow: boolean
}
interface PropsType {
children?: any
}
interface InputEventPropsType {
x: number
y: number
width: number
height: number
pageX: number
pageY: number
}
class CommentKeyboardAvoidingView extends ClassuseEngineOptionsContext {
keyboardDidShowListener: any = null
keyboardDidHideListener: any = null
inputListener: any = null
inputEvent: InputEventPropsType = {
x: 0,
y: 0,
width: 0,
height: 0,
pageX: 0,
pageY: 0
}
insets: EdgeInsets = {
top: 0,
right: 0,
bottom: 0,
left: 0
}
constructor(props: PropsType) {
super(props)
this.state = {
keyboardHeight: 0,
isKeyBoardShow: false,
enabled: true
}
}
setKeyboardHeight = (num: number) => {
this.setState({ keyboardHeight: num })
}
componentDidMount() {
this.addKeyEvent()
this.addInputEvent()
}
componentWillUnmount() {
this.removeKeyEvent()
this.removeInputEvent()
}
setIsKeyBoardShow(isKeyBoardShow: boolean) {
this.setState({
isKeyBoardShow: isKeyBoardShow
})
}
addInputEvent = () => {
try {
this.inputListener = DeviceEventEmitter.addListener('onInputLayout', (inputEvent: InputEventPropsType) => {
console.log('onInputLayout-inputEvent', inputEvent)
this.inputEvent = inputEvent
})
} catch {}
}
removeInputEvent = () => {
try {
this.inputListener && this.inputListener.remove()
} catch {}
}
addKeyEvent = () => {
try {
this.keyboardDidShowListener = Keyboard.addListener('keyboardDidShow', this.keyboardDidShow)
this.keyboardDidHideListener = Keyboard.addListener('keyboardDidHide', this.keyboardDidHide)
} catch {}
}
removeKeyEvent = () => {
try {
this.keyboardDidShowListener && this.keyboardDidShowListener.remove()
this.keyboardDidHideListener && this.keyboardDidHideListener.remove()
} catch (err) {
console.log('keyboardDidShowListener')
}
}
getShengyuHeight = (): number => {
const screenHeight = Dimensions.get('window').height
const pageY = this.inputEvent.pageY
const shengyuHeight = screenHeight - pageY
return shengyuHeight
}
// 键盘弹出
keyboardDidShow = debounce(
(e: any) => {
let height = Math.ceil(e?.endCoordinates?.height || 0)
console.log(`e---`, e)
console.log('onInputLayout-inputEvent2', this.inputEvent)
const shengyuHeight = this.getShengyuHeight()
let enabled: Boolean = true
if (shengyuHeight < height + this.insets.bottom) {
height = height + this.insets.bottom
enabled = true
} else {
height = 0
enabled = false
}
if (Platform.OS == 'ios') {
enabled = false
}
this.setKeyboardHeight(height)
this.setIsKeyBoardShow(true)
this.setState({
enabled: enabled
})
},
30,
null,
{
leading: false,
trailing: true
}
)
// 键盘隐藏
keyboardDidHide = debounce(
(e: any) => {
this.setKeyboardHeight(0)
this.setIsKeyBoardShow(false)
this.setState({
enabled: false
})
},
300,
null,
{
leading: true,
trailing: false
}
)
render(): React.ReactNode {
const { keyboardHeight, engineOptionContext, enabled } = this.state
console.log(`keyboardHeight`, keyboardHeight)
const { insets } = this.props
return (
<KeyboardAvoidingView behavior={Platform.OS == 'ios' ? 'padding' : 'padding'} enabled={enabled}>
{this.props.children}
{enabled && <View style={{ paddingBottom: 30 }}></View>}
</KeyboardAvoidingView>
)
}
}
export default withSafeAreaInsets(CommentKeyboardAvoidingView)
直接使用
<CommentKeyboardAvoidingView>
{children}
</CommentKeyboardAvoidingView>