是否有一种可重用的方式来订阅诸如键盘事件之类的监听器。
实际上,我在屏幕的最底部有一个绝对位置的按钮,当键盘弹出时,它会 float 在顶部,看起来不太好。
因此,当键盘可见时,我会隐藏该按钮,但如果您在多个屏幕上有类似的情况,那么在每个屏幕上添加订阅就会变得令人头疼,目前我正在这样做。
class Profile extends Component {
constructor(props) {
super(props);
this._keyboardDidShow = this._keyboardDidShow.bind(this);
this._keyboardDidHide = this._keyboardDidHide.bind(this);
}
componentDidMount() {
// subscribing to keyboard listeners on didMount
this.keyboardDidShowListener = Keyboard.addListener(
'keyboardDidShow',
this._keyboardDidShow
);
this.keyboardDidHideListener = Keyboard.addListener(
'keyboardDidHide',
this._keyboardDidHide
);
}
_keyboardDidShow() {
this.setState({
keyboardVisible: true,
});
}
_keyboardDidHide() {
this.setState({
keyboardVisible: false,
});
}
componentWillUnmount() {
// unsubscribing listeners on unMount
this.keyboardDidShowListener.remove();
this.keyboardDidHideListener.remove();
}
render() {
const AnimatedBottomButton = Animated.createAnimatedComponent(BottomButton);
return (
<ScrollView
style={styles.containerStyle}
bounces={false}
contentContainerStyle={{ flex: 1 }}
keyboardShouldPersistTaps="handled">
{this.renderUserImage()}
{this.renderUserDetail()}
{!this.state.keyboardVisible && (
<View
style={{
flex: 1,
justifyContent: 'flex-end',
}}>
<AnimatedBottomButton
title="Done"
onPress={() => Actions.pop()}
style={{
opacity: this.anim5,
transform: [{ scale: this.anim5 }],
marginBottom: Utils.isPhoneX() ? Metrics.doubleBaseMargin : 0,
}}
/>
</View>
)}
</ScrollView>
);
}
}
我不喜欢上面的解决方案,因为我必须向我想要订阅键盘事件的每个组件添加订阅相关的代码,我是 JavaScript 新手,仍在学习它。
如果有人可以帮助我找到一些通用的解决方案,那就太好了。
最佳答案
自定义组件在这些情况下会派上用场。您可以创建一个实现所需行为的组件,然后将该组件添加到您要使用的屏幕中。
示例
export default class CustomButton extends Component {
state = {
visible: true
}
componentDidMount() {
// subscribing to keyboard listeners on didMount
this.keyboardDidShowListener = Keyboard.addListener(
'keyboardDidShow',
() => this._toggleVisiblity(false)
);
this.keyboardDidHideListener = Keyboard.addListener(
'keyboardDidHide',
() => this._toggleVisiblity(true)
);
}
_toggleVisiblity = (visible) => {
this.setState({ visible })
}
componentWillUnmount() {
// unsubscribing listeners on unMount
this.keyboardDidShowListener.remove();
this.keyboardDidHideListener.remove();
}
render() {
if (this.state.visible === false) return null
return (
<View
style={{
flex: 1,
justifyContent: 'flex-end',
}}>
<AnimatedBottomButton
title="Done"
onPress={() => Actions.pop()}
style={{
opacity: this.anim5,
transform: [{ scale: this.anim5 }],
marginBottom: Utils.isPhoneX() ? Metrics.doubleBaseMargin : 0,
}}
/>
</View>
);
}
}
class Profile extends Component {
render() {
return (
<ScrollView
style={styles.containerStyle}
bounces={false}
contentContainerStyle={{ flex: 1 }}
keyboardShouldPersistTaps="handled">
{this.renderUserImage()}
{this.renderUserDetail()}
<CustomButton />
</ScrollView>
);
}
}
如果您愿意,您可以更进一步,创建 HOC 。
示例
const withKeyboardEvents = WrappedComponent => {
return class extends Component {
state = {
visible: true,
};
componentDidMount() {
this.keyboardDidShowListener = Keyboard.addListener(
'keyboardDidShow',
() => this._toggleVisiblity(false)
);
this.keyboardDidHideListener = Keyboard.addListener(
'keyboardDidHide',
() => this._toggleVisiblity(true)
);
}
_toggleVisiblity = visible => {
this.setState({ visible });
};
componentWillUnmount() {
this.keyboardDidShowListener.remove();
this.keyboardDidHideListener.remove();
}
render() {
return (
<React.Fragment>
{this.state.visible === true && (
<View
style={{
flex: 1,
justifyContent: 'flex-end',
}}>
<AnimatedBottomButton
title="Done"
onPress={() => Actions.pop()}
style={{
opacity: this.anim5,
transform: [{ scale: this.anim5 }],
marginBottom: Utils.isPhoneX() ? Metrics.doubleBaseMargin : 0,
}}
/>
</View>
)}
<WrappedComponent />
</React.Fragment>
);
}
};
};
class Profile extends Component {
render() {
return (
<ScrollView
style={styles.containerStyle}
bounces={false}
contentContainerStyle={{ flex: 1 }}
keyboardShouldPersistTaps="handled">
{this.renderUserImage()}
{this.renderUserDetail()}
</ScrollView>
);
}
}
export default withKeyboardEvents(Profile)
关于reactjs - 在 React Native 中订阅监听器的通用解决方案,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51056989/