React Native Scroll View bounces back to top - react-native

I am trying to implement a SrollView in my project however for some reason when I try to scroll through all the elements inside it, it springs back to the top of the ScrollView. I've looked around and some other questions were resolved by adding flex:1 to the ScrollView, however when I try that the entire ScrollView goes off screen. I've tried to add position:'absolute' to the ScrollView however that only leads to the scrollView not moving anymore
I've also tried experimenting with <KeyboardAwareScrollView> however the screen doesn't seem to adjust to the Input.
Here is my code:
import React from "react";
import {
View,
Dimensions,
Platform,
ActivityIndicator,
Alert,
Image,
KeyboardAvoidingView,
TouchableHighlight,
Keyboard
} from "react-native";
import { KeyboardAwareScrollView } from 'react-native-keyboard-aware-scroll-view'
import { Form, Item, Input, Label, Button, Text, Picker } from "native-base";
import * as firebase from "firebase";
import { ScrollView } from "react-native-gesture-handler";
import { LinearGradient, ImagePicker, Permissions } from "expo";
import Modal from "react-native-modal";
import uuid from "uuid";
import axios from "axios";
<View style={{borderBottomLeftRadius:20, borderBottomRightRadius:20, marginTop:20}}>
<TouchableHighlight onPress={this.toggleModal} underlayColor="white">
<Image source={{ uri: this.state.imageUrl }} style={{ width: SCREEN_WIDTH, height: SCREEN_HEIGHT/3, borderRadius: 20, marginBottom:20 }}/>
</TouchableHighlight>
</View>
}
{!this.state.loading ? (
<Button
full
style={{
fontFamily: "nunito",
backgroundColor: 'transparent',
alignSelf: "center",
height: SCREEN_HEIGHT/3,
width: SCREEN_WIDTH
}}
onPress={() => this.alertOptions()}
>
<View style={{flexDirection:'column'}}>
<Text
style={{
fontFamily: "nunito",
color: "black",
fontSize: 30,
textAlign: 'center'
}}
>
{this.state.imageUrl === ""
? "Tap"
: ""}
</Text>
<Text
style={{
fontFamily: "nunito",
color: "black",
fontSize: 30,
textAlign: 'center'
}}
>
{this.state.imageUrl === ""
? "to"
: ""}
</Text>
<Text
style={{
fontFamily: "nunito",
color: "black",
fontSize: 30,
textAlign:'center'
}}
>
{this.state.imageUrl === ""
? "Upload Photo"
: ""}
</Text>
</View>
</Button>
) : (
<Text style={{color:'white', textAlign:'center', fontSize: 40, marginTop: 25}}>Loading...Please Wait</Text>
)}
</View>
<View>
<ScrollView showsVerticalScrollIndicator={false} style={{ borderTopRightRadius: -20, borderTopLeftRadius: -20, backgroundColor:"#a2b6d8",}}>
<Text
style={{
fontSize: 28,
color: "#404040",
fontWeight: "700",
marginLeft: 12,
marginBottom: 10,
marginTop: 20,
textAlign: "center"
}}
>
Enter your details below
</Text>
<Form>
<Item stackedLabel rounded>
<Label style={{ fontFamily: "nunito" }}>
Address (Street, City)<Text style={{ color: "red", marginLeft: 10 }}>*</Text>
</Label>
<Input
placeholderTextColor="#9e9e9e"
placeholder="Required"
onChangeText={e => this.setState({ address: e })}
style={{ fontFamily: "nunito" }}
/>
</Item>
<Item stackedLabel>
<Label style={{ fontFamily: "nunito" }}>
Name
<Text style={{ color: "red", marginLeft: 10 }}>*</Text>
</Label>
<Input
placeholderTextColor="#9e9e9e"
placeholder="Required"
onChangeText={e => this.setState({ name: e })}
style={{ fontFamily: "nunito" }}
/>
</Item>
<Item stackedLabel>
<Label style={{ fontFamily: "nunito" }}>
Contractor{" "}
<Text style={{ color: "red", marginLeft: 10 }}>*</Text>
</Label>
<Input
placeholderTextColor="#9e9e9e"
placeholder="Required"
onChangeText={e => this.setState({ contractor: e })}
style={{ fontFamily: "nunito" }}
/>
</Item>
<Item stackedLabel>
<Label style={{ fontFamily: "nunito" }}>
Zip
<Text style={{ color: "red", marginLeft: 10 }}>*</Text>
</Label>
<Input
placeholderTextColor="#9e9e9e"
placeholder="Required"
onChangeText={e => this.setState({ zip: e })}
style={{ fontFamily: "nunito" }}
/>
</Item>
<Item stackedLabel>
<Label style={{ fontFamily: "nunito" }}>
Type of work performed
<Text style={{ color: "red", marginLeft: 10 }}>*</Text>
</Label>
<Input
placeholderTextColor="#9e9e9e"
placeholder="Required"
onChangeText={e => this.setState({ performed: e })}
style={{ fontFamily: "nunito" }}
/>
</Item>
</Form>
<View
style={{
flexDirection: "row",
justifyContent: "center",
alignItems: "center",
marginTop: 20,
marginBottom: 10
}}
>
</View>
<View
style={{
justifyContent:'space-around',
marginLeft: 15,
flexDirection:'row'
}}
>
{!this.state.loader ? (
<Button
full
style={{
fontFamily: "nunito",
backgroundColor: "#f3d95c",
width: SCREEN_WIDTH/3,
borderRadius:50,
shadowColor: "#918236",
shadowOffset: {
width: 0,
height: 0,
},
shadowOpacity: 0.8,
shadowRadius: 4,
// alignSelf: "center",
}}
onPress={() => this.add()}
>
<Text
style={{
fontFamily: "nunito",
color: "black",
fontSize: 22
}}
>
SEND
</Text>
</Button>
) : (
<ActivityIndicator size="large" color="#f3d95c" />
)}
<Button
onPress={() => this.logout()}
style={{ alignSelf: "center", marginBottom: 20, backgroundColor:'red', borderRadius:50 }}
>
<Text style={{fontSize:18}}>Logout</Text>
</Button>
</View>
</ScrollView>
</View>

Replace the content of the files.
EnterDetails.js
import React from "react";
import {
View,
Dimensions,
Platform,
ActivityIndicator,
Alert,
Image,
KeyboardAvoidingView,
TouchableHighlight,
TouchableWithoutFeedback,
Keyboard,
ScrollView
} from "react-native";
import { KeyboardAwareScrollView } from "react-native-keyboard-aware-scroll-view";
import { Form, Item, Input, Label, Button, Text, Picker } from "native-base";
import * as firebase from "firebase";
import { LinearGradient, ImagePicker, Permissions } from "expo";
import Modal from "react-native-modal";
import uuid from "uuid";
import axios from "axios";
const SCREEN_WIDTH = Dimensions.get("window").width;
const SCREEN_HEIGHT = Dimensions.get("window").height;
export default class EnterDetails extends React.Component {
constructor(props) {
super(props);
this.state = {
loader: false,
loading: false,
address: "",
name: "",
contractor: "",
zip: "",
email: "frank.gully2800#gmail.com",
// userEmail: firebase.auth().currentUser.email,
imageUrl: "",
performed: ""
};
}
state = {
isModalVisible: false
};
toggleModal = () => {
this.setState({ isModalVisible: !this.state.isModalVisible });
};
onValueChange(value) {
this.setState({
selected: value
});
}
imagePicker = () => {
Permissions.askAsync(Permissions.CAMERA_ROLL);
ImagePicker.launchImageLibraryAsync({
allowsEditing: false,
base64: true
}).then(async result => {
const blob = await new Promise((resolve, reject) => {
const xhr = new XMLHttpRequest();
xhr.onload = function() {
resolve(xhr.response);
};
xhr.onerror = function(e) {
reject(new TypeError("Network request failed"));
};
xhr.responseType = "blob";
xhr.open("GET", result.uri, true);
xhr.send(null);
});
const ref = firebase
.storage()
.ref()
.child(uuid.v4());
const snapshot = await ref.put(blob);
blob.close();
let imageUrl = await snapshot.ref.getDownloadURL();
this.setState({ imageUrl: imageUrl, loading: false });
});
};
cameraUsage = () => {
this.setState({ loading: true });
Permissions.askAsync(Permissions.CAMERA);
ImagePicker.launchCameraAsync({
allowsEditing: false,
base64: true
}).then(async result => {
const blob = await new Promise((resolve, reject) => {
const xhr = new XMLHttpRequest();
xhr.onload = function() {
resolve(xhr.response);
};
xhr.onerror = function(e) {
reject(new TypeError("Network request failed"));
};
xhr.responseType = "blob";
xhr.open("GET", result.uri, true);
xhr.send(null);
});
const ref = firebase
.storage()
.ref()
.child(uuid.v4());
const snapshot = await ref.put(blob);
blob.close();
let imageUrl = await snapshot.ref.getDownloadURL();
this.setState({ imageUrl: imageUrl, loading: false });
});
};
add = () => {
if (
this.state.zip !== "" &&
this.state.address !== "" &&
this.state.name !== "" &&
this.state.contractor !== "" &&
this.state.email !== "" &&
this.state.imageUrl !== "" &&
this.state.performed !== ""
) {
const {
name,
imageUrl,
contractor,
address,
email,
zip,
performed
} = this.state;
axios
.post(
"https://us-central1-cccproject-2b2f6.cloudfunctions.net/sendMailToUser",
{
zip: zip,
name: name,
imageUrl: imageUrl,
address: address,
email: email,
contractor: contractor,
performed: performed,
userEmail: this.state.userEmail
}
)
.then(response => {
Alert.alert("Details Sent");
})
.catch(error => {});
} else {
Alert.alert("Please Complete The form");
}
};
alertOptions = () => {
Alert.alert(
"Photo Options",
"Choose how you upload your photo",
[
{ text: "Camera", onPress: () => this.cameraUsage() },
{
text: "Image Library",
onPress: () => this.imagePicker()
},
{
text: "Cancel",
onPress: () => console.log("Day sayd no :("),
style: "cancel"
}
],
{ cancelable: false }
);
};
logout = () => {
firebase
.auth()
.signOut()
.then(s => {
this.props.navigation.navigate("Login");
})
.catch(e => {});
};
render() {
return (
<View style={{ flex: 1 }}>
<View
style={{
width: SCREEN_WIDTH,
height: SCREEN_HEIGHT / 3,
alignSelf: "center",
marginTop: 0,
backgroundColor: "red",
borderBottomLeftRadius: 20,
borderBottomRightRadius: 20
}}
>
{this.state.imageUrl === "" ? null : (
<View
style={{
borderBottomLeftRadius: 20,
borderBottomRightRadius: 20,
marginTop: 20
}}
>
<TouchableHighlight
onPress={this.toggleModal}
underlayColor="white"
>
<Image
source={{ uri: this.state.imageUrl }}
style={{
width: SCREEN_WIDTH,
height: SCREEN_HEIGHT / 3,
borderRadius: 20,
marginBottom: 20
}}
/>
</TouchableHighlight>
</View>
)}
{!this.state.loading ? (
<Button
full
style={{
fontFamily: "nunito",
backgroundColor: "transparent",
alignSelf: "center",
height: SCREEN_HEIGHT / 3,
width: SCREEN_WIDTH
}}
onPress={() => this.alertOptions()}
>
<View style={{ flexDirection: "column" }}>
<Text
style={{
fontFamily: "nunito",
color: "black",
fontSize: 30,
textAlign: "center"
}}
>
{this.state.imageUrl === "" ? "Tap" : ""}
</Text>
<Text
style={{
fontFamily: "nunito",
color: "black",
fontSize: 30,
textAlign: "center"
}}
>
{this.state.imageUrl === "" ? "to" : ""}
</Text>
<Text
style={{
fontFamily: "nunito",
color: "black",
fontSize: 30,
textAlign: "center"
}}
>
{this.state.imageUrl === "" ? "Upload Photo" : ""}
</Text>
</View>
</Button>
) : (
<Text
style={{
color: "white",
textAlign: "center",
fontSize: 40,
marginTop: 25
}}
>
Loading...Please Wait
</Text>
)}
</View>
<View style={{ borderWidth: 2, borderColor: "pink", flex: 1 }}>
<ScrollView
style={{
borderTopRightRadius: -20,
borderTopLeftRadius: -20,
backgroundColor: "#a2b6d8",
position: "relative",
flex: 1
}}
>
<Text
style={{
fontSize: 28,
color: "#404040",
fontWeight: "700",
marginLeft: 12,
marginBottom: 10,
marginTop: 20,
textAlign: "center"
}}
>
Enter your details below
</Text>
<Form>
<Item stackedLabel rounded>
<Label style={{ fontFamily: "nunito" }}>
Address (Street, City)
<Text style={{ color: "red", marginLeft: 10 }}>*</Text>
</Label>
<Input
placeholderTextColor="#9e9e9e"
placeholder="Required"
onChangeText={e => this.setState({ address: e })}
style={{ fontFamily: "nunito" }}
/>
</Item>
<Modal isVisible={this.state.isModalVisible}>
<Image
source={{ uri: this.state.imageUrl }}
style={{
width: SCREEN_WIDTH / 1.1,
height: SCREEN_HEIGHT / 1.1,
justifyContent: "center",
alignSelf: "center",
marginBottom: 0
}}
resizeMode="contain"
/>
<Button
style={{
backgroundColor: "red",
borderBottomRightRadius: 20,
borderBottomLeftRadius: 20,
borderTopLeftRadius: 20,
borderTopRightRadius: 20,
width: SCREEN_WIDTH - 20,
alignSelf: "center",
justifyContent: "center"
}}
onPress={this.toggleModal}
>
<Text style={{ fontFamily: "nunito", textAlign: "center" }}>
Close
</Text>
</Button>
</Modal>
<Item stackedLabel>
<Label style={{ fontFamily: "nunito" }}>
Name
<Text style={{ color: "red", marginLeft: 10 }}>*</Text>
</Label>
<Input
placeholderTextColor="#9e9e9e"
placeholder="Required"
onChangeText={e => this.setState({ name: e })}
style={{ fontFamily: "nunito" }}
/>
</Item>
<Item stackedLabel>
<Label style={{ fontFamily: "nunito" }}>
Contractor{" "}
<Text style={{ color: "red", marginLeft: 10 }}>*</Text>
</Label>
<Input
placeholderTextColor="#9e9e9e"
placeholder="Required"
onChangeText={e => this.setState({ contractor: e })}
style={{ fontFamily: "nunito" }}
/>
</Item>
<Item stackedLabel>
<Label style={{ fontFamily: "nunito" }}>
Zip
<Text style={{ color: "red", marginLeft: 10 }}>*</Text>
</Label>
<Input
placeholderTextColor="#9e9e9e"
placeholder="Required"
onChangeText={e => this.setState({ zip: e })}
style={{ fontFamily: "nunito" }}
/>
</Item>
<Item stackedLabel>
<Label style={{ fontFamily: "nunito" }}>
Type of work performed
<Text style={{ color: "red", marginLeft: 10 }}>*</Text>
</Label>
<Input
placeholderTextColor="#9e9e9e"
placeholder="Required"
onChangeText={e => this.setState({ performed: e })}
style={{ fontFamily: "nunito" }}
/>
</Item>
</Form>
<View
style={{
flexDirection: "row",
justifyContent: "center",
alignItems: "center",
marginTop: 20,
marginBottom: 10
}}
></View>
<View
style={{
justifyContent: "space-around",
marginLeft: 15,
flexDirection: "row"
}}
>
{!this.state.loader ? (
<Button
full
style={{
fontFamily: "nunito",
backgroundColor: "#f3d95c",
width: SCREEN_WIDTH / 3,
borderRadius: 50,
shadowColor: "#918236",
shadowOffset: {
width: 0,
height: 0
},
shadowOpacity: 0.8,
shadowRadius: 4
// alignSelf: "center",
}}
onPress={() => this.add()}
>
<Text
style={{
fontFamily: "nunito",
color: "black",
fontSize: 22
}}
>
SEND
</Text>
</Button>
) : (
<ActivityIndicator size="large" color="#f3d95c" />
)}
<Button
onPress={() => this.logout()}
style={{
alignSelf: "center",
marginBottom: 20,
backgroundColor: "red",
borderRadius: 50
}}
>
<Text style={{ fontSize: 18 }}>Logout</Text>
</Button>
</View>
</ScrollView>
</View>
</View>
);
}
}
App.js
import React from "react";
import { AppLoading } from "expo";
import * as Font from "expo-font";
import { Ionicons } from "#expo/vector-icons";
import Routes from "./Routes";
import { View, StatusBar } from "react-native";
import * as firebase from "firebase";
var firebaseConfig = {//ADD YOUR CREDS HERE};
// Initialize Firebase
firebase.initializeApp(firebaseConfig);
export default class App extends React.Component {
state = {
isReady: true,
isTrue: false
};
async componentWillMount() {
await Font.loadAsync({
...Ionicons.font,
Roboto: require("native-base/Fonts/Roboto.ttf"),
Roboto_medium: require("native-base/Fonts/Roboto_medium.ttf"),
nunito: require("./assets/nunito/Nunito-Regular.ttf"),
MonReg: require("./assets/Montserrat-Regular.ttf"),
MonBold: require("./assets/Montserrat-Bold.ttf")
});
this.setState({ isReady: false });
}
render() {
setTimeout(() => this.setState({ isTrue: true }), 6000);
if (this.state.isReady) {
return <AppLoading />;
}
return (
<View style={{ flex: 1 }}>
<StatusBar backgroundColor="rgba(255,255,255,1)" />
<Routes />
</View>
);
}
}

Related

Why does my keyboard get dismissed at each keystroke when I extract a View with a TextInput to a function, but not when I return it directly?

I created a FormInput component which encapsulates a View with a TextInput:
<FormInput inputType="text" title={translate("Exam Name")} value={name} setValue={setName} ref={examNameRef} required />
Inside FormInput I do the following:
if (inputType === 'text') {
// return (
// <View style={[styles.button, { height: 90 }]} >
// <View style={{ flexDirection: 'row' }}>
// <Text style={[styles.fieldLabel, {}]}>{title}</Text>
// {required && <Text style={{ color: 'red' }}>{' *'}</Text>}
// </View>
// <View>
// {requiredValidationError ?
// <Text style={[styles.fieldValue, { borderColor: 'red', color: 'red' }]}>{'Campo Obrigatório'}</Text>
// :
// <TextInput style={[styles.fieldValue]} value={value} onChangeText={setValue} />
// }
// </View>
// </View>
// )
return <InputText />
The function InputText has the same code as the commented code above:
function InputText() {
return (
<View style={[styles.button, { height: 90 }]} >
<View style={{ flexDirection: 'row' }}>
<Text style={[styles.fieldLabel, {}]}>{title}</Text>
{required && <Text style={{ color: 'red' }}>{' *'}</Text>}
</View>
<View>
{requiredValidationError ?
<Text style={[styles.fieldValue, { borderColor: 'red', color: 'red' }]}>{'Campo Obrigatório'}</Text>
:
<TextInput style={[styles.fieldValue]} value={value} onChangeText={setValue} />
}
</View>
</View>
)
}
When I use it like this my keyboard keeps getting dismissed at every key stroke,but when I uncomment the commented part above and return the View directly instead of putting it inside a function this bug doesn't happen. What could be the problem?
Here's the whoe FormInput.js:
import React, { useState, useEffect, useRef, forwardRef, useImperativeHandle } from 'react';
import { Text, Pressable, View, TextInput, SafeAreaView, TouchableOpacity, Platform, ActivityIndicator, StyleSheet, Switch } from 'react-native';
import { useNavigation, useRoute, useTheme } from '#react-navigation/native';
import { translate } from '../../translate';
import Page from '../../components/Page';
import Picker from '../../components/Picker';
import Modal from '../../components/Modal';
import Button from '../../components/Button';
import DateTimePicker from '#react-native-community/datetimepicker';
import Toast from 'react-native-simple-toast';
import moment from 'moment';
import Icon from 'react-native-vector-icons/Ionicons';
Icon.loadFont();
const FormInput = forwardRef(({ inputType, title, value, setValue, required, maxLength }, ref) => {
const [modalVisible, setModalVisible] = useState(false);
const [internalValue, setInternalValue] = useState(value);
const [dateTimePickerMode, setDateTimePickerMode] = useState("date");
const [date, setDate] = useState(new Date());
const [requiredValidationError, setRequiredValidationError] = useState(false);
const inputRef = useRef();
useImperativeHandle(ref, () => ({
validate() {
if (required) {
if (internalValue) {
setRequiredValidationError(false)
} else {
setRequiredValidationError(true)
}
}
},
error: requiredValidationError
}));
const onChangeDate = (event, newDate) => {
if (event.type === "dismissed") {
setDateTimePickerMode("date")
setModalVisible(false);
return;
}
const dateWithTime = new Date(date);
if (dateTimePickerMode === 'date') {
setModalVisible(true);
setDate(newDate || new Date());
setDateTimePickerMode('time');
} else {
setModalVisible(false);
dateWithTime.setHours(newDate.getHours());
dateWithTime.setMinutes(newDate.getMinutes());
setDateTimePickerMode('date');
setValue(dateWithTime);
}
}
function InputSwitch() {
return (
<View style={[styles.button, { paddingRight: 15 }]} >
<Text style={[styles.fieldLabel, { marginBottom: 10 }]}>{title}</Text>
<View style={{ marginRight: 30 }}>
<Switch
style={{ transform: [{ scaleX: Platform.select({ ios: 0.8, android: 1.3 }) }, { scaleY: Platform.select({ ios: 0.8, android: 1.3 }) }] }}
thumbColor={"#f4f3f4"}
onValueChange={setValue}
value={value}
/>
</View>
</View>
)
}
function InputText() {
return (
<View style={[styles.button, { height: 90 }]} >
<View style={{ flexDirection: 'row' }}>
<Text style={[styles.fieldLabel, {}]}>{title}</Text>
{required && <Text style={{ color: 'red' }}>{' *'}</Text>}
</View>
<View>
{requiredValidationError ?
<Text style={[styles.fieldValue, { borderColor: 'red', color: 'red' }]}>{'Campo Obrigatório'}</Text>
:
<TextInput style={[styles.fieldValue]} value={value} onChangeText={setValue} />
}
</View>
</View>
)
}
function InputNumber() {
return (
<View style={[styles.button, { height: 90 }]} >
<View style={{ flexDirection: 'row' }}>
<Text style={[styles.fieldLabel, {}]}>{title}</Text>
{required && <Text style={{ color: 'red' }}>{' *'}</Text>}
</View>
<View>
<Text style={[styles.fieldValue, { borderColor: requiredValidationError ? 'red' : 'grey', color: requiredValidationError ? 'red' : 'grey' }]}>{requiredValidationError ? 'Campo Obrigatório' : value}</Text>
</View>
</View>
)
}
function InputDate() {
return (
<View>
{inputType === 'date' && modalVisible && (
<DateTimePicker
testID="dateTimePicker"
value={internalValue ? new Date(internalValue) : new Date()}
is24Hour={true}
mode={dateTimePickerMode}
onChange={onChangeDate}
/>
)}
<Pressable style={[styles.button, { height: 90 }]} onPress={() => setModalVisible(true)} >
<View style={{ flexDirection: 'row' }}>
<Text style={[styles.fieldLabel, {}]}>{title}</Text>
{required && <Text style={{ color: 'red' }}>{' *'}</Text>}
</View>
<Text style={styles.fieldValue}>{value ? moment(value).format('DD/MM/yyyy HH:mm') : ''}</Text>
</Pressable>
</View>
)
}
if (inputType === 'text') {
// return (
// <View style={[styles.button, { height: 90 }]} >
// <View style={{ flexDirection: 'row' }}>
// <Text style={[styles.fieldLabel, {}]}>{title}</Text>
// {required && <Text style={{ color: 'red' }}>{' *'}</Text>}
// </View>
// <View>
// {requiredValidationError ?
// <Text style={[styles.fieldValue, { borderColor: 'red', color: 'red' }]}>{'Campo Obrigatório'}</Text>
// :
// <TextInput style={[styles.fieldValue]} value={value} onChangeText={setValue} />
// }
// </View>
// </View>
// )
return <InputText />
} else if (inputType === 'number') {
return <InputNumber />
} else if (inputType === 'switch') {
return <InputSwitch />
} else if (inputType === 'date') {
return <InputDate />
} else {
return <Text style={{ backgroundColor: 'orange', textAlign: 'center', padding: 10, margin: 10 }}>Input do tipo {inputType} não está implementado</Text>
}
})
const styles = StyleSheet.create({
container: {
backgroundColor: '#A7A6A6',
marginBottom: 100
},
header: {
backgroundColor: '#FF000010',
flexDirection: 'row',
justifyContent: 'center',
alignItems: 'center',
paddingHorizontal: 16,
paddingVertical: Platform.select({ ios: 10, android: 10 })
},
title: {
flex: 1,
fontSize: 32,
color: '#626262',
fontWeight: 'bold',
backgroundColor: '#00FF0010',
},
modalView: {
marginVertical: 230,
marginHorizontal: 20,
backgroundColor: "white",
borderRadius: 20,
padding: 35,
alignItems: "center",
shadowColor: "#000",
shadowOffset: {
width: 0,
height: 2
},
shadowOpacity: 0.25,
shadowRadius: 4,
elevation: 5
},
button: {
padding: 5
},
fieldLabel: {
color: "grey",
fontWeight: "bold",
textAlign: "left"
},
fieldValue: {
color: "black",
textAlign: "right",
borderBottomWidth: 1,
paddingTop: 10,
paddingRight: 10,
paddingBottom: 5,
textAlign: 'right',
borderColor: 'grey',
},
modalText: {
marginBottom: 15,
textAlign: "center"
},
textInput: {
borderWidth: 0,
paddingHorizontal: 20,
fontSize: 16,
marginBottom: 4,
color: '#626262',
borderRadius: 0,
borderBottomWidth: 1,
borderColor: '#626262',
width: 300,
textAlign: 'center'
},
});
export default FormInput;
And the return of the parent component:
return (
<>
<Page type="static" title={'Avaliação'} subtitle={'Editar'}>
<ScrollView style={{ flexGrow: 0.8, paddingHorizontal: 5}} keyboardShouldPersistTaps="always">
<FormInput inputType="text" title={translate("Exam Name")} value={name} setValue={setName} ref={examNameRef} required />
<FormInput inputType="text" title={translate("Code")} value={code} setValue={setCode} maxLength={8} ref={examCodeRef} required />
<FormInput inputType="number" title={translate("Max Grade")} value={maxGrade} setValue={setMaxGrade} />
<FormInput inputType="number" title={translate("Weight")} value={weight} setValue={setWeight} ref={examWeightRef} required />
<FormInput inputType="date" title={translate("Start Date")} value={startDate} setValue={setStartDate} />
<FormInput inputType="date" title={translate("End Date")} value={endDate} setValue={setEndDate} />
<FormInput inputType="switch" title={translate("Ignore Formula")} value={ignoreFormula} setValue={setIgnoreFormula} />
</ScrollView>
</Page>
<View style={{}}>
<Button style={[styles.button, {}]} textStyle={styles.buttonText} title={translate('Save')} onPress={() => saveExam()} requestFeedback />
</View>
</>
);

Emailvalidator (require("email-validator") stopped working

I am doing email validation in my Signup form and all of a sudden it doesn't work anymore. I didn't change the signup.js file so it is a bit strange. I started working on the login.js file today so maybe there is some 'interference', but I don't have any idea where to look fist to be honest.
So here is the signup.js, where I put the emailvalidation that doesn't work anymore in bold.
import React, { Component } from 'react';
import { Text, StyleSheet, TouchableOpacity, Image, TextInput, View } from 'react-native';
import firebase from 'react-native-firebase';
var validator = require("email-validator");
export default class loginComponent extends Component {
constructor(props) {
super(props);
this.state = {firstName: ''};
this.state = {lastName: ''};
this.state = {email: ''};
this.state = {password: ''};
this.state = {emailValidated: false};
this.state = {errorMessage: null};
}
handleSignUp = () => {
firebase
.auth()
.createUserWithEmailAndPassword(this.state.email, this.state.password)
.then(() => this.props.navigation.navigate('Main'))
.catch(error => this.setState({ errorMessage: error.message }))
}
render() {
function renderEmailValidationState(emailInput) {
if(validator.validate(emailInput)) {
return false;
} else {
return true;
}
}
return (
<View style={styles.container}>
<View style={styles.logoContainer} >
<Image source={require('./assets/logo.png')} style={styles.logo}></Image>
<Text style={styles.slush}>
Lenen of huren, {"\n"} bij de buren!
</Text>
</View>
<View style={styles.formContainer}>
<View style={styles.inputTextFieldContainer}>
{this.state.errorMessage &&
<Text style={{ color: 'red' }}>
{this.state.errorMessage}
</Text>
}
<TextInput
style={styles.inputTextField}
placeholder="Enter you first name"
value={this.state.text}
backgroundColor="white"
onChangeText={(firstName) => this.setState({firstName})}
/>
<TextInput
style={styles.inputTextField}
placeholder="Enter you last name"
value={this.state.text}
backgroundColor="white"
onChangeText={(lastName) => this.setState({lastName})}
/>
<TextInput
style={styles.inputTextField}
placeholder="Enter your e-mail"
value={this.state.text}
backgroundColor="white"
onChangeText={(email) => this.setState({email})}
/>
<TextInput
style={styles.inputTextField}
placeholder="Enter your password"
value={this.state.password}
backgroundColor="white"
onChangeText={(password) => this.setState({password})}
/>
<TouchableOpacity
disabled= {renderEmailValidationState(this.state.email)}
style={styles.buttonContainer}
onPress={this.handleSignUp}
>
<View>
<Text style={styles.buttonText}>Sign up!</Text>
</View>
</TouchableOpacity>
<Text style={styles.plainText}>
Already a user?
</Text>
<TouchableOpacity
style={styles.buttonContainer}
onPress={() => this.props.navigation.navigate('Login')}
>
<View>
<Text style={styles.buttonText}>Login!</Text>
</View>
</TouchableOpacity>
</View>
</View>
</View>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 2,
padding:10,
backgroundColor:'#c6f1e7',
alignItems: 'stretch',
justifyContent: 'space-around'
},
logoContainer: {
padding: 10,
height: 250,
justifyContent: 'center' ,
alignItems: 'center'
},
logo: {
width: 250,
height: 250
},
slush: {
fontSize: 20,
color: '#59616e',
fontFamily: 'Raleway-Regular'
},
formContainer: {
flex:1,
padding: 10,
},
inputTextFieldContainer: {
padding: 100,
justifyContent: 'space-between',
alignItems: 'center',
marginBottom: 30
},
inputTextField: {
padding: 10,
height: 40,
width: 300,
marginBottom: 10,
fontSize: 16,
fontFamily: 'Raleway-Regular',
},
buttonContainer: {
padding: 10,
marginBottom: 20,
width: 300,
alignItems: 'center',
backgroundColor: '#acdcd7',
},
buttonText: {
padding: 1,
fontSize: 16,
color: '#59616e',
fontFamily: 'Raleway-Regular',
},
plainText: {
padding: 1,
fontSize: 16,
marginBottom: 5,
fontFamily: 'Raleway-Regular',
color: '#59616e'
},
});
And this is the login.js, but that is work in progress.
import React, { Component } from 'react';
import { Text, StyleSheet, TouchableOpacity, Image, TextInput, View } from 'react-native';
import firebase from 'react-native-firebase';
var validator = require("email-validator");
export default class loginComponent extends Component {
constructor(props) {
super(props);
this.state = {email: ''};
this.state = {password: ''};
this.state = {emailValidated: false};
this.state = {errorMessage: null};
}
render() {
function renderEmailValidationState(emailInput) {
if(validator.validate(emailInput)) {
return false;
} else {
return true;
}
}
return (
<View style={styles.container}>
<View style={styles.logoContainer}>
<Image source={require('./assets/logo.png')} style={styles.logo}></Image>
<Text style={styles.slush}>
Huren bij de buren!
</Text>
</View>
<View style={styles.formContainer}>
<View style={styles.inputTextFieldContainer}>
{this.state.errorMessage &&
<Text style={{ color: 'red' }}>
{this.state.errorMessage}
</Text>
}
<TextInput
style={styles.inputTextField}
placeholder="Enter your e-mail"
value={this.state.text}
backgroundColor="white"
onChangeText={(email) => this.setState({email})}
/>
<TextInput
style={styles.inputTextField}
placeholder="Enter your password"
value={this.state.password}
backgroundColor="white"
onChangeText={(password) => this.setState({password})}
/>
<TouchableOpacity
**disabled= {renderEmailValidationState(this.state.email)}**
style={styles.buttonContainer}
onPress={this.handleSignUp}
>
<View>
<Text style={styles.buttonText}>Sign up!</Text>
</View>
</TouchableOpacity>
<Text style={styles.plainText}>
Don't have an account?
</Text>
<TouchableOpacity
style={styles.buttonContainer}
onPress={() => this.props.navigation.navigate('SignUp')}
>
<View>
<Text style={styles.buttonText}>Register!</Text>
</View>
</TouchableOpacity>
</View>
</View>
</View>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 2,
padding:10,
backgroundColor:'#c6f1e7',
alignItems: 'stretch',
justifyContent: 'space-around'
},
logoContainer: {
padding: 10,
height: 350,
justifyContent: 'center' ,
alignItems: 'center'
},
logo: {
width: 250,
height: 250
},
slush: {
fontSize: 25,
color: '#59616e',
fontFamily: 'Raleway-Regular'
},
formContainer: {
flex:1,
padding: 10,
},
inputTextFieldContainer: {
padding: 100,
justifyContent: 'space-between',
alignItems: 'center',
marginBottom: 30
},
inputTextField: {
padding: 10,
height: 40,
width: 300,
marginBottom: 10,
fontSize: 16,
fontFamily: 'Raleway-Regular',
},
buttonContainer: {
padding: 10,
marginBottom: 20,
width: 300,
alignItems: 'center',
backgroundColor: '#acdcd7',
},
buttonText: {
padding: 1,
fontSize: 16,
color: '#59616e',
fontFamily: 'Raleway-Regular',
},
plainText: {
padding: 1,
fontSize: 16,
marginBottom: 5,
fontFamily: 'Raleway-Regular',
color: '#59616e'
},
});
Can anyone point me in the good direction?
Thanks a lot!
Tim
try this npm i raysk-vali
instead of email-validator.
usage:
const { isEmail } = require("raysk-vali");
isEmail("abc#example.com") // return true
isEmail("abcexample.com") // return false
for more checkout the documentation : https://www.npmjs.com/package/raysk-vali.

How to create dynamic checkbox in react native

I am able to create the dynamic checkbox but i need to check and uncheck it separately, right now if i check one everything gets checked and if i uncheck everything gets unchecked.
How to change the value of checkbox separately for each checkbox from state?
import React from 'react';
import {View,Text,StyleSheet,TouchableOpacity,Image,Switch,Platform,Dimensions,PixelRatio,} from'react-native';
import ImagePicker from 'react-native-image-picker';
import { Input, Button } from 'react-native-elements';
import { moderateScale } from 'react-native-size-matters';
const deviceWidth = Dimensions.get('window').width;
const deviceHeight = Dimensions.get('window').height;
const calcHeight = x => PixelRatio.roundToNearestPixel((deviceHeight * x) / 100);
const calcWidth = x => PixelRatio.roundToNearestPixel((deviceWidth * x) / 100);
class ErrorScreen extends React.Component {
constructor() {
super();
this.state = {
arr: [],
parkPay: false,
itemChecked: false,
index: null,
};
}
functionTwo = () => {
alert('func 2');
this.setState(() => ({
parkPay: true,
}));
};
checkedItem = index => {
console.log('this is index', index);
// let itemChecked = this.state.itemChecked
if (this.state.index != index) {
this.setState(() => ({
index: index,
itemChecked: !this.state.itemChecked,
}));
}
};
addParkField = () => {
console.log('jjjjj');
console.log(' ^^ props in parking form ^^ ', this.props);
let x = 0;
this.setState(() => ({
arr: [...this.state.arr, ''],
}));
// this.addFieldSecond()
// this.props.addParkFieldSecond()
};
render() {
return (
<View>
<View
style={{flex: 1, paddingRight: calcWidth(4),paddingLeft: calcWidth(6), paddingTop: calcHeight(4),paddingBottom: calcHeight(4),
}}>
<Input
placeholder="Enter Amount"
label="Enter Amount"
labelStyle={{ fontWeight: '200', color: 'black' }}
inputContainerStyle={{
paddingRight: calcWidth(2),
paddingLeft: calcWidth(2),
paddingTop: calcHeight(1),
paddingBottom: calcHeight(1),
}}
// onChangeText={this.props.parkingAmount}
/>
<Text style={[styles.error]}>{this.state.errors.Amount}</Text>
<View
style={{ paddingLeft: calcWidth(2), paddingTop: calcHeight(4) }}>
<View style={{ paddingRight: calcWidth(70) }}>
<Switch
value={this.state.parkPay}
style={
Platform.OS === 'ios' ? styles.switchIOS : styles.switchAND
}
// onValueChange={(value) => {this.props.toggleCustomerParkingPay(value); this.functionTwo()}}
/>
</View>
<Text style={{ paddingTop: calcHeight(8) }}>Paid By Customer</Text>
</View>
</View>
<View style={{}}>
{this.state.arr.map((extra, index) => {
return (
<View
style={{
flex: 1,
paddingRight: calcWidth(4),
paddingLeft: calcWidth(20),
paddingTop: calcHeight(15),
paddingBottom: calcHeight(4),
}}
key={index}>
<Input
placeholder="Enter Amount"
label="Enter Amount"
labelStyle={{ fontWeight: '200', color: 'black' }}
inputContainerStyle={{
paddingRight: calcWidth(2),
paddingLeft: calcWidth(2),
paddingTop: calcHeight(1),
paddingBottom: calcHeight(1),
}}
// onChangeText={this.handleAmount}
// onChangeText={this.props.parkingAmount}
/>
<Text style={[styles.error]}>{this.state.errors.Amount}</Text>
<View style={{ paddingTop: calcHeight(4) }}>
<View style={{ paddingRight: calcWidth(70) }}>
<Switch
value={this.state.parkPay}
style={
Platform.OS === 'ios'
? styles.switchIOS
: styles.switchAND
}
// onValueChange={(value) => {this.props.toggleCustomerParkingPay(value);}}
/>
</View>
<Text style={{ paddingTop: calcHeight(8) }}>
Paid By Customer
</Text>
</View>
</View>
);
})}
<View>
<View
style={{ paddingLeft: calcWidth(60), paddingTop: calcHeight(2) }}>
<TouchableOpacity
style={[styles.cardCirclePassenger]}
onPress={this.addParkField}>
<View
style={{
justifyContent: 'center',
alignItems: 'center',
paddingTop: calcHeight(2.2),
}}>
{/* <Image
style={{width: 24, height: 24}}
source={require('../../images/Group424.png')}
/> */}
<Text>Add</Text>
</View>
</TouchableOpacity>
</View>
</View>
</View>
</View>
);
}
}
const styles = StyleSheet.create({
cardCirclePassenger: {
backgroundColor: '#31588A',
marginBottom: 10,
marginLeft: '5%',
width: 60,
height: 60,
borderRadius: 60 / 2,
borderColor: 'white',
shadowOpacity: 0.2,
shadowRadius: 1,
shadowOffset: {
width: 3,
height: 3,
},
borderWidth: 1,
},
switchIOS: {
transform: [
{ scaleX: moderateScale(0.7, 0.2) },
{ scaleY: moderateScale(0.7, 0.2) },
],
},
switchAND: {
transform: [
{ scaleX: moderateScale(1, 0.2) },
{ scaleY: moderateScale(1, 0.2) },
],
},
});
export default ErrorScreen;
i worked around a little bit and found the below way to generate dynamic checboxes along with separate state values. hope this helps someone.
The below code creates dynamic key-value pairs in state. if you console.log the state in your render you'll see (check0:true check1:true check2: false ....) .
<Switch
value={this.state[`check${key}`]}
onValueChange={value => this.setState({ [`check${key}`]: value })}
/>

Invariant Violation: Element type is invalid: expected a string or a class/function but got: undefined.

Developers,
HELP. I'm getting this error with the below, I've been pouring over it trying to find the issue but just can't see it! What's wrong here? It seems to be stemming from the code from 146 to 236.
Invariant Violation: Element type is invalid: expected a string (for built-in >components) or a class/function (for composite components) but got: >undefined. You likely forgot to export your component from the file it's >defined in, or you might have mixed up default and named imports.
import React, { Component } from "react";
import PropTypes from "prop-types";
import {
View,
Text,
StyleSheet,
KeyboardAvoidingView,
LayoutAnimation,
UIManager,
Dimensions
} from "react-native";
import { Button, Input } from "react-native-elements";
import Icon from "react-native-vector-icons/FontAwesome";
import SimpleIcon from "react-native-vector-icons/SimpleLineIcons";
const SCREEN_WIDTH = Dimensions.get("window").width;
// Enable LayoutAnimation on Android
UIManager.setLayoutAnimationEnabledExperimental &&
UIManager.setLayoutAnimationEnabledExperimental(true);
const TabSelector = ({ selected }) => {
return (
<View style={styles.selectorContainer}>
<View style={selected && styles.selected} />
</View>
);
};
TabSelector.propTypes = {
selected: PropTypes.bool.isRequired
};
export default class AuthScreen extends Component {
constructor(props) {
super(props);
this.state = {
email: "",
password: "",
selectedCategory: 0,
isLoading: false,
isPasswordValid: true,
isConfirmationValid: true
};
this.selectCategory = this.selectCategory.bind(this);
this.login = this.login.bind(this);
this.signUp = this.signUp.bind(this);
}
selectCategory(selectedCategory) {
LayoutAnimation.easeInEaseOut();
this.setState({
selectedCategory,
isLoading: false
});
}
login() {
const { password } = this.state;
this.setState({ isLoading: true });
// Simulate an API call
setTimeout(() => {
LayoutAnimation.easeInEaseOut();
this.setState({
isLoading: false,
isPasswordValid: password.length >= 8 || this.passwordInput.shake()
});
}, 1500);
}
signUp() {
const { password, passwordConfirmation } = this.state;
this.setState({ isLoading: true });
// Simulate an API call
setTimeout(() => {
LayoutAnimation.easeInEaseOut();
this.setState({
isLoading: false,
isPasswordValid: password.length >= 8 || this.passwordInput.shake(),
isConfirmationValid:
password == passwordConfirmation || this.confirmationInput.shake()
});
}, 1500);
}
render() {
const {
selectedCategory,
isLoading,
isPasswordValid,
isConfirmationValid,
email,
password,
passwordConfirmation
} = this.state;
const isLoginPage = selectedCategory === 0;
const isSignUpPage = selectedCategory === 1;
return (
<View style={styles.container}>
<KeyboardAvoidingView
contentContainerStyle={styles.loginContainer}
behavior="position"
>
<View style={styles.titleContainer}>
<View style={{ flexDirection: "row" }}>
<Text style={styles.titleText}>BEAUX</Text>
</View>
<View style={{ marginTop: -10, marginLeft: 10 }}>
<Text style={styles.titleText}>VOYAGES</Text>
</View>
</View>
<View style={{ flexDirection: "row" }}>
<Button
disabled={isLoading}
clear
activeOpacity={0.7}
onPress={() => this.selectCategory(0)}
containerStyle={{ flex: 1 }}
titleStyle={[
styles.categoryText,
isLoginPage && styles.selectedCategoryText
]}
title={"Login"}
/>
<Button
disabled={isLoading}
clear
activeOpacity={0.7}
onPress={() => this.selectCategory(1)}
containerStyle={{ flex: 1 }}
titleStyle={[
styles.categoryText,
isSignUpPage && styles.selectedCategoryText
]}
title={"Sign up"}
/>
</View>
<View style={styles.rowSelector}>
<TabSelector selected={isLoginPage} />
<TabSelector selected={isSignUpPage} />
</View>
{/* //!ISSUE LIES HERE */}
<View style={styles.formContainer}>
<Input
leftIcon={
<Icon
name="envelope-o"
color="rgba(0, 0, 0, 0.38)"
size={25}
style={{ backgroundColor: "transparent" }}
/>
}
value={email}
keyboardAppearance="light"
autoFocus={false}
autoCapitalize="none"
autoCorrect={false}
keyboardType="email-address"
returnKeyType="next"
inputStyle={{ marginLeft: 10 }}
placeholder={"Email"}
containerStyle={{
borderBottomColor: "rgba(0, 0, 0, 0.38)"
}}
ref={input => (this.emailInput = input)}
onSubmitEditing={() => this.passwordInput.focus()}
onChangeText={email => this.setState({ email })}
/>
<Input
leftIcon={
<SimpleIcon
name="lock"
color="rgba(0, 0, 0, 0.38)"
size={25}
style={{ backgroundColor: "transparent" }}
/>
}
value={password}
keyboardAppearance="light"
autoCapitalize="none"
autoCorrect={false}
secureTextEntry={true}
returnKeyType={isSignUpPage ? "next" : "done"}
blurOnSubmit={true}
containerStyle={{
marginTop: 16,
borderBottomColor: "rgba(0, 0, 0, 0.38)"
}}
inputStyle={{ marginLeft: 10 }}
placeholder={"Password"}
ref={input => (this.passwordInput = input)}
onSubmitEditing={() =>
isSignUpPage ? this.confirmationInput.focus() : this.login()
}
onChangeText={password => this.setState({ password })}
errorMessage={
isPasswordValid ? null : "Please enter at least 8 characters"
}
/>
{isSignUpPage && (
<Input
icon={
<SimpleIcon
name="lock"
color="rgba(0, 0, 0, 0.38)"
size={25}
style={{ backgroundColor: "transparent" }}
/>
}
value={passwordConfirmation}
secureTextEntry={true}
keyboardAppearance="light"
autoCapitalize="none"
autoCorrect={false}
keyboardType="default"
returnKeyType={"done"}
blurOnSubmit={true}
containerStyle={{
marginTop: 16,
borderBottomColor: "rgba(0, 0, 0, 0.38)"
}}
inputStyle={{ marginLeft: 10 }}
placeholder={"Confirm password"}
ref={input => (this.confirmationInput = input)}
onSubmitEditing={this.signUp}
onChangeText={passwordConfirmation =>
this.setState({ passwordConfirmation })
}
errorMessage={
isConfirmationValid ? null : "Please enter the same password"
}
/>
)}
{/* //!ISSUE ENDS HERE */}
<Button
buttonStyle={styles.loginButton}
containerStyle={{ marginTop: 32, flex: 0 }}
activeOpacity={0.8}
title={isLoginPage ? "LOGIN" : "SIGN UP"}
onPress={isLoginPage ? this.login : this.signUp}
titleStyle={styles.loginTextButton}
loading={isLoading}
disabled={isLoading}
/>
</View>
</KeyboardAvoidingView>
<View style={styles.helpContainer}>
<Button
title={"Need help ?"}
titleStyle={{ color: "red" }}
buttonStyle={{ backgroundColor: "transparent" }}
underlayColor="transparent"
onPress={() => console.log("Account created")}
/>
</View>
</View>
);
}
}
const styles = StyleSheet.create({
container: {
backgroundColor: "#034d84",
flex: 1
},
rowSelector: {
height: 20,
flexDirection: "row",
alignItems: "center"
},
selectorContainer: {
flex: 1,
alignItems: "center"
},
selected: {
position: "absolute",
borderRadius: 50,
height: 0,
width: 0,
top: -5,
borderRightWidth: 70,
borderBottomWidth: 70,
borderColor: "white",
backgroundColor: "white"
},
loginContainer: {
alignItems: "center",
justifyContent: "center"
},
loginTextButton: {
fontSize: 16,
color: "white",
fontWeight: "bold"
},
loginButton: {
backgroundColor: "rgba(232, 147, 142, 1)",
borderRadius: 10,
height: 50,
width: 200
},
titleContainer: {
height: 150,
backgroundColor: "transparent",
justifyContent: "center"
},
formContainer: {
backgroundColor: "white",
width: SCREEN_WIDTH - 30,
borderRadius: 10,
paddingTop: 32,
paddingBottom: 32,
alignItems: "center"
},
loginText: {
fontSize: 16,
fontWeight: "bold",
color: "white"
},
categoryText: {
textAlign: "center",
color: "white",
fontSize: 24,
fontFamily: "light",
backgroundColor: "transparent",
opacity: 0.54
},
selectedCategoryText: {
opacity: 1
},
titleText: {
color: "white",
fontSize: 30,
fontFamily: "regular"
},
helpContainer: {
height: 64,
alignItems: "center",
justifyContent: "center"
}
});
Based on your input that you are on react-native-elements version 0.19.1, it seems the Input component isn't available (see docs). Only the v1.0.0 beta versions support Input as component.

React native and scrollView

I used the other question to fix it my problem but I don't understand where I mistake.
Hi,
I have a problem with react native scroll view, it scroll but when I release it comes back to the top, how can I fix it?
This is the render:
render() {
const { centerEverything, skeleton, container, textContainer, contentContainer, buttonContainer,
propHeight, propWidth, halfPropWidth, titleContainer, descContainer, title, artworkTitle,
desc, buttonStyle, artworkContainer, artwork } = styles;
let CheckIndex = i => {
if((i % 2) == 0) {
return styles.gray
}
};
let rows = this.state.rows.map((r, i) => {
return <View key={ i } style={{ flexDirection: 'row' }}>
<Input
propWidth={halfPropWidth}
placeholder="Ingrediente"
onChangeText={this.changeIngrediente.bind(this, 'quantita', i)}
value={this.state.date} />
<Input
propWidth={halfPropWidth}
placeholder="Quantita"
onChangeText={this.changeIngrediente.bind(this, 'ingrediente', i)}
value={this.state.time} />
</View>
});
return (
<TouchableWithoutFeedback onPress={()=> dismissKeyboard()}>
<View style={[centerEverything, container]}>
<View style={[centerEverything, textContainer]}>
<View style={titleContainer}>
<Text style={[title]}>Add Event</Text>
</View>
<View style={descContainer}>
<Text style={[desc]}>Submit your event and we will process it in a bit ⚡️</Text>
</View>
</View>
<ScrollView style={[contentContainer, propWidth]}>
<View style={[centerEverything, artworkContainer]}>
<TouchableOpacity onPress={this.selectPhotoTapped.bind(this)}>
<View style={[centerEverything, {height: 100, width: deviceWidth*0.8}]}>
{
(() => {
switch (this.state.artworkUrl) {
case null:
return (
<View>
<Text style={[artworkTitle]}>Upload event artwork</Text>
<Text style={[desc]}>Preferably 640x480</Text>
</View>
);
case '':
return <Spinner size="small"/>
default:
return(
<Image style={artwork} source={{uri: this.state.artworkUrl}} />
)
}
})()
}
</View>
</TouchableOpacity>
</View>
<Input
propWidth={propWidth}
placeholder="Event Title"
onChangeText={(title) => this.setState({ title })}
value={this.state.title} />
<View style={{ flexDirection: 'row' }}>
<Input
propWidth={halfPropWidth}
placeholder="Date"
onChangeText={(date) => this.setState({ date })}
value={this.state.date} />
<Input
propWidth={halfPropWidth}
placeholder="Time"
onChangeText={(time) => this.setState({ time })}
value={this.state.time} />
</View>
<View>
{ rows }
<TouchableHighlight
onPress={ this._addRow.bind(this) }
style={styles.button}>
<Text>Aggiungi ingrediente</Text>
</TouchableHighlight>
</View>
<View style={{ flexDirection: 'row' }}>
<Input
propWidth={halfPropWidth}
placeholder="Organizer"
onChangeText={(organizer) => this.setState({ organizer })}
value={this.state.organizer} />
<Input
propWidth={halfPropWidth}
placeholder="Cost"
onChangeText={(cost) => this.setState({ cost })}
value={this.state.cost} />
</View>
<Input
propWidth={[propHeight, propWidth]}
placeholder="Address"
multiline={true}
onChangeText={(address) => this.setState({ address })}
value={this.state.address} />
<Input
propWidth={[propHeight, propWidth]}
placeholder="Note"
multiline={true}
onChangeText={(note) => this.setState({ note })}
value={this.state.note} />
</ScrollView>
<View style={[buttonContainer]}>
<ButtonComponent
style={buttonStyle}
type='primary'
shape='rectangle'
buttonState={this.state.buttonState}
states={this.buttonStates}
/>
</View>
</View>
</TouchableWithoutFeedback>
)
}
this is the style:
const styles = {
centerEverything: {
justifyContent: 'center',
alignItems: 'center'
},
skeleton: {
borderWidth: 1,
borderColor: 'red'
},
container: {
flex: 1,
flexDirection: 'column',
backgroundColor: '#F5F6F7',
marginTop: 44
},
textContainer: {
flex: 2,
marginTop: 20
},
propHeight: {
height: 80
},
propWidth: {
width: deviceWidth*0.8
},
halfPropWidth: {
width: deviceWidth*0.4
},
contentContainer: {
flex: 1,
width: deviceWidth,
height: deviceHeight-200
},
buttonContainer: {
width: deviceWidth,
alignItems: 'center',
backgroundColor: 'transparent',
position: 'absolute',
bottom: 20
},
button: {
alignItems: 'center',
justifyContent: 'center',
height:55,
backgroundColor: '#ededed',
marginBottom:10
},
titleContainer: {
width: deviceWidth*0.8,
},
descContainer: {
width: deviceWidth*0.6,
},
title: {
fontSize: 22,
fontFamily: 'Helvetica Neue',
fontWeight: '400',
textAlign: 'center'
},
artworkTitle: {
fontSize: 18
},
desc: {
color: 'grey',
fontSize: 15,
fontFamily: 'Helvetica Neue',
fontWeight: '300',
textAlign: 'center'
},
buttonStyle: {
height: 40,
width: deviceWidth*0.7,
borderRadius: 20,
margin: 3
},
artworkContainer: {
borderColor: '#9B9B9B',
borderRadius: 3,
borderWidth: 1 / PixelRatio.get(),
marginBottom: 5,
width: deviceWidth*0.8,
height: 100
},
artwork: {
width: deviceWidth*0.8,
height: 100
},
listViewContainer: {
justifyContent: 'center',
alignItems: 'center',
flexDirection: 'row',
flexWrap: 'wrap',
},
}
I set minheight property of the scroll and it seems to work.