React Native 如何在滑动时禁用视图滚动?

lo8azlld  于 2023-11-21  发布在  React
关注(0)|答案(1)|浏览(254)

我在我的React Native项目中使用了react-native-swipe-verify包,但是很难将它一直滑动到最后。我认为这是因为在滑动时没有禁用滚动,这就是为什么我问是否有一种方法可以在滑动时禁用滚动?
沿着下列路线的东西:

if(swiping) {
    scrollEnabled: false;
}

字符串
或者更具体地针对检测滑动何时开始和结束的东西会更好。沿着以下路线的东西:

if(swipeStarted) {
   scrollEnabled: false;
} elseif(swipeEnded) {
   scrollEnabled: true;
}


如果这些例子都不可能,那么如果我在包围滑动验证的视图上使用onPress,是否可以禁用滚动?然后在触摸特定视图之外时再次启用滚动?
我希望有人能明白我的意思。提前感谢你的时间。

edqdpe6u

edqdpe6u1#

你可以使用标准的ScrollView组件和你自己的CustomSwitch组件(通过Animated.View)。

// CustomSwitch.js
import React, { useState } from "react";
import {
  StyleSheet,
  View,
  PanResponder,
  Animated,
  NativeModules,
  Text,
} from "react-native";

import LinearGradient from "react-native-linear-gradient";

const { UIManager } = NativeModules;
UIManager.setLayoutAnimationEnabledExperimental &&
  UIManager.setLayoutAnimationEnabledExperimental(true);

const SIZE_THUMB = 50;

const Styles = ({
  WIDTH_SWIPE,
}) =>
  StyleSheet.create({
    swipeContainer: {
      width: WIDTH_SWIPE,
      height: 50,
      borderRadius: 25,
      justifyContent: "center",
      alignItems: "flex-start",
      position: "relative",
      backgroundColor: "#55544e",
    },
    swipeFillContainer: {
      position: 'absolute',
      width: 100,
      height: "100%",
      borderRadius: 25,
      justifyContent: "center",
      alignItems: "flex-start",
      backgroundColor: "#55544e",
    },
    swipePan: {
      width: 50,
      height: 50,
      borderRadius: 25,
      backgroundColor: "#F9DA4C",
    },
    swipeText: {
      position: "absolute",
      color: "#F9DA4C",
      display: "flex",
      alignSelf: "center",
    },
  });
  
const WIDTH_SWIPE = 240;
const MINUS_WIDTH = 100;

const CustomSwitch = ({ onSwipe, title, onSwiping = ()=>{} }) => {

  const styles = Styles({ WIDTH_SWIPE });
  const [state, setState] = useState({
    paddingHorizontal: new Animated.Value(0),
    paddingFill: new Animated.Value(0),
    dx: 0,
  });

  const panResponder = PanResponder.create({
    onStartShouldSetPanResponder: (evt, gestureState) => true,
    onStartShouldSetPanResponderCapture: (evt, gestureState) => true,
    onMoveShouldSetPanResponder: (evt, gestureState) => true,
    onMoveShouldSetPanResponderCapture: (evt, gestureState) => true,

    onPanResponderMove: (evt, gestureState) => {
      if (gestureState.dx >= 30 + MINUS_WIDTH) {
        Animated.timing(state.paddingHorizontal, {
          toValue: WIDTH_SWIPE - 50,
          duration: 50,
          useNativeDriver: false,
        }).start((p) => {
          if (p.finished) {
            onSwiping(false);
            onSwipe();
          }
        });
        Animated.timing(state.paddingFill, {
          toValue: WIDTH_SWIPE-25,
          duration: 50,
          useNativeDriver: false,
        }).start();
      } else if (gestureState.dx > 0) {
        state.paddingHorizontal.setValue(gestureState.dx);
        state.paddingFill.setValue(gestureState.dx + SIZE_THUMB/2);
        onSwiping(true);
      }
    },
    onPanResponderTerminationRequest: (evt, gestureState) => true,
    onPanResponderRelease: (evt, gestureState) => {
      if (
        gestureState.dx > -(WIDTH_SWIPE - MINUS_WIDTH) &&
        gestureState.dx < WIDTH_SWIPE - MINUS_WIDTH
      ) {
        Animated.timing(state.paddingHorizontal, {
          toValue: 0,
          duration: WIDTH_SWIPE - MINUS_WIDTH,
          useNativeDriver: false,
        }).start();
        Animated.timing(state.paddingFill, {
          toValue: 0,
          duration: WIDTH_SWIPE - MINUS_WIDTH,
          useNativeDriver: false,
        }).start();
        setSwiping(false);
      }
    },
  });

  return (
    <LinearGradient
      style={styles.swipeContainer}
      locations={[0, 1.0]}
      colors={["#55544e", "#52514b"]}
    >
      <Text style={styles.swipeText}>{title}</Text>

      <Animated.View
        style={{
          height: '100%',
          paddingLeft: state.paddingFill,
          backgroundColor: '#ffffff10',
        }}
        {...panResponder.panHandlers}
      >
      </Animated.View>

      <Animated.View
        style={{
          paddingLeft: state.paddingHorizontal,
          alignItems: "flex-start",
        }}
        {...panResponder.panHandlers}
      >
          <View style={styles.swipePan} />
      </Animated.View>
    </LinearGradient>
  );
}

export default CustomSwitch;

// Screen.js
const [scrolled, setScrolled] = useState(false);
const onSwiping = (status) => {
  setScrolled(!status)
}
const onSwipe = () => {
  // finished swipe, logic
}

<ScrollView 
  scrollEnabled={scrolled} 
  ...
>
  <View>
    <CustomSwitch 
      title="custom switch" 
      onSwipe={onSwipe} 
      onSwiping={onSwiping} 
    />
  </View>
</ScrollView>

字符串

相关问题