New plant form
If you fancy a challenge, look at the screenshots at the end and try to build this UI yourself first.
Add a new color to our theme file (we'll use it for the input border):
Update theme.ts
@@ -4,4 +4,5 @@ export const theme = {
colorAppleGreen: "#a0d36c",
colorLimeGreen: "#d0e57e",
colorWhite: "#fff",
+ colorLightGrey: "#eee",
};
Now update the modal screen to add the form for creating a new plant:
Update app/new.tsx
import {
Text,
StyleSheet,
TextInput,
Alert,
ScrollView,
View,
} from "react-native";
import { theme } from "@/theme";
import { PlantlyButton } from "@/components/PlantlyButton";
import { useState } from "react";
import { PlantlyImage } from "@/components/PlantlyImage";
export default function NewScreen() {
const [name, setName] = useState<string>();
const [days, setDays] = useState<string>();
const handleSubmit = () => {
if (!name) {
return Alert.alert("Validation Error", "Give your plant a name");
}
if (!days) {
return Alert.alert(
"Validation Error",
`How often does ${name} need to be watered?`,
);
}
if (Number.isNaN(Number(days))) {
return Alert.alert(
"Validation Error",
"Watering frequency must be a be a number",
);
}
console.log("Adding plant", name, days);
};
return (
<ScrollView
style={styles.container}
contentContainerStyle={styles.contentContainer}
keyboardShouldPersistTaps="handled"
>
<View style={styles.centered}>
<PlantlyImage />
</View>
<Text style={styles.label}>Name</Text>
<TextInput
value={name}
onChangeText={setName}
style={styles.input}
placeholder="E.g. Casper the Cactus"
autoCapitalize="words"
/>
<Text style={styles.label}>Watering Frequency (every x days)</Text>
<TextInput
value={days}
onChangeText={setDays}
style={styles.input}
placeholder="E.g. 6"
keyboardType="number-pad"
/>
<PlantlyButton title="Add plant" onPress={handleSubmit} />
</ScrollView>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: theme.colorWhite,
},
contentContainer: {
paddingTop: 24,
paddingHorizontal: 24,
paddingBottom: 100,
},
input: {
borderWidth: 2,
borderColor: theme.colorLightGrey,
padding: 12,
borderRadius: 6,
marginBottom: 24,
fontSize: 18,
},
label: {
fontSize: 18,
marginBottom: 8,
},
centered: {
alignItems: "center",
},
});
If you're done editing and tap the "add plant" button, by default you'll have to press it twice: once to hide the keyboard and once to actually press the button.
The keyboardShouldPersistTaps prop on the ScrollView
lets us configure how we handle taps. In our case, adding keyboardShouldPersistTaps="handled"
makes it so keyboard will not dismiss automatically when the tap was handled by children of the scroll view (i.e. our "add plant" button).
And add textAlign: "center"
to the button text to ensure it gets rendered in the center for full-width buttons:
Update components/PlantlyButton.tsx
@@ -33,6 +33,7 @@ const styles = StyleSheet.create({
color: "white",
fontSize: 18,
fontWeight: "bold",
+ textAlign: "center",
},
button: {
paddingHorizontal: 18,
For large forms, you may want to use KeyboardAvoidingView or KeyboardAwareScrollView to ensure your inputs are always visible.
Instructions for setting up KeyboardAvoidingView
First, install the package:
npx expo install react-native-keyboard-aware-scroll-view
Then, replace the ScrollView
with the KeyboardAwareScrollView
.
@@ -1,15 +1,9 @@
-import {
- Text,
- StyleSheet,
- TextInput,
- Alert,
- ScrollView,
- View,
-} from "react-native";
+import { Text, StyleSheet, TextInput, Alert, View } from "react-native";
import { theme } from "@/theme";
import { PlantlyButton } from "@/components/PlantlyButton";
import { useState } from "react";
import { PlantlyImage } from "@/components/PlantlyImage";
+import { KeyboardAwareScrollView } from "react-native-keyboard-aware-scroll-view";
export default function NewScreen() {
const [name, setName] = useState<string>();
@@ -36,7 +30,7 @@ export default function NewScreen() {
};
return (
- <ScrollView
+ <KeyboardAwareScrollView
style={styles.container}
contentContainerStyle={styles.contentContainer}
keyboardShouldPersistTaps="handled"
@@ -61,7 +55,7 @@ export default function NewScreen() {
keyboardType="number-pad"
/>
<PlantlyButton title="Add plant" onPress={handleSubmit} />
- </ScrollView>
+ </KeyboardAwareScrollView>
);
}
Checkpoint
Android | iOS |
---|---|
![]() | ![]() |