Search code examples
react-nativescrollview

React Native Scroll View bounces back to top


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>


Solution

  • 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: "[email protected]",
          // 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>
        );
      }
    }