I'm trying to create a new simple app. While in this process, I've decided to start with a login page and a sign up page. These pages have the same styling, where the top third of the screen is a container with a logo in it, and the bottom two thirds is a form with input fields.
The problem that I'm stuck at now is that everything looks great, but when you press one of the inputs then the keyboard covers most of the inputs. I've done a little research and I've tried to apply both ScrollView and KeyboardAvoidingView, but neither of these seem to work properly.
This is how my page is set up:
<View style={styles.screen}>
{this.state.loading && (
<View style={styles.loading}>
<ActivityIndicator
color={primaryColor}
size="large"
/>
</View>
)}
<View style={styles.logoContainer}>
<Image source={require('../../../assets/logo.png')} style={styles.logo} />
</View>
<View style={styles.formContainer}>
<KeyboardAvoidingView
behavior={'padding'}
enabled
style={styles.form}
>
<FloatingLabelInput
blurOnSubmit={false}
editable={true}
keyboardType={'email-address'}
label="Email"
onChangeText={this.handleEmailChange}
onSubmitEditing={() => this.passwordInput && this.passwordInput.focus()}
ref={(input) => { this.emailInput = input; }}
returnKeyType="next"
value={this.state.email}
/>
<FloatingLabelInput
editable={true}
label="Password"
onChangeText={this.handlePasswordChange}
onSubmitEditing={() => this.signup()}
ref={(input) => { this.passwordInput = input; }}
secureTextEntry={true}
value={this.state.password}
/>
</KeyboardAvoidingView>
<View style={styles.buttonContainer}>
<Button buttonFunction={() => this.signup()} buttonStyle={'primary'} buttonText={'Sign Up'} />
</View>
</View>
</View>
I feel like I've exhausted most solutions, but I must be missing something crucial.
I had added a Content component in your code, which solves your problem. I don't know why issue had gone by removing KeyboardAvoidingView, but if you want to use KeyboardAvoidingView you can do like this.
<View style={styles.container}>
<Content>
<View style={{ alignItems: "center", marginTop: "50%" }}>
<Image source={require('../assets/CustomLogo1.png')} style={{ marginLeft: 10, marginBottom: 20, height: 200, width: 200 }} />
</View>
<View>
<KeyboardAvoidingView behavior={Platform.Os == "ios" ? "padding" : "height"}>
<FloatingLabelInput
blurOnSubmit={false}
editable={true}
keyboardType={'email-address'}
label="Email"
onChangeText={this.handleEmailChange}
onSubmitEditing={() => this.passwordInput && this.passwordInput.focus()}
ref={(input) => { this.emailInput = input; }}
returnKeyType="next"
value="sample mail"
/>
<FloatingLabelInput
editable={true}
label="Password"
onChangeText={this.handlePasswordChange}
onSubmitEditing={() => this.signup()}
ref={(input) => { this.passwordInput = input; }}
secureTextEntry={true}
value="password"
/>
</KeyboardAvoidingView>
<View style={{ marginTop: 20 }}>
<Button buttonFunction={() => this.signup()} title="sign up" />
</View>
</View>
</Content>
</View>
Initial login page when there is a problem in focusing password:
After making some necessary changes it will be like this:
Just add a content component which can be imported from native base after your View component. I think removing KeyBoardAvoidingView will not fix the issue for smaller screens.
Hope this helps!
Related
I am using a ScrollView in my react-native app. The App work fine in my iOS simulator but when I test in my Android emulator the ScrollView does not work.
Here is what my React Components returns
<SafeAreaView style={styles.container}>
<Image
source={require('../assets/images/logo.png')}
style={styles.logo}
/>
<Androw style={styles.shadow}>
<Text style={[styles.logoText, styles.shadow]}>{NAME}</Text>
</Androw>
<Text style={styles.title}>Welcome Back</Text>
<View style={styles.subContainer}>
<ScrollView showsVerticalScrollIndicator={false}>
<Text style={styles.loginText}>Login</Text>
<View style={styles.textBox}>
<Input
// icon="email"
placeholder="Email or username"
autoCapitalize="none"
autoCompleteType="email"
value={this.state.email}
onChangeText={(txt) => this.setState({email: txt})}
/>
<View style={styles.textInput}>
<Input
// icon="pass"
placeholder="Password"
autoCapitalize="none"
autoCompleteType="password"
value={this.state.password}
onChangeText={(txt) => this.setState({password: txt})}
/>
</View>
</View>
<TouchableOpacity>
<Text style={styles.forgotPasswordText}>
Don't remember your password?
</Text>
</TouchableOpacity>
<TouchableOpacity
style={styles.button}
onPress={() => console.log(this.state)}>
<Button text="Login" />
</TouchableOpacity>
<Text style={styles.noAccountText}>
Don't have an account?{' '}
<Text style={styles.signupText}>Signup</Text>
</Text>
</ScrollView>
</View>
</SafeAreaView>
you should wrap your child views inside like
<ScrollView>
<View>
.....
</View>
</ScrollView>
Top <View> must have style flex:1. Alternate try doing like this
<ScrollView contentContainerStyle={{ flexGrow: 1 }}>
...
</ScrollView>
SafeAreaView that does not require flex: 1. Also try removing it from ScrollView too if it is there.
This is what i assume. Would be more helpful if you share your stylesheet also.
I want to change background image dynamically.I tried to know TextInput is focused or not with this way.Also I tried this.text.current.isFocused().But It didn't help me.Anyone knows?
text={};
renderDrawerContent(){
let image = this.text.isFocused() ? require('../assets/images/gyzyl.png') : require('../assets/images/BlackBack.jpg');
return(
<Container style={styles.containerDrawer}>
<ImageBackground
source={image}
style={{flex:1}}
resizeMode={'cover'}
>
<Content style={{ paddingTop: 0, }}>
<View style={{paddingTop: 20}}>
<View style={{flexDirection:'column' , marginVertical:5 ,padding:15}}>
<Text style={styles.search}>Search</Text>
<TextInput ref={ref => this.text=ref} autotFocus={this.state.Focused} underlineColorAndroid={'white'} placeholder='Cinema, Theatre, Concert ...' placeholderTextColor = '#fff' style={{color: '#fff', fontSize: 16 ,flex:1 , borderBottomColor: '#fff'}} />
</View>
</View>
</Content>
</ImageBackground>
</Container>
);
}
You can use the onFocus event from textinput to do this along with onBlur.
Using this method you should add to your state object a value that tracks if the input is focused.
<TextInput onFocus={()=> this.setState({inputFocused: true})} onBlur={()=> this.setState({inputFocused: false})}/>
then just use your inputFocused to check if the input is focused or not
An alternative that I got success.
const [themeInput, setThemeInput] = useState(false)
<TextInput
mode='outlined'
theme={{colors: {primary: `${colors.salmon}`, }}}
onFocus={() =>setThemeInput(true)}
onBlur={() =>setThemeInput(false)}
label="Email"
left={ <TextInput.Icon
name={() => <Feather name='mail' size={26}
color={ themeInput ? colors.salmon : colors.gray3} />} />}
/>
I am trying to disable a TouchableOpacity element when username/password fields are not filled. It does not work. It is always in a disabled state.
I printed the condition !this.state.username || !this.state.password
to console and it is only false when both are filled which is the desired result but the disabled property of TouchableOpacity does not seem to reflect the value in this condition. Below is a snippet of my code:
can anyone suggest a solution to this problem?
<ScrollView style={styles.content}>
<View style={[styles.container, styles.content]}>
<View style={styles.inputContainer}>
<Image style={styles.inputIcon} source={emailicon}/>
<TextInput style={[styles.inputs]}
ref={`username`}
placeholder="Email"
keyboardType="email-address"
underlineColorAndroid='transparent'
onChangeText={(text) => {this.state.username = text}}
required={true}
/>
</View>
<View style={styles.inputContainer}>
<Image style={styles.inputIcon} source={keyicon}/>
<TextInput
style={styles.inputs}
ref={`password`}
placeholder="Password"
secureTextEntry={true}
underlineColorAndroid='transparent'
onChangeText={(text) => {this.state.password = text}}
required={true}
/>
</View>
<TouchableOpacity style={[styles.buttonContainer, styles.loginButton]}
onPress={() => { console.log(!this.state.username || !this.state.password) }} disabled={!this.state.username || !this.state.password}>
<Text style={styles.loginText}>Login</Text>
</TouchableOpacity>
Try to use setState instead of assign value this state in onChangeText.
Just replace this line in both textInput
onChangeText={(text) => {this.setState({username:text})}}
and
onChangeText={(text) => {this.setState({password:text})}}
This is my code:
<TouchableWithoutFeedback onPress={Keyboard.dismiss}>
<KeyboardAvoidingView style={styles.container} behavior="padding" enabled>
<Text style={styles.title}>Login</Text>
<ActivityIndicator size="large" color="#0000ff" animating={this.state.isProcessing} />
<View style={styles.inputContainer}>
<TextInput
style={styles.textInput}
onChangeText={(email) => this.setState({ email })}
value={this.state.email}
keyboardType="email-address"
textContentType="emailAddress"
placeholder="Email"
editable={!this.state.isProcessing}
/>
</View>
<View style={styles.inputContainer}>
<TextInput
style={styles.textInput}
onChangeText={(password) => this.setState({ password })}
value={this.state.password}
secureTextEntry={true}
placeholder="Password"
editable={!this.state.isProcessing}
/>
</View>
<View style={styles.inputContainer}>
<TouchableOpacity
style={styles.button}
onPress={this.logIn.bind(this)}
disabled={this.state.isProcessing}
>
<Text style={{ color: '#fefffe' }}>Login</Text>
</TouchableOpacity>
</View>
</KeyboardAvoidingView>
</TouchableWithoutFeedback>
Keyboard.dismiss can work properly, but KeyboardAvoidingView does not work completely.
If I touch the TextInput, KeyboardAvoidingView will not adjust position based on the position of the keyboard.
Why does this happened?
Please help me. Thanks a lot.
i try to used shoutem/ui in my project! I create one component for login/register, it work well in iOS, but at android i got issue like picture below there, here is my code:
<Screen
style={{
backgroundColor: '#2ecc71'
}}
>
<StatusBar
barStyle="light-content"
/>
<NavigationBar
styleName="no-border"
style={{
container: {
position: 'relative',
width: Dimensions.get('window').width,
backgroundColor: '#2ecc71'
}
}}
/>
<View
style={{
alignItems: 'center',
flexGrow: 1,
justifyContent: 'center',
}}
>
<Divider />
<Image
styleName="medium-square"
source={require('../images/logo.png')}
/>
{this.renderSpinner()}
<Divider />
<TextInput
placeholder={'Username or email'}
editable={!this.state.statusButton}
onChangeText={(text) => this.setState({ email: text })}
keyboardType="email-address"
autoCapitalize="none"
autoCorrect={false}
/>
<Divider styleName="line" />
<TextInput
editable={!this.state.statusButton}
onChangeText={(text) => this.setState({ password: text })}
placeholder={'Password'}
secureTextEntry
autoCapitalize="none"
/>
<Divider />
<View styleName="horizontal flexible">
<Button
disabled={this.state.statusButton}
styleName="full-width confirmation"
onPress={this.onLoginPressed.bind(this)}
>
<Text>LOGIN</Text>
</Button>
<Button
disabled={this.state.statusButton}
styleName="full-width confirmation"
onPress={this.goToRegister.bind(this)}
>
<Text>REGISTER</Text>
</Button>
</View>
</View>
</Screen>
and here is result iOS/android:
If I'm not mistaken, you never specify a width for your TextInput components.
<TextInput
placeholder={'Username or email'}
editable={!this.state.statusButton}
onChangeText={(text) => this.setState({ email: text })}
keyboardType="email-address"
autoCapitalize="none"
autoCorrect={false}
/>
<TextInput
editable={!this.state.statusButton}
onChangeText={(text) => this.setState({ password: text })}
placeholder={'Password'}
secureTextEntry
autoCapitalize="none"
/>
It looks like by default on iOS a TextInput will stretch to the max screen width, but on android it'll shrink as you can see in your own screenshots.
Add a width and you should be good to go.
<TextInput
placeholder={'Username or email'}
editable={!this.state.statusButton}
onChangeText={(text) => this.setState({ email: text })}
keyboardType="email-address"
autoCapitalize="none"
autoCorrect={false}
style={{ width: 100% }}
/>