Задать вопрос
@User782
Кратко о себе

Как автоматически включить скролл контента при достижения верхней границы свайпом родителя?

По расспрашивал все чаты. Решение не нашел.
Сейчас чтобы скрол контента на экране включился, я довожу родителя до самого верха и нужно поднять палец, тогда скрол контента включиться.
Нужно чтобы не поднимая пальца скрол включился при достижении верхней грницы экрана родителем при свайпе.
То есть я поднимаю родителя свайпом вверх, и если продолжаю свайпить вверх то нужно чтобы переключился свайп на скрол контента не поднимая пальцы.
Сейчас палец нужно поднять.
И при закрытии также нужно поднять палец чтобы скрол отключился когда тяну вниз.
Помогите пожалуйста.
import React, { useEffect, useRef, useState } from 'react';
import {
  Modal,
  View,
  Text,
  StyleSheet,
  TouchableOpacity,
  Animated,
  Dimensions,
  Image,
  PanResponder,
  Alert,
  ScrollView,
} from 'react-native';

const screenWidth = Dimensions.get('window').width;
const screenHeight = Dimensions.get('window').height;
const INITIAL_POSITION = screenHeight * 0.4;

const Screen1 = ({ navigation }) => {
  const [isScrollEnabled, setScrollEnabled] = useState(false); 
  const [isOverlayVisible, setOverlayVisible] = useState(true);

  const slideAnim = useRef(new Animated.Value(INITIAL_POSITION)).current;
  const currentPosition = useRef(INITIAL_POSITION);
  const scrollViewRef = useRef(null); // Реф для ScrollView

  useEffect(() => {
    slideAnim.setValue(screenHeight);
    Animated.timing(slideAnim, {
      toValue: INITIAL_POSITION,
      duration: 400,
      useNativeDriver: true,
    }).start();
  }, []);

  const panResponder = useRef(
    PanResponder.create({
      onMoveShouldSetPanResponder: (_, gestureState) => {
        // Разрешаем родителю захватывать свайп, если ScrollView неактивен или вверху
        return Math.abs(gestureState.dy) > 10 && (!isScrollEnabled || gestureState.dy > 0);
      },
      onPanResponderMove: (_, gestureState) => {
        const newPosition = Math.max(0, currentPosition.current + gestureState.dy);
        slideAnim.setValue(newPosition);
        setOverlayVisible(newPosition < screenHeight * 0.7);

        // Включаем ScrollView только если модалка в самом верху
        setScrollEnabled(newPosition <= 0);
      },
      onPanResponderRelease: (_, gestureState) => {
        currentPosition.current = slideAnim._value;

        if (currentPosition.current > screenHeight * 0.7) {         
          Animated.timing(slideAnim, {
            toValue: screenHeight,
            duration: 300,
            useNativeDriver: true,
          }).start(() => {           
            navigation.goBack();
          });
        } else {
          Animated.spring(slideAnim, {
            toValue: currentPosition.current,
            useNativeDriver: true,
          }).start();
        }
      },
    })
  ).current;   

  // Обработчик прокрутки ScrollView
  const handleScroll = (event) => {
    const scrollY = event.nativeEvent.contentOffset.y;
    // Если ScrollView в самом верху, отключаем его, чтобы передать свайп родителю
    if (scrollY <= 0) {
      setScrollEnabled(false);
    }
  };

  return (
    <View style={styles.fullScreen}>
      {isOverlayVisible && <View style={styles.backgroundOverlay} />}
      <Animated.View
        style={[styles.overlay, { transform: [{ translateY: slideAnim }] }]}
        {...panResponder.panHandlers}
      >
        <View style={[styles.container, { backgroundColor: '#eee', flex: 1 }]}>       

          <View style={[styles.section, { backgroundColor: '#eee',height:200 }]}>            
            
            <Text style={[styles.sectionT, { fontSize: 19 }]}>
             БЛОК ПОД КОТОРЫМ СКОЛЛ
            </Text>

          </View>
          <ScrollView
            ref={scrollViewRef}
            scrollEnabled={isScrollEnabled}
            onScroll={handleScroll}
            scrollEventThrottle={16}         
          >

<View style={{marginRight:20}}>
           <View style={{ position: 'relative' }}>
  <View style={{height:200,margin:30,padding:20,backgroundColor:'#000'}}><Text>qwe</Text></View>
               <View style={{height:200,margin:30,padding:20,backgroundColor:'#000'}}><Text>qwe</Text></View>
                <View style={{height:200,margin:30,padding:20,backgroundColor:'#000'}}><Text>qwe</Text></View>
                 <View style={{height:200,margin:30,padding:20,backgroundColor:'#000'}}><Text>qwe</Text></View>
                  <View style={{height:200,margin:30,padding:20,backgroundColor:'#000'}}><Text>qwe</Text></View>
                   <View style={{height:200,margin:30,padding:20,backgroundColor:'#000'}}><Text>qwe</Text></View>
                    <View style={{height:200,margin:30,padding:20,backgroundColor:'#000'}}><Text>qwe</Text></View>
                     <View style={{height:200,margin:30,padding:20,backgroundColor:'#000'}}><Text>qwe</Text></View>
 
</View>
            </View>          
          </ScrollView>
          
        </View>  
        </Animated.View>        
    </View>
  );
};
 
const styles = StyleSheet.create({
  fullScreen: {
    flex: 1,
    position: 'absolute',
    top: 0,
    left: 0,
    width: screenWidth,
    height: screenHeight,
  },
  backgroundOverlay: {
    position: 'absolute',
    top: 0,
    left: 0,
    right: 0,
    bottom: 0,
    backgroundColor: 'rgba(0, 0, 0, 0.5)',
  },
  overlay: {
    position: 'absolute',
    top: 0,
    left: 0,
    width: screenWidth,
    height: '100%',
    zIndex: 1000,
  },    
  modalOverlay: {
    flex: 1,
    backgroundColor: '#00000088',
    justifyContent: 'center',
    alignItems: 'center',
  },
});

export default Screen1;
  • Вопрос задан
  • 28 просмотров
Подписаться 1 Средний Комментировать
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы