目錄
2.react-native-keyboard-aware-scroll-view
4.1實現類似QQ聊天效果,點擊輸入框以後可以繼續停留在未彈出鍵盤的位置;
鍵盤遮擋
在開發中難免會用於(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 (
<KeyboardAwareScrollView
innerRef={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 ScrollView
this.scroll.props.scrollToFocusedInput(reactNode)
}
效果
注意事項:
Android加入android:windowSoftInputMode="adjustResize"
<activity
android: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 }]} />
<TextInput
placeholder="Email"
style={styles.input}
/>
<TextInput
placeholder="Username"
style={styles.input}
/>
<TextInput
placeholder="Password"
style={styles.input}
/>
<TextInput
placeholder="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>
<KeyboardAwareScrollView
innerRef={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>TextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextText
TextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextText
TextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextText
TextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextText
TextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextText
TextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextText
TextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextText
TextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextText
TextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextText
TextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextText
TextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextText
TextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextText
TextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextText
TextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextText
TextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextText
TextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextText
TextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextText
TextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextText
TextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextText
cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
ccccccccccccccccccccccccccccccccccccTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextText
TextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextText
TextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextText
TextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextText
TextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextText
TextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextText
TextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextText
TextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextText
TextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextText
TextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextText
TextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextText
TextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextText
TextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextText
TextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextText
TextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextText
TextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextText
TextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextText
TextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextText
TextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextText
cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
cccccccccccccccccccccccccccccccccccc</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