Browse Source

fix(YooLogin): avoid input from being hidden under virtual keyboard

For some reason, components is not reachable as children of `Animated.View`, so I create some Animated components to replace the originals.
dev 0.0.4a
kdxcxs 4 years ago
parent
commit
2f7f2e13f1
  1. 2
      README.md
  2. 71
      src/ui/YooLoginUI.js

2
README.md

@ -18,7 +18,7 @@
## 📄 TODO ## 📄 TODO
- [ ] 弹出键盘不遮挡输入框 - [x] 弹出键盘不遮挡输入框
- [ ] ~~根据像素比例设置登录背景图片大小~~ - [ ] ~~根据像素比例设置登录背景图片大小~~
- [x] 添加应用图标 - [x] 添加应用图标
- [ ] 适配 iOS 登录失败 toast - [ ] 适配 iOS 登录失败 toast

71
src/ui/YooLoginUI.js

@ -8,6 +8,8 @@ import {
Text, Text,
ActivityIndicator, ActivityIndicator,
ToastAndroid, ToastAndroid,
Animated,
Keyboard,
} from 'react-native'; } from 'react-native';
const styles = StyleSheet.create({ const styles = StyleSheet.create({
@ -45,15 +47,37 @@ const styles = StyleSheet.create({
fontSize: 26, fontSize: 26,
}, },
}); });
const AnimatedInput = Animated.createAnimatedComponent(TextInput);
const AnimatedImage = Animated.createAnimatedComponent(Image);
const AnimatedTouchableOpacity = Animated.createAnimatedComponent(TouchableOpacity);
export default class YooLoginUI extends Component { export default class YooLoginUI extends Component {
constructor(props) { constructor(props) {
super(props); super(props);
this.state = { this.state = {
loading: false, loading: false,
translateY: new Animated.Value(0),
}; };
this.onButtonPress = this.onButtonPress.bind(this); this.onButtonPress = this.onButtonPress.bind(this);
this.onLoginFailed = this.onLoginFailed.bind(this); this.onLoginFailed = this.onLoginFailed.bind(this);
this.onKeyboardDidShow = this.onKeyboardDidShow.bind(this);
this.onKeyboardDidHide = this.onKeyboardDidHide.bind(this);
}
componentDidMount() {
this.keyboardDidShowListener = Keyboard.addListener(
'keyboardDidShow',
this.onKeyboardDidShow,
);
this.keyboardDidHideListener = Keyboard.addListener(
'keyboardDidHide',
this.onKeyboardDidHide,
);
}
componentWillUnmount() {
this.keyboardDidShowListener.remove();
this.keyboardDidHideListener.remove();
} }
onButtonPress() { onButtonPress() {
@ -68,31 +92,64 @@ export default class YooLoginUI extends Component {
ToastAndroid.show(hint, ToastAndroid.SHORT); ToastAndroid.show(hint, ToastAndroid.SHORT);
} }
onKeyboardDidShow() {
Animated.timing(this.state.translateY, {
toValue: -320,
duration: 250,
useNativeDriver: true,
}).start();
}
onKeyboardDidHide() {
Animated.timing(this.state.translateY, {
toValue: 0,
duration: 250,
useNativeDriver: true,
}).start();
}
render() { render() {
return ( return (
<View style={styles.container}> <View style={styles.container}>
<Image source={require('../../assets/icon.png')} style={styles.logo} /> <AnimatedImage
<TextInput source={require('../../assets/icon.png')}
style={styles.input} style={[
styles.logo,
{transform: [{translateY: this.state.translateY}]},
]}
/>
<AnimatedInput
style={[
styles.input,
{transform: [{translateY: this.state.translateY}]},
]}
placeholder={'账号'} placeholder={'账号'}
maxLength={10} maxLength={10}
value={this.props.username} value={this.props.username}
onChangeText={(username) => this.props.setUsername(username)} onChangeText={(username) => this.props.setUsername(username)}
/> />
<TextInput <AnimatedInput
style={styles.input} style={[
styles.input,
{transform: [{translateY: this.state.translateY}]},
]}
placeholder={'密码'} placeholder={'密码'}
secureTextEntry={true} secureTextEntry={true}
value={this.props.password} value={this.props.password}
onChangeText={(password) => this.props.setPassword(password)} onChangeText={(password) => this.props.setPassword(password)}
/> />
<TouchableOpacity style={styles.button} onPress={this.onButtonPress}> <AnimatedTouchableOpacity
style={[
styles.button,
{transform: [{translateY: this.state.translateY}]},
]}
onPress={this.onButtonPress}>
{this.state.loading ? ( {this.state.loading ? (
<ActivityIndicator size="large" color="#00ff00" /> <ActivityIndicator size="large" color="#00ff00" />
) : ( ) : (
<Text style={styles.buttonText}>登录</Text> <Text style={styles.buttonText}>登录</Text>
)} )}
</TouchableOpacity> </AnimatedTouchableOpacity>
</View> </View>
); );
} }

Loading…
Cancel
Save