当 React Native 有输入附件时如何滚动到焦点上的文本输入
How to scroll to text input on focus when there is an input accessory with React Native
我正在开发 React Native 应用程序,许多屏幕都有带有文本输入字段的表单。
当我按下文本输入时,键盘打开。我创建了一个浮动 InputAccessory
组件,它出现在键盘顶部以关闭它,上面有按钮 "Done"。
但是现在我有了这个配件,当我点击输入字段或按键盘上的 "Next" 按钮转到下一个字段时,ScrollView
滚动以对齐底部使用键盘顶部的文本输入。使用此浮动附件会带来问题,如下所示,由于此附件,您看不到文本输入的内容,我想让滚动视图滚动更多以显示整个文本输入。
我可能可以为此进行计算,运行 ScrollView
组件中的 .scrollTo()
方法,但这种模式对我的整个应用程序来说很常见,我正在寻找一个优雅的解决方案,每次我导入文本输入并专注于它时都可以足够通用。
你有什么建议吗?
谢谢
我以前遇到过同样的问题,我有 2 种不同的解决方案,它们都对我有用。
1- 使用 react-native-keyboard-aware-scroll-view ,注意这个库将已经包含 scrollView 所以你删除你自己的滚动视图并使用
<KeyboardAwareScrollView>
<View>
<TextInput />
</View>
</KeyboardAwareScrollView>
您还可以查看 documentation 了解更多信息。
这个解决方案更简单,因为你不需要自己处理任何事情,但我认为如果你想在其中包含 scrollView
,你会遇到一些问题。
2- 我曾经创建了一个组件 AvoidKeyboard
,它实际上做的事情与您的解决方案类似,但它用于将键盘高度值转换到整个视图的顶部,这个解决方案对我来说也非常有效。
实施
import React, { Component } from 'react';
import { Animated, Easing, Keyboard } from 'react-native';
import PropTypes from 'prop-types';
class AvoidKeyboard extends Component {
constructor(props) {
super(props);
this.state = {
animatedViewHeight: new Animated.Value(0),
viewHeight: 0,
};
this.setViewHeightOnce = this.setViewHeightOnce.bind(this);
this.keyboardWillShow = this.keyboardWillShow.bind(this);
this.keyboardWillHide = this.keyboardWillHide.bind(this);
this.keyboardDidShowListener = Keyboard.addListener('keyboardWillShow', this.keyboardWillShow);
this.keyboardDidHideListener = Keyboard.addListener('keyboardWillHide', this.keyboardWillHide);
}
componentWillUnmount() {
this.keyboardDidShowListener && this.keyboardDidShowListener.remove();
this.keyboardDidHideListener && this.keyboardDidHideListener.remove();
}
setViewHeightOnce(event) {
const { height } = event.nativeEvent.layout;
if (this.state.viewHeight === 0) {
const avoidPaddingBottom = 15;
this.setState({
viewHeight: height + avoidPaddingBottom,
animatedViewHeight: new Animated.Value(height + avoidPaddingBottom),
});
}
}
keyboardWillShow(e) {
const { viewHeight } = this.state;
if (viewHeight) {
requestAnimationFrame(() => { // eslint-disable-line no-undef
Animated.timing(this.state.animatedViewHeight, {
toValue: (viewHeight - e.endCoordinates.height),
duration: 200,
delay: 0,
easing: Easing.inOut(Easing.ease),
}).start();
});
}
}
keyboardWillHide() {
requestAnimationFrame(() => { // eslint-disable-line no-undef
Animated.timing(this.state.animatedViewHeight, {
toValue: this.state.viewHeight,
duration: 200,
delay: 0,
easing: Easing.inOut(Easing.ease),
}).start();
});
}
render() {
let animatedHeight;
const { viewHeight } = this.state;
if (viewHeight > 0) {
animatedHeight = { maxHeight: this.state.animatedViewHeight };
}
return (
<Animated.View
style={[{ flex: 1, justifyContent: 'flex-end' }, animatedHeight]}
onLayout={this.setViewHeightOnce}
>
{this.props.children}
</Animated.View>
);
}
}
AvoidKeyboard.propTypes = {
children: PropTypes.node.isRequired,
};
export default AvoidKeyboard;
现在你只需要将你的组件或屏幕包裹在里面AvoidKeyboard
,一旦键盘打开你的屏幕高度就会缩小,你就可以滚动屏幕了
我找到了一个不涉及 hacky 动画更改的解决方案。
当键盘打开时,我决定做的是在 ScrollView 的底部添加一些边距,它对应于 InputAccessory 的高度。然后,当键盘关闭时,我删除了这个边距。它看起来像这样:
import KeyboardListener from 'react-native-keyboard-listener';
...
render() [
<ScrollView
key={1}
style={{ marginBottom: this.state.scrollViewMarginBottom }}
/>,
<InputAccessory key={2} onLayout={...} />,
<KeyboardListener
key={3}
onWillShow={() => this.setState({ scrollViewMarginBottom: inputAccessoryHeight });
onWillHide={() => this.setState({ scrollViewMarginBottom: 0 })
/>
]
我在 IOS 中遇到了很多键盘问题。没有 KeyboardSpacer、react-native-keyboard-aware-scroll-view 和更多包解决了它。
最近发现了react-native-keyboard-manager,一行代码解决了我所有的问题,还有modals等等(我和作者没有关系,但是这个包救了我那天)。给它一个改变。
我遇到了同样的问题,通过在线阅读我找到了以下解决方案
对于Android
转到您的 AndroidManifest.xml
并添加 android:windowSoftInputMode="adjustPan"
<activity
android:name=".MainActivity"
android:windowSoftInputMode="adjustPan">
.....
</activity>
对于IOS
只需按照此存储库中的说明进行操作即可。
https://github.com/douglasjunior/react-native-keyboard-manager.
希望这对您有所帮助。 :)
我正在开发 React Native 应用程序,许多屏幕都有带有文本输入字段的表单。
当我按下文本输入时,键盘打开。我创建了一个浮动 InputAccessory
组件,它出现在键盘顶部以关闭它,上面有按钮 "Done"。
但是现在我有了这个配件,当我点击输入字段或按键盘上的 "Next" 按钮转到下一个字段时,ScrollView
滚动以对齐底部使用键盘顶部的文本输入。使用此浮动附件会带来问题,如下所示,由于此附件,您看不到文本输入的内容,我想让滚动视图滚动更多以显示整个文本输入。
我可能可以为此进行计算,运行 ScrollView
组件中的 .scrollTo()
方法,但这种模式对我的整个应用程序来说很常见,我正在寻找一个优雅的解决方案,每次我导入文本输入并专注于它时都可以足够通用。
你有什么建议吗?
谢谢
我以前遇到过同样的问题,我有 2 种不同的解决方案,它们都对我有用。
1- 使用 react-native-keyboard-aware-scroll-view ,注意这个库将已经包含 scrollView 所以你删除你自己的滚动视图并使用
<KeyboardAwareScrollView>
<View>
<TextInput />
</View>
</KeyboardAwareScrollView>
您还可以查看 documentation 了解更多信息。
这个解决方案更简单,因为你不需要自己处理任何事情,但我认为如果你想在其中包含 scrollView
,你会遇到一些问题。
2- 我曾经创建了一个组件 AvoidKeyboard
,它实际上做的事情与您的解决方案类似,但它用于将键盘高度值转换到整个视图的顶部,这个解决方案对我来说也非常有效。
实施
import React, { Component } from 'react';
import { Animated, Easing, Keyboard } from 'react-native';
import PropTypes from 'prop-types';
class AvoidKeyboard extends Component {
constructor(props) {
super(props);
this.state = {
animatedViewHeight: new Animated.Value(0),
viewHeight: 0,
};
this.setViewHeightOnce = this.setViewHeightOnce.bind(this);
this.keyboardWillShow = this.keyboardWillShow.bind(this);
this.keyboardWillHide = this.keyboardWillHide.bind(this);
this.keyboardDidShowListener = Keyboard.addListener('keyboardWillShow', this.keyboardWillShow);
this.keyboardDidHideListener = Keyboard.addListener('keyboardWillHide', this.keyboardWillHide);
}
componentWillUnmount() {
this.keyboardDidShowListener && this.keyboardDidShowListener.remove();
this.keyboardDidHideListener && this.keyboardDidHideListener.remove();
}
setViewHeightOnce(event) {
const { height } = event.nativeEvent.layout;
if (this.state.viewHeight === 0) {
const avoidPaddingBottom = 15;
this.setState({
viewHeight: height + avoidPaddingBottom,
animatedViewHeight: new Animated.Value(height + avoidPaddingBottom),
});
}
}
keyboardWillShow(e) {
const { viewHeight } = this.state;
if (viewHeight) {
requestAnimationFrame(() => { // eslint-disable-line no-undef
Animated.timing(this.state.animatedViewHeight, {
toValue: (viewHeight - e.endCoordinates.height),
duration: 200,
delay: 0,
easing: Easing.inOut(Easing.ease),
}).start();
});
}
}
keyboardWillHide() {
requestAnimationFrame(() => { // eslint-disable-line no-undef
Animated.timing(this.state.animatedViewHeight, {
toValue: this.state.viewHeight,
duration: 200,
delay: 0,
easing: Easing.inOut(Easing.ease),
}).start();
});
}
render() {
let animatedHeight;
const { viewHeight } = this.state;
if (viewHeight > 0) {
animatedHeight = { maxHeight: this.state.animatedViewHeight };
}
return (
<Animated.View
style={[{ flex: 1, justifyContent: 'flex-end' }, animatedHeight]}
onLayout={this.setViewHeightOnce}
>
{this.props.children}
</Animated.View>
);
}
}
AvoidKeyboard.propTypes = {
children: PropTypes.node.isRequired,
};
export default AvoidKeyboard;
现在你只需要将你的组件或屏幕包裹在里面AvoidKeyboard
,一旦键盘打开你的屏幕高度就会缩小,你就可以滚动屏幕了
我找到了一个不涉及 hacky 动画更改的解决方案。
当键盘打开时,我决定做的是在 ScrollView 的底部添加一些边距,它对应于 InputAccessory 的高度。然后,当键盘关闭时,我删除了这个边距。它看起来像这样:
import KeyboardListener from 'react-native-keyboard-listener';
...
render() [
<ScrollView
key={1}
style={{ marginBottom: this.state.scrollViewMarginBottom }}
/>,
<InputAccessory key={2} onLayout={...} />,
<KeyboardListener
key={3}
onWillShow={() => this.setState({ scrollViewMarginBottom: inputAccessoryHeight });
onWillHide={() => this.setState({ scrollViewMarginBottom: 0 })
/>
]
我在 IOS 中遇到了很多键盘问题。没有 KeyboardSpacer、react-native-keyboard-aware-scroll-view 和更多包解决了它。
最近发现了react-native-keyboard-manager,一行代码解决了我所有的问题,还有modals等等(我和作者没有关系,但是这个包救了我那天)。给它一个改变。
我遇到了同样的问题,通过在线阅读我找到了以下解决方案
对于Android
转到您的 AndroidManifest.xml
并添加 android:windowSoftInputMode="adjustPan"
<activity
android:name=".MainActivity"
android:windowSoftInputMode="adjustPan">
.....
</activity>
对于IOS
只需按照此存储库中的说明进行操作即可。 https://github.com/douglasjunior/react-native-keyboard-manager.
希望这对您有所帮助。 :)