【问题标题】:PanResponder to change Card Y value and issue of moving out of screenPanResponder 更改 Card Y 值和移出屏幕的问题
【发布时间】:2020-07-11 15:09:03
【问题描述】:

我是 react-native 动画 API 和 PanResponder API 的新手。
我想创建谷歌地图克隆 UI 和卡片动画,在结果后显示。
我想创建卡片,当用户向上滑动时,卡片到达屏幕顶部,当用户向下滑动时,卡片应该调整到原始位置。
Demo of Google Maps that i want to achieve


我已经为此实现了一些代码,但我面临的问题是卡片在顶部方向上移出屏幕(卡片到达顶部位置后向上滑动)。有时,向下滑动会起作用,但并非总是如此。


My demo

Expo Snack Link


App.js

import React, { useEffect, useState } from "react";
import {
  SafeAreaView,
  View,
  Text,
  Dimensions,
  PanResponder,
  Animated,
} from "react-native";
import { Searchbar, FAB } from "react-native-paper";
import MapView from "react-native-maps";
import * as Location from "expo-location";


const SCREEN_HEIGHT = Dimensions.get("window").height;
const SCREEN_WIDTH = Dimensions.get("window").width;

const App = () => {
  

  const [latitute, setLatitute] = useState(0);
  const [longitute, setLongitute] = useState(0);
  const [isLoading, setIsLoading] = useState(true);


  const pan = useState(
    new Animated.ValueXY({ x: 0, y: SCREEN_HEIGHT - 200 })
  )[0];


  const panResponder = useState(
    PanResponder.create({
      onMoveShouldSetPanResponder: () => true,
      onPanResponderGrant: () => {
        pan.extractOffset();
        return true;
      },
      onPanResponderMove: (e, gestureState) => {
        pan.setValue({ x: 0, y: gestureState.dy });
      },
      onPanResponderRelease: (e, gestureState) => {
        
        if (gestureState.moveY > SCREEN_HEIGHT - 200) {
          Animated.spring(pan.y, {
            toValue: 0,
            tension: 1,
            useNativeDriver: true,
          }).start();
        } else if (gestureState.moveY < 200) {
          Animated.spring(pan.y, {
            toValue: 0,
            tension: 1,
            useNativeDriver: true,
          }).start();
        } else if (gestureState.dy < 0) {
          Animated.spring(pan.y, {
            toValue: -SCREEN_HEIGHT + 200,
            tension: 1,
            useNativeDriver: true,
          }).start();
        } else if (gestureState.dy > 0) {
          Animated.spring(pan.y, {
            toValue: SCREEN_HEIGHT - 200,
            tension: 1,
            useNativeDriver: true,
          }).start();
        }
      },
    })
  )[0];

  const animatedHeight = {
    transform: pan.getTranslateTransform(),
  };

  useEffect(() => {
    (async () => {
      let { status } = await Location.requestPermissionsAsync();

      let location = await Location.getCurrentPositionAsync({});
      console.log(location);
      setLatitute(location.coords.latitude);
      setLongitute(location.coords.longitude);
      setIsLoading(false);
    })();
  }, []);

  return (
    <SafeAreaView
      style={{
        display: "flex",
        flex: 1,
      }}
    >
      {!isLoading && (
        <View>
          <MapView
            style={{ width: SCREEN_WIDTH, height: SCREEN_HEIGHT }}
            showsUserLocation
            initialRegion={{
              latitude: latitute,
              longitude: longitute,
              latitudeDelta: 0.01,
              longitudeDelta: 0.01,
            }}
          />

          <Searchbar
            placeholder="Search"
            style={{
              position: "absolute",
              top: 10,
              margin: 10,
            }}
            
            icon="menu"
            onIconPress={() => {}}
          />

          <FAB
            style={{
              position: "absolute",
              top: SCREEN_HEIGHT * 0.8,
              left: SCREEN_WIDTH * 0.8,
            }}
            icon="plus"
            onPress={() => console.log("Pressed")}
          />

          <Animated.View
            style={[
              animatedHeight,
              {
                position: "absolute",
                right: 0,
                left: 0,
                width: SCREEN_WIDTH,
                height: SCREEN_HEIGHT,
                backgroundColor: "#0af",
                borderTopLeftRadius: 25,
                borderTopRightRadius: 25,
                zIndex: 10,
              },
            ]}
            {...panResponder.panHandlers}
          >
            <View>
              <Text>Hi</Text>
            </View>
          </Animated.View>
        </View>
      )}
    </SafeAreaView>
  );
};

export default App;


【问题讨论】:

    标签: reactjs react-native animation expo panresponder


    【解决方案1】:

    如果你想制作底页,那么你可以使用react-native-bottomsheet-reanimated

    yarn add react-native-bottomsheet-reanimated
    
    import React, { useEffect, useState } from "react";
    import {
      SafeAreaView,
      View,
      Text,
      Dimensions,
      PanResponder,
      Animated,
      StyleSheet
    } from "react-native";
    import { Searchbar, FAB } from "react-native-paper";
    import MapView from "react-native-maps";
    import * as Location from "expo-location";
    import BottomSheet from "react-native-bottomsheet-reanimated";
    
    
    
    const SCREEN_HEIGHT = Dimensions.get("window").height;
    const SCREEN_WIDTH = Dimensions.get("window").width;
    
    const App = () => {
      
    
      const [latitute, setLatitute] = useState(0);
      const [longitute, setLongitute] = useState(0);
      const [isLoading, setIsLoading] = useState(true);
    
    
      const pan = useState(
        new Animated.ValueXY({ x: 0, y: SCREEN_HEIGHT - 200 })
      )[0];
    
      useEffect(() => {
        (async () => {
          let { status } = await Location.requestPermissionsAsync();
    
          let location = await Location.getCurrentPositionAsync({});
          console.log(location);
          setLatitute(location.coords.latitude);
          setLongitute(location.coords.longitude);
          setIsLoading(false);
        })();
      }, []);
    
      return (
        <SafeAreaView
          style={{
            display: "flex",
            flex: 1,
          }}
        >
          {!isLoading && (
            <View>
              <MapView
                style={{ width: SCREEN_WIDTH, height: SCREEN_HEIGHT }}
                showsUserLocation
                initialRegion={{
                  latitude: latitute,
                  longitude: longitute,
                  latitudeDelta: 0.01,
                  longitudeDelta: 0.01,
                }}
              />
    
              <Searchbar
                placeholder="Search"
                style={{
                  position: "absolute",
                  top: 10,
                  margin: 10,
                }}
                
                icon="menu"
                onIconPress={() => {}}
              />
    
              <FAB
                style={{
                  position: "absolute",
                  top: SCREEN_HEIGHT * 0.8,
                  left: SCREEN_WIDTH * 0.8,
                }}
                icon="plus"
                onPress={() => console.log("Pressed")}
              />
    
              <BottomSheet
              bottomSheerColor="#FFFFFF"
              initialPosition={"30%"}  //200, 300
              snapPoints={["30%","100%"]}
              isBackDropDismisByPress={true}
              isRoundBorderWithTipHeader={true}
              containerStyle={{backgroundColor:"#0af"}}
              header={
                <View>
                  <Text style={styles.text}>Header</Text>
                </View>
              }
              body={
                <View style={styles.body}>
                  <Text>Hi</Text>
                </View>
              }
            />
    
            </View>
          )}
        </SafeAreaView>
      );
    };
    
    
    export default App;
    
    const styles = StyleSheet.create({
      body:{
        justifyContent:"center",
        alignItems:"center"
      },
      text:{
        fontSize:20,
        fontWeight:"bold"
      }
    });
    

    【讨论】:

    • 我正在使用 PanResponder API 寻找答案。如果没有更好的答案,我会接受你的答案。
    • 有什么方法可以让这张底片变成可滚动的,而不是 100% 的高度??如果您知道任何使其可滚动的内容,请回复?
    • @FerinPatel 目前这个包不支持可滚动的底页,但我会尽快添加这个支持并让你知道
    • @MuhammadNuman 我遇到了很多 React 原生地图。你的答案是最好的之一。我有地理围栏的问题。我在 stack-overflow 社区问过。你能帮我解决这个问题吗:stackoverflow.com/questions/64816066/…
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-19
    • 1970-01-01
    • 2016-08-13
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多