目录
1.KeyboardAvoidingView
2.react-native-keyboard-aware-scroll-view
3.Keyboard Module
4.QQ聊天示例
4.1实现类似QQ聊天效果,点击输入框以后可以继续停留在未弹出键盘的位置;
4.2键盘显示或隐藏总是滚到底部
键盘遮挡
在开发中难免会用于(TextInput)输入框,可能会遇到键盘遮挡TextInput的情况,效果图:
示例代码:
render(){return (<View style={styles.container}><Text style={{height:150,textAlignVertical:'center'}}>键盘遮挡</Text><TextInput ref="username1"autoCapitalize='none' //设置首字母不自动大写placeholder={'请输入账号1'}//提示语style={styles.textInputStyle}/><TextInput ref="username2"autoCapitalize='none' //设置首字母不自动大写placeholder={'请输入账号2'}//提示语style={styles.textInputStyle}/><TextInput ref="username3"autoCapitalize='none' //设置首字母不自动大写placeholder={'请输入账号3'}//提示语style={styles.textInputStyle}/><TextInput ref="username4"autoCapitalize='none' //设置首字母不自动大写placeholder={'请输入账号4'}//提示语style={styles.textInputStyle}/><TextInput ref="username5"autoCapitalize='none' //设置首字母不自动大写placeholder={'请输入账号5'}//提示语style={styles.textInputStyle}/><TextInput ref="username6"autoCapitalize='none' //设置首字母不自动大写placeholder={'请输入账号6'}//提示语style={styles.textInputStyle}/></View>);}
}let styles = StyleSheet.create({container:{flex: 1,justifyContent: 'center',alignItems:'center',backgroundColor:'#0ff'},textInputStyle:{height:50, width:'90%',backgroundColor:'#fff',marginTop:10, borderRadius:10}
});
介绍几种解决键盘遮挡问题的方法
1.KeyboardAvoidingView
本组件用于解决一个常见的尴尬问题:手机上弹出的键盘常常会挡住当前的视图。本组件可以自动根据键盘的位置,调整自身的 height 或底部的 padding,以避免被遮挡。
用法:
import { KeyboardAvoidingView } from 'react-native';
<KeyboardAvoidingView style={styles.container} behavior="padding" enabled>... 在这里放置需要根据键盘调整位置的组件 ...
</KeyboardAvoidingView>
关键参数说明:
behavior:参数表示怎样显示键盘;
注意:Android 和 iOS 在此属性上表现并不一致。 Android 可能不指定此属性更好,而 iOS 可能相反。
通过测试behavior设置为padding基本满足需求的;
我们可以看到通过KeyboardAvoidingView包裹输入框以后基本可以满足需要了;
render(){return (<KeyboardAvoidingView style={styles.container}behavior= 'padding'><Text style={{height:150,textAlignVertical:'center'}}>键盘遮挡</Text><TextInput ref="username1"autoCapitalize='none' //设置首字母不自动大写placeholder={'请输入账号1'}//提示语style={styles.textInputStyle}/><TextInput ref="username2"autoCapitalize='none' //设置首字母不自动大写placeholder={'请输入账号2'}//提示语style={styles.textInputStyle}/><TextInput ref="username3"autoCapitalize='none' //设置首字母不自动大写placeholder={'请输入账号3'}//提示语style={styles.textInputStyle}/><TextInput ref="username4"autoCapitalize='none' //设置首字母不自动大写placeholder={'请输入账号4'}//提示语style={styles.textInputStyle}/><TextInput ref="username5"autoCapitalize='none' //设置首字母不自动大写placeholder={'请输入账号5'}//提示语style={styles.textInputStyle}/><TextInput ref="username6"autoCapitalize='none' //设置首字母不自动大写placeholder={'请输入账号6'}//提示语style={[styles.textInputStyle, {marginBottom:50}]}/><Text style={[styles.textInputStyle, {textAlign:'center', textAlignVertical:'center'}]}>登录</Text></KeyboardAvoidingView>);}
通过效果图我们会发现一个问题,视图是被直接顶上去了,显示在视图之外,界面无法滚动;
针对 Android 开发者:我发现这种方法是处理这个问题最好,也是唯一的办法。在 AndroidManifest.xml
中添加 android:windowSoftInputMode="adjustResize"。操作系统将为你解决大部分的问题,
KeyboardAvoidingView 会为你解决剩下的问题。参见https://gist.github.com/spencercarli/e1b9575c1c8845c2c20b86415dfba3db#file-
androidmanifest-xml-L23这个。
2.react-native-keyboard-aware-scroll-view
一个ScrollView组件,用于处理键盘外观并自动滚动到焦点文本输入。
您可以使用KeyboardAwareScrollView、KeyboardAwareSectionList或KeyboardAwareFlatList组件。它们分别继承Scrollview、SectionList和FlatList默认属性,并实现一个名为KeyboardAwareHOC的自定义高阶组件来处理键盘外观。如果要在任何其他组件中使用高阶组件,也可以使用它。
可以实现输入框获取焦点自动滚动到输入框的位置 ;
安装:
<KeyboardAwareScrollView><View><TextInput /></View>
</KeyboardAwareScrollView>
npm i react-native-keyboard-aware-scroll-view --save
或
yarn add react-native-keyboard-aware-scroll-view
使用示例:
render(){return (<KeyboardAwareScrollViewinnerRef={ref => {this.scroll = ref //内部引用}}enableOnAndroid={true}// contentContainerStyle={} //咱不定义此参数,会导致无法滚动style={{ backgroundColor: '#4c69a5', flex:1}}><View style={styles.container}><Text style={{height:150,textAlignVertical:'center'}}>键盘遮挡</Text><TextInput ref="username1"autoCapitalize='none' //设置首字母不自动大写placeholder={'请输入账号1'}//提示语style={styles.textInputStyle}/><TextInput ref="username2"autoCapitalize='none' //设置首字母不自动大写placeholder={'请输入账号2'}//提示语style={styles.textInputStyle}/><TextInput ref="username3"autoCapitalize='none' //设置首字母不自动大写placeholder={'请输入账号3'}//提示语style={styles.textInputStyle}/><TextInput ref="username4"autoCapitalize='none' //设置首字母不自动大写placeholder={'请输入账号4'}//提示语style={styles.textInputStyle}/><TextInput ref="username5"autoCapitalize='none' //设置首字母不自动大写placeholder={'请输入账号5'}//提示语style={styles.textInputStyle}/><TextInput ref="username6"autoCapitalize='none' //设置首字母不自动大写placeholder={'请输入账号6'}//提示语style={[styles.textInputStyle, {marginBottom:50}]}onFocus={(event: Event) => {// `bind` the function if you're using ES6 classes
//获取焦点监听 this._scrollToInput(ReactNative.findNodeHandle(event.target))}}/><Text style={[styles.textInputStyle, {textAlign:'center', textAlignVertical:'center'}]}>登录</Text></View></KeyboardAwareScrollView>);}
//滚动到获取焦点的输入框的位置_scrollToInput (reactNode: any) {// Add a 'scroll' ref to your ScrollViewthis.scroll.props.scrollToFocusedInput(reactNode)}
效果
注意事项:
Android加入android:windowSoftInputMode="adjustResize"
<activityandroid:name=".MainActivity"android:windowSoftInputMode="adjustResize" >
KeyboardAwareScrollView:组件配置contentContainerStyle属性,会导致无法滚动;
更多功能支持可以参考官方git:https://github.com/APSL/react-native-keyboard-aware-scroll-view
可以监听键盘显示,滚动到任意位置等更多功能;
3.Keyboard Module
通过监听键盘显示和隐藏,用动画实现平滑滚动;
a.监听键盘显示和隐藏事件
componentWillMount() {this.keyboardWillShowSub = Keyboard.addListener('keyboardDidShow', this.keyboardWillShow);this.keyboardWWillHideSub = Keyboard.addListener('keyboardDidHide', this.keyboardWillHide);}
b.执行相关动画
修改外层视图底部paddingBottom,绑定paddingBottom动画
paddingBottom: this.keyboardHeight
修改大图高度和宽度,绑定高度和宽度动画
style={[styles.logo, { height: this.imageHeight,width: this.imageWidth }]}
keyboardWillShow = (event) => {Animated.parallel([Animated.timing(this.keyboardHeight, {duration:100,//event.duration,toValue:event.endCoordinates.height}),Animated.timing(this.imageHeight,{duration:100,//event.duration,toValue:50}),Animated.timing(this.imageWidth,{duration:100,//event.duration,toValue:50})]).start();}keyboardWillHide = (event) => {// Alert.alert(this.imageHeight._value+// '');Animated.parallel([Animated.timing(this.keyboardHeight, {duration:100,//event.duration,toValue:0}),Animated.timing(this.imageHeight,{duration:100,//event.duration,toValue:300}),Animated.timing(this.imageWidth,{duration:100,//event.duration,toValue:300})]).start();}
完整示例代码
import React, {Component} from 'react'
import ReactNative,{StyleSheet, TextInput, Animated, Keyboard} from 'react-native';
export default class TabTwo extends Component{constructor(props){super(props);//定义动画this.keyboardHeight = new Animated.Value(0);this.imageHeight = new Animated.Value(300);this.imageWidth = new Animated.Value(300);}componentWillUnmount() {this.keyboardDidShowSub.remove();this.keyboardDidHideSub.remove();}componentWillMount() {//监听键盘显示和隐藏this.keyboardDidShowSub = Keyboard.addListener('keyboardDidShow', this.keyboardDidShow);this.keyboardDidHideSub = Keyboard.addListener('keyboardDidHide', this.keyboardDidHide);// //监听键盘弹出事件// this.keyboardDidShowListener = Keyboard.addListener('keyboardDidShow',// this.keyboardDidShowHandler.bind(this));// //监听键盘隐藏事件// this.keyboardDidHideListener = Keyboard.addListener('keyboardDidHide',// this.keyboardDidHideHandler.bind(this));}//键盘显示keyboardDidShow = (event) => {//并行执行动画Animated.parallel([Animated.timing(this.keyboardHeight, {duration:100,//event.duration,toValue:event.endCoordinates.height}),Animated.timing(this.imageHeight,{duration:100,//event.duration,toValue:50}),Animated.timing(this.imageWidth,{duration:100,//event.duration,toValue:50})]).start();}//键盘隐藏keyboardDidHide = (event) => {//并行执行动画Animated.parallel([Animated.timing(this.keyboardHeight, {duration:100,//event.duration,toValue:0}),Animated.timing(this.imageHeight,{duration:100,//event.duration,toValue:300}),Animated.timing(this.imageWidth,{duration:100,//event.duration,toValue:300})]).start();}render(){return (<Animated.View style={[styles.container, { paddingBottom: this.keyboardHeight }]}><Animated.Image source={require('./image/head.png')} style={[styles.logo, { height: this.imageHeight,width: this.imageWidth }]} /><TextInputplaceholder="Email"style={styles.input}/><TextInputplaceholder="Username"style={styles.input}/><TextInputplaceholder="Password"style={styles.input}/><TextInputplaceholder="Confirm Password"style={styles.input}/></Animated.View>);}// _scrollToInput (reactNode: any) {// // Add a 'scroll' ref to your ScrollView// this.scroll.props.scrollToFocusedInput(reactNode)// }
}let styles = StyleSheet.create({container:{flex: 1,justifyContent: 'center',alignItems:'center',backgroundColor:'#0ff',},textInputStyle:{height:70, width:'90%',backgroundColor:'#fff',marginTop:10, borderRadius:10},contentContainer: {flex: 1}
});
最外层的paddingBottom动画<Animated.View>和视图可以用<KeyboardAvoidingView behavior="padding">替换实现;
4.QQ聊天示例
视图大概结构
<View style={styles.container}><Text style={styles.nameStyle}>标题(QQ用户名)</Text>标题<KeyboardAwareScrollView> 滚动视图,根据键盘显示隐藏高度会动态调整<View></View><View onLayout={e => this.setState({scrollViewHeight: e.nativeEvent.layout.y})}/> //ScrollView最下面下面视图,获取ScrollView实际高度</KeyboardAwareScrollView><View style={styles.senditemStyle}> 输入和发送视图</View>
</View>
问题说明:KeyboardAwareScrollView长度变短之后,里面的内容并没有发生滚动。产生键盘覆盖 KeyboardAwareScrollView 内容的效果;
4.1实现类似QQ聊天效果,点击输入框以后可以继续停留在未弹出键盘的位置;
完整示例代码
import React, {Component} from "react";
import {KeyboardAwareScrollView} from 'react-native-keyboard-aware-scroll-view'
import {Keyboard, Text, TextInput, TouchableOpacity, StyleSheet, View
} from "react-native";export default class QQChatShowScene extends Component{constructor(props){super(props);this.state = {keyboardHeight:0, //键盘高度lastOffset:0, //最后偏移位置scrollViewHeight:0 //滚动视图的实际高度};}componentDidMount() {//监听键盘显示和隐藏this.keyboardDidShowSub = Keyboard.addListener('keyboardDidShow', this.keyboardDidShow);this.keyboardDidHideSub = Keyboard.addListener('keyboardDidHide', this.keyboardDidHide);}//键盘显示keyboardDidShow = (event) => {//记录键盘的高度this.setState({keyboardHeight:event.endCoordinates.height});//滚动到未显示键盘之前y轴偏移的位置,KeyboardAwareScrollView视图变小,偏移位置上移键盘高度this.scrollview.props.scrollToPosition(0, this.state.lastOffset+event.endCoordinates.height);}//键盘隐藏keyboardDidHide = (event) => {//滚动到显示键盘之前y轴偏移的位置,KeyboardAwareScrollView视图变大,偏移位置下移键盘高度this.scrollview.props.scrollToPosition(0, this.state.lastOffset-this.state.keyboardHeight);}componentWillUnmount() {//移除键盘监听this.keyboardDidShowSub.remove();this.keyboardDidHideSub.remove();}render(){return (<View style={styles.container}><Text style={styles.nameStyle}>标题(QQ用户名)</Text><KeyboardAwareScrollViewinnerRef={ref => {this.scrollview = ref}}onScroll = {(event)=>{{console.log(event.nativeEvent.contentOffset.x);//水平滚动距离console.log(event.nativeEvent.contentOffset.y);//垂直滚动距离this.setState({lastOffset:event.nativeEvent.contentOffset.y});//记录y轴滚动位置}}}><Text>TextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextcccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc</Text><View onLayout={e => this.setState({scrollViewHeight: e.nativeEvent.layout.y})}/></KeyboardAwareScrollView><View style={styles.senditemStyle}><TextInput placeholder='请输入' style={styles.textInputStyle}/><TouchableOpacity style={styles.sendBtnStyle}><Text>发送</Text></TouchableOpacity></View></View>);}
}let styles = StyleSheet.create({container:{flex:1},nameStyle:{height:45,width:'100%',textAlign:'center',textAlignVertical:'center'},senditemStyle:{height:55,width:'100%',flexDirection:'row',backgroundColor:'#0f0',alignItems:'center'},textInputStyle:{flex:4},sendBtnStyle:{flex:1}
});
4.2键盘显示或隐藏总是滚到底部
//键盘显示keyboardDidShow = (event) => {//记录键盘的高度this.setState({keyboardHeight:event.endCoordinates.height});//滚动到未显示键盘之前y轴偏移的位置,KeyboardAwareScrollView视图变小,偏移位置上移键盘高度// this.scrollview.props.scrollToPosition(0, this.state.lastOffset+event.endCoordinates.height);// 键盘展开// 键盘展开时 scrollview 变小,内容位置不会发生变化,所以减去键盘高度滑动到最底this.scrollview.props.scrollToPosition(0, this.state.scrollViewHeight-event.endCoordinates.height);}//键盘隐藏keyboardDidHide = (event) => {//滚动到显示键盘之前y轴偏移的位置,KeyboardAwareScrollView视图变大,偏移位置下移键盘高度//this.scrollview.props.scrollToPosition(0, this.state.lastOffset-this.state.keyboardHeight);// 键盘关闭时 scrollView 变大,所以再减一个键盘高度this.scrollview.props.scrollToPosition(0, this.state.scrollViewHeight-2*this.state.keyboardHeight);}
参考:
https://blog.csdn.net/sinat_17775997/article/details/72953940
https://blog.csdn.net/weixin_39330484/article/details/86687951