我正在尝试分别管理 2 个输入的状态。这两个输入具有浮动标签动画。当您专注于输入时,占位符会转到顶部,并且在模糊时它会返回到其原始位置。
现在我有一个名为 handleFocusAndBlur
的函数,我需要在其中实现该逻辑。目前,这种行为有点奇怪,因为即使只有一个输入中只有文本,如果您转到空输入,则填写的输入的标签会返回到其原始位置,这不应该是这样。
这是我为此使用的组件:
import React, { Component } from 'react';
import PropTypes from 'prop-types';
import { View, TextInput, Animated } from 'react-native';
import styles from '../../styles/SigningScreenStyles';
export default class SigningInputs extends Component {
state = { isFocused: false };
componentWillMount() {
this.animatedIsFocused = new Animated.Value(0);
}
componentDidUpdate() {
const { isFocused } = this.state;
Animated.timing(this.animatedIsFocused, {
toValue: isFocused ? 1 : 0,
duration: 200,
}).start();
}
// SEE THIS FUNCTION
handleFocusAndBlur = () => {
const { usernameLength, passwordLength } = this.props;
if (usernameLength || passwordLength) {
this.setState({ isFocused: false });
} else {
this.setState({ isFocused: true });
}
};
render() {
const { secureTextEntry, onChangeText, labelText } = this.props;
const labelStyle = {
position: 'absolute',
left: 0,
top: this.animatedIsFocused.interpolate({
inputRange: [0, 1],
outputRange: [10, -10],
}),
fontSize: this.animatedIsFocused.interpolate({
inputRange: [0, 1],
outputRange: [25, 14],
}),
color: this.animatedIsFocused.interpolate({
inputRange: [0, 1],
outputRange: ['black', 'gray'],
}),
};
return (
<>
<View style={styles.inputContainer}>
<Animated.Text style={labelStyle}>{labelText}</Animated.Text>
<TextInput
style={styles.inputs}
onChangeText={onChangeText}
onFocus={this.handleFocusAndBlur}
onBlur={this.handleFocusAndBlur}
blurOnSubmit
secureTextEntry={secureTextEntry}
propsLength
/>
</View>
</>
);
}
}
SigningInputs.defaultProps = {
secureTextEntry: false,
};
SigningInputs.propTypes = {
secureTextEntry: PropTypes.oneOfType([PropTypes.bool]),
onChangeText: PropTypes.func.isRequired,
labelText: PropTypes.oneOfType([PropTypes.string]).isRequired,
usernameLength: PropTypes.oneOfType([PropTypes.string, PropTypes.number])
.isRequired,
passwordLength: PropTypes.oneOfType([PropTypes.string, PropTypes.number])
.isRequired,
};
这就是我调用该组件的方式:
const { username, password } = this.state;
<SigningInputs
onChangeText={user => this.setState({ username: user })}
labelText="User Name"
usernameLength={username.length}
/>
<SigningInputs
onChangeText={pass => this.setState({ password: pass })}
secureTextEntry
labelText="Password"
passwordLength={password.length}
/>
当我只有一个输入时,这很容易,但现在有了 2 个输入,我发现我需要实现更多的逻辑。
有人可以看看吗?
拆分手柄Foucus 和 Blur 有效:
handleFocus = () => {
const {length} = this.props
if (!length) {
Animated.timing(this.animatedIsFocused, {
toValue: 1,
duration: 200
}).start()
}
}
handleBlur = () => {
const {length} = this.props
if (!length) {
Animated.timing(this.animatedIsFocused, {
toValue: 0,
duration: 200
}).start()
}
}
同时删除组件DidUpdate函数,更新您的输入 on Focus 和 onBlur,并且只传递一次长度道具(如其他答案所示(
更新:你的handleFocusAndBlur
逻辑有一些缺陷,考虑这种情况:你专注,handleFocusAndBlur
isFocused
设置为 true,你的标签移动。现在你输入,离开焦点,现在handleFocusAndBlur
isFocused
设置为 false。所以标签再次移动。它不应该,因为有文本。
如果完全删除isFocused
状态,则可以解决此问题。因为您不需要知道它是否聚焦,所以您有两个单独的回调。为焦点和模糊添加单独的处理程序(正如乔纳森欧文的答案所建议的那样(
<TextInput
style={styles.inputs}
onChangeText={onChangeText}
onFocus={this.handleFocus}
onBlur={this.handleBlur}
blurOnSubmit
secureTextEntry={secureTextEntry}
propsLength
/>
handleFocus = () => {
const { inputLength } = this.props;
if (!inputLength) {
Animated.timing(this.animatedIsFocused, {
toValue: 1,
duration: 200
}).start()
}
}
handleBlur = () => {
const { inputLength } = this.props;
if (!inputLength) {
Animated.timing(this.animatedIsFocused, {
toValue: 0,
duration: 200
}).start()
}
}
您可以将长度作为普通道具发送inputLength
:
const { username, password } = this.state;
<SigningInputs
onChangeText={user => this.setState({ username: user })}
labelText="User Name"
inputLength={username.length}
/>
<SigningInputs
onChangeText={pass => this.setState({ password: pass })}
secureTextEntry
labelText="Password"
inputLength={password.length}
/>