ReactNative: 使用键盘避免视图KeyboardAvoidingView组件实现键盘自适应
一、简介
在前面使用了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组件时不会遮盖正常使用。
程序猿神奇的手,每时每刻,这双手都在改变着世界的交互方式!