Анимация BottomSheet в react-native впервые не работает должным образом

Я пытаюсь создать эту анимацию для своего нижнего листа, поэтому сначала, когда загружается мой домашний экран, нижний лист всплывает снизу с пружинной анимацией, а затем, когда пользователь проводит пальцем вверх, нижний лист также прокручивается вверх с пружинной анимацией, и снова если пользователь проводит пальцем вниз, нижний лист возвращается в исходное положение с анимацией пружины.

Единственная проблема, с которой я столкнулся, заключается в том, что первое смахивание вверх, которое я делаю после того, как происходит начальная анимация всплывающей пружины, анимация для смахивания вверх происходит не плавно, и она привязывается к верхнему положению всего за мгновенно, без показа пружинной анимации

Вот мой код для моего BottomSheet.

import * as React from "react";
import { SCREEN_HEIGHT } from "../../assets/constants";
import { StyleSheet, Animated, TextInput, View } from "react-native";
import { PanGestureHandler } from "react-native-gesture-handler";
import { Easing } from "react-native-reanimated";
import BottomSheetStack from "./BottomSheetStack";

export default class BottomSheet extends React.Component {
  constructor(props) {
    super(props);
    this.BottomSheet = new Animated.Value(0);
    this.state = {
      isOpen: false,
      isLoading: false,
      isPanChanged: false,
    };
  }

  componentDidMount() {
    setTimeout(() => this.animateTranslate(), 1000);
  }

  animateTranslate() {
    Animated.spring(this.BottomSheet, {
      toValue: 1,
      duration: 500,
      useNativeDriver: true,
      easing: Easing.ease,
    }).start();
  }

  translateDrawer() {
    return this.BottomSheet.interpolate({
      inputRange: [0, 1],
      outputRange: [SCREEN_HEIGHT, SCREEN_HEIGHT / 1.48],
    });
  }

  animateBottomSheetUp() {
    this.BottomSheet.setValue(0);
    Animated.spring(this.BottomSheet, {
      toValue: 1,
      duration: 100,
      useNativeDriver: true,
      easing: Easing.ease,
    }).start();
  }
  animateBottomSheetDown() {
    this.BottomSheet.setValue(0);
    Animated.spring(this.BottomSheet, {
      toValue: 1,
      duration: 100,
      useNativeDriver: true,
      easing: Easing.ease,
    }).start();
  }

  handlePanGesture(props) {
    this.setState({ isLoading: true });
    if (!this.state.isPanChanged) {
      this.setState({ isPanChanged: true });
    }
    if (!this.state.isOpen && props.nativeEvent.translationY > 0) {
      this.animateBottomSheetUp();
      this.setState({ isOpen: true });
    } else if (this.state.isOpen && props.nativeEvent.translationY < 0) {
      this.animateBottomSheetDown();
      this.setState({ isOpen: false });
    }
  }

  openBottomSheetHandler() {
    return this.BottomSheet.interpolate({
      inputRange: [0, 1],
      outputRange: [SCREEN_HEIGHT / 1.48, SCREEN_HEIGHT / 2.1],
    });
  }
  closeBottomSheetHandler() {
    return this.BottomSheet.interpolate({
      inputRange: [0, 1],
      outputRange: [SCREEN_HEIGHT / 2.1, SCREEN_HEIGHT / 1.48],
    });
  }

  render() {
    return (
      <PanGestureHandler
        onGestureEvent={(props) => this.handlePanGesture(props)}
      >
        <Animated.View
          style={{
            ...StyleSheet.absoluteFill,
            height: SCREEN_HEIGHT - SCREEN_HEIGHT / 2.2,
            backgroundColor: "#ffffff",
            elevation: 10,
            transform: [
              {
                translateY: !this.state.isLoading
                  ? this.translateDrawer()
                  : !this.state.isOpen && this.state.isPanChanged
                  ? this.openBottomSheetHandler()
                  : this.closeBottomSheetHandler(),
              },
            ],
            alignItems: "center",
            borderRadius: 15,
          }}
        >
          <View style={styles.bottomSheetLine} />
          <TextInput
            value={this.state.name}
            style={styles.searchBox}
            placeholder="Search"
            placeholderTextColor="#5DB075"
          />
          <BottomSheetStack {...this.props.navigation} />
        </Animated.View>
      </PanGestureHandler>
    );
  }
}

const styles = StyleSheet.create({
  searchBox: {
    height: 45,
    width: `85%`,
    backgroundColor: "#ffffff",
    borderRadius: 10,
    color: "#5DB075",
    paddingLeft: 20,
    fontSize: 14,
    letterSpacing: 0.5,
    top: 20,
    fontFamily: "regular",
    borderColor: "#5DB075",
    borderWidth: 1,
  },
  bottomSheetLine: {
    height: 5,
    backgroundColor: "#5DB075",
    width: 70,
    borderRadius: 5,
    top: 5,
  },
});

Пожалуйста, предложите мне какую-нибудь идею о том, как я могу добиться этого, или любой другой метод, который можно использовать для достижения этого.


person Rahul Halder    schedule 29.06.2020    source источник


Ответы (1)


Итак, по-видимому, где-то я нашел эту весеннюю анимацию, toValue:1 на самом деле не достигает 1, а слегка пересекает 1. Вот почему моя анимация вела себя так, я думаю.

Решением этого было то, что я просто изменил свои toValue на animateBottomSheetUp и animateBottomSheetDown, перешел на более высокое значение, то есть toValue:2 на animateBottomSheetUp.

Мои изменения в моем коде очень незначительны, это выглядит так,

также я удалил все this.BottomSheet.setValue(/*somevalue*/) из своего кода.

для animateBottomSheetUp:

  animateBottomSheetUp() {
    Animated.spring(this.BottomSheet, {
      toValue: 2,   // made this change from 1 to 2
      duration: 100,
      useNativeDriver: true,
      easing: Easing.ease,
    }).start();
  }

и openBottomSheetHandler и closeBottomSheetHandler теперь выглядят так,

  openBottomSheetHandler() {
    return this.BottomSheet.interpolate({
      inputRange: [1, 2],
      outputRange: [SCREEN_HEIGHT / 1.48, SCREEN_HEIGHT / 2.1],
    });
  }
  closeBottomSheetHandler() {
    return this.BottomSheet.interpolate({
      inputRange: [1, 2],
      outputRange: [SCREEN_HEIGHT / 1.48, SCREEN_HEIGHT / 2.1],
    });
  }

Я публикую этот ответ, если кто-то сталкивается с той же проблемой,
Хотя я работал над этой проблемой, но я все еще чувствую, что должен быть лучший способ сделать это, если у кого-то есть лучший способ, пожалуйста, ответьте. :-)

person Rahul Halder    schedule 01.07.2020