一、簡介
在前面使用了TextInput實現了文本輸入和搜索功能,一般情況下,我們會通過樣式設置把控鍵盤彈起后與視圖的間距,以至於不會擋住某些視圖。但是,如果視圖上的組件比較多,鍵盤的彈起覆蓋某些視圖幾乎是無法避免的。ReactNative中就提供了一個KeyboardAvoidingView組件來解決這個問題。使用了這個組件后,它會幫助自動完成鍵盤的自適應,通過偏移避免其他組件被鍵盤遮蓋。
二、API
KeyboardAvoidingView組件提供了3個比較重要的屬性,分別是behavior、contentContainerStyle、keyboardVerticalOffset。behavior譯為行為,這里指鍵盤避免視圖組件的位移焦點。contentContainerStyle是該組件內部視圖的樣式布局。keyboardVerticalOffset則是鍵盤的豎直偏移距離。如下:
//位移的參照焦點有三種:height:以高度為焦點 position:以位置為焦點 padding:以邊距為焦點 behavior: PropTypes.oneOf(['height', 'position', 'padding']), //組件內容視圖樣式布局,只有采用‘ position’為焦點時,才會創建出這個內容視圖 contentContainerStyle: ViewPropTypes.style, //這是用戶屏幕頂部與應用視圖的距離,可以利用這個屬性來補償修正這段距離 keyboardVerticalOffset: PropTypes.number.isRequired,
KeyboardAvoidingView組件也提供了幾個常用的方法,可以使用這幾個方法手動來調整鍵盤的偏移。如下:
//鍵盤的相對高度 relativeKeyboardHeight(keyboardFrame: ScreenRect): number //鍵盤改變時的回調 onKeyboardChange(event: ?KeyboardChangeEvent) //鍵盤布局時的回調 onLayout(event: LayoutEvent) //這個幾個方法用到的對象如下 type Rect = { x: number, y: number, width: number, height: number, }; type ScreenRect = { screenX: number, screenY: number, width: number, height: number, }; type KeyboardChangeEvent = { startCoordinates?: ScreenRect, //起始位置 endCoordinates: ScreenRect, //終止位置 duration?: number, //動畫時間 easing?: string, }; type LayoutEvent = { nativeEvent: { layout: Rect, } };
三、拓展
使用KeyboardAvoidingView組件時,可以搭配鍵盤組件Keyboard組件一起完成開發。鍵盤彈起和隱藏的過程,都可以使用鍵盤組件Keyboard進行監聽。它提供了常用的幾個監聽名稱和鍵盤相關數據,如下所示:
//監聽名稱 type KeyboardEventName = | 'keyboardWillShow' | 'keyboardDidShow' | 'keyboardWillHide' | 'keyboardDidHide' | 'keyboardWillChangeFrame' | 'keyboardDidChangeFrame'; //鍵盤數據 type KeyboardEventData = { endCoordinates: { width: number, height: number, screenX: number, screenY: number,}, };
提供的幾個方法比較簡單,如下所示:
//給鍵盤添加監聽 addListener(eventName: KeyboardEventName, callback: KeyboardEventListener) //給鍵盤移除監聽 removeListener(eventName: KeyboardEventName, callback: Function) //移除鍵盤所有監聽 removeAllListeners(eventName: KeyboardEventName) //關閉鍵盤 dismiss()
四、使用
現在使用KeyboardAvoidingView組件來調節輸入框的位置,示例如下:
/** * Sample React Native App * https://github.com/facebook/react-native * @flow */ import React, { Component } from 'react'; import { AppRegistry, StyleSheet, View, TextInput, Dimensions, Keyboard, KeyboardAvoidingView } from 'react-native'; let {height} = Dimensions.get('window'); export default class ReactNativeDemo extends Component { componentWillMount() { this.keyboardDidShowListener = Keyboard.addListener('keyboardDidShow',(KeyboardEventData)=>{ console.log('Keyboard Shown'); console.log(KeyboardEventData.endCoordinates.screenY); // KeyboardAvoidingView實例的方法,可以在監聽事件中調用 // const avoidingView = this.refs.KeyboardAvoidingView; // avoidingView.onKeyboardChange(KeyboardChangeEvent); // avoidingView.onLayout(LayoutEvent); // avoidingView.relativeKeyboardHeight(keyboardFrame); }); this.keyboardDidHideListener = Keyboard.addListener('keyboardDidHide', (KeyboardEventData)=>{ console.log('Keyboard Hidden'); console.log(KeyboardEventData.endCoordinates.screenY); // KeyboardAvoidingView實例的方法,可以在監聽事件中調用 // const avoidingView = this.refs.KeyboardAvoidingView; // avoidingView.onKeyboardChange(KeyboardChangeEvent); // avoidingView.onLayout(LayoutEvent); // avoidingView.relativeKeyboardHeight(keyboardFrame); }); } componentWillUnmount() { this.keyboardDidShowListener.remove(); this.keyboardDidHideListener.remove(); } render() { return ( <View style={[styles.flex,styles.bgColor]}> <KeyboardAvoidingView ref={'KeyboardAvoidingView'} behavior={'position'} keyboardVerticalOffset={10} contentContainerStyle={styles.avoidingView}> <TextInput style={styles.inputView} placeholder='請輸入關鍵字' placeholderTextColor="black" returnKeyType='search' clearButtonMode='while-editing' enablesReturnKeyAutomatically={true} /> </KeyboardAvoidingView> </View> ); } } const styles = StyleSheet.create({ flex: { flex: 1 }, bgColor: { backgroundColor: 'white' }, center: { alignItems: 'center', justifyContent: 'center', }, font: { fontSize: 30, color: 'purple', textAlign: 'center' }, avoidingView: { backgroundColor:'#DDD' }, inputView:{ height:100, borderWidth: 1, marginTop: height-111, marginRight:5, marginLeft: 5, paddingLeft: 5, borderColor:'red', borderRadius: 4 }, }); AppRegistry.registerComponent('ReactNativeDemo', () => ReactNativeDemo);
打印結果如下:
2020-01-02 17:22:55.793 [info][tid:com.facebook.react.JavaScript] Keyboard Shown 2020-01-02 17:22:55.794 [info][tid:com.facebook.react.JavaScript] 407 2020-01-02 17:23:05.852 [info][tid:com.facebook.react.JavaScript] Keyboard Shown 2020-01-02 17:23:05.853 [info][tid:com.facebook.react.JavaScript] 407 2020-01-02 17:23:08.470 [info][tid:com.facebook.react.JavaScript] Keyboard Hidden 2020-01-02 17:23:08.470 [info][tid:com.facebook.react.JavaScript] 667
截圖結果如下:1圖為初始狀態、2圖為不使用KeyboardAvoidingView組件時輸入框被鍵盤遮蓋、圖3使用了KeyboardAvoidingView組件時不會遮蓋正常使用。