0

我正在尝试为我的底页创建这个动画,所以最初当我的主屏幕加载时,底页会从下方弹出一个弹簧动画,然后当用户向上滑动时,底页也会向上滑动一个弹簧动画,然后再一次如果用户向下滑动底页,则返回其原始位置并带有弹簧动画。

我面临的唯一问题是,在初始弹出弹簧动画发生后我进行的第一次向上滑动,向上滑动的动画不会顺利进行,并且它会在瞬间捕捉到上部位置而没有显示任何像动画一样的春天

这是我的 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,
  },
});

请向我提出一些关于如何实现这一目标的想法,或任何其他可用于实现这一目标的方法。

4

1 回答 1

0

所以,显然,我在某个地方发现了弹簧动画,toValue:1实际上并没有达到 1,它略微超过 1。所以这就是为什么我的动画表现得像我猜的那样。

对此的解决方案是,我只是将我toValue的 foranimateBottomSheetUp和更改为animateBottomSheetDown更高的值,即toValue:2for 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();
  }

&现在看起来像这样openBottomSheetHandlercloseBottomSheetHandler

  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],
    });
  }

如果有人遇到同样的问题,我会发布这个答案,
虽然我已经解决了这个问题,但我仍然觉得必须有更好的方法来做到这一点,如果有人有更好的方法,请回答。:-)

于 2020-07-01T11:03:03.023 回答