如何避免Stack Navigator头部被KeyboardAvoidingView顶起?
我在Stack Navigator中有一个容器组件,顶部为Header,下方包含承载消息的ScrollView和Input元素。当聚焦Input时,整个窗口上移,Header也被隐藏。请问如何避免该行为?
以下是我使用的组件代码:
class Chat extends Component { static navigationOptions = ({navigation}) => { return { headerTitle: ( <Header user={navigation.getParam('chat').partecipants[0]} headerClick={() => navigation.getParam('openProfile')()} /> ) } } ..... render() { ... return ( <KeyboardAvoidingView style={{flex: 1}} behavior={'padding'} > <ScrollView> {messages} </ScrollView> <Input sendMessage={(m) => this.props.sendMessage(chat, m)}/> </KeyboardAvoidingView> ) } }
别着急,我给你几个靠谱的解决办法,都是实际项目里亲测有效的:
方法1:关闭Stack Navigator的自动键盘调整
React Navigation的Stack Navigator默认会在键盘弹出时自动调整屏幕布局,这就是Header被顶上去甚至隐藏的元凶。你可以在定义Stack Navigator的时候,全局或者针对单个屏幕关闭这个行为:
const ChatStack = createStackNavigator({ Chat: { screen: Chat, navigationOptions: { // 你的其他导航配置项 } } }, { defaultNavigationOptions: { keyboardHandlingEnabled: false // 关键配置:禁用导航器的自动键盘调整 } });
加上这个配置后,导航器就不会再因为键盘弹出而乱动布局,Header就能稳稳待在顶部了。
方法2:优化KeyboardAvoidingView的配置
你现在用的behavior={'padding'}在某些场景下会导致整个视图上移,我们可以针对性调整这个属性,或者手动设置偏移量:
分平台设置behavior
不同平台对KeyboardAvoidingView的behavior支持不一样,我们可以根据系统动态切换:
import { Platform } from 'react-native'; // ... render() { ... return ( <KeyboardAvoidingView style={{flex: 1}} behavior={Platform.OS === 'ios' ? 'padding' : 'height'} // iOS用padding,Android用height更稳定 > <ScrollView style={{flex: 1}}> {/* 给ScrollView加上flex:1,让它占满剩余空间 */} {messages} </ScrollView> <Input sendMessage={(m) => this.props.sendMessage(chat, m)}/> </KeyboardAvoidingView> ) }
手动设置键盘偏移量
如果还是有问题,可以给KeyboardAvoidingView加上keyboardVerticalOffset,手动指定键盘弹出时的偏移高度,这个值一般对应你的Header高度(iOS默认Header是64,Android是56,你可以根据自己的Header实际高度调整):
<KeyboardAvoidingView style={{flex: 1}} behavior={'padding'} keyboardVerticalOffset={64} // 替换成你的Header实际高度 > {/* 内部的ScrollView和Input */} </KeyboardAvoidingView>
方法3:优化ScrollView的交互属性
给ScrollView加上两个属性,确保键盘弹出时视图不会异常移位,同时保证输入交互正常:
<ScrollView style={{flex: 1}} keyboardDismissMode="interactive" // 滑动屏幕可以收起键盘,提升体验 keyboardShouldPersistTaps="handled" // 点击输入框外的区域不会自动收起键盘,避免误操作 > {messages} </ScrollView>
你可以先试试方法1,这个是最直接解决导航器导致Header隐藏的办法,如果还有其他布局问题,再结合方法2和3调整,应该就能搞定啦!
内容的提问来源于stack exchange,提问作者nicecatch

