Задать вопрос
  • Как сделать беспрерывный свайп?

    @User782 Автор вопроса
    Кратко о себе
    может кому пригодиться без реаниматора v4
    реаниматор v4 тупит без expo или я не смог настроить его нормально, но тупило жоска на последней версии RN.
    реаниматор v3 не пробовал. надо старую версию RN накатывать

    этот вариант очень простой через PanResponder
    багов не увидел.

    import React, { useEffect, useRef, useState } from 'react';
    import {
      View, Text, StyleSheet, Animated, Dimensions,
      PanResponder, ScrollView
    } from 'react-native';
    
    const { height: screenHeight } = Dimensions.get('window');
    
    const MIN_HEIGHT = 70;
    const MAX_HEIGHT = 3400; // потолок, выше которого панель не открывать, даже если контент больше
    
    const INITIAL_TRANSLATE_Y = screenHeight - MIN_HEIGHT;
    const CLOSED_POSITION = INITIAL_TRANSLATE_Y;
    
    const ScreenDemo1 = ({ navigation }) => {
      const slideAnim = useRef(new Animated.Value(INITIAL_TRANSLATE_Y)).current;
    
      const currentPosition = useRef(INITIAL_TRANSLATE_Y);
      const [btmCoo, setBtmCoo] = useState(100);
    
      const [isAtTop, setIsAtTop] = useState(false);
      const [scrollY, setScrollY] = useState(0);
    
     
    
      const [heightBottom, setHeightBottom] = useState(0);
    
      // ref с тем же значением — он НЕ застывает в замыканиях PanResponder
      const contentHeightRef = useRef(0);
      const measuredRef = useRef(false); // флаг "высота уже посчитана"
    
      // актуальный верхний предел открытия панели
      const getMaxOpenPosition = () => {
        const measuredHeight = measuredRef.current
          ? contentHeightRef.current // + MIN_HEIGHT + 70 на хэндл сверху контента
          : MAX_HEIGHT; // пока высота не измерена — используем потолок как дефолт
        const h = Math.min(measuredHeight, MAX_HEIGHT);
        return screenHeight - h;
      };
    
      const updateIsAtTop = (value) => {
        const newIsAtTop = Math.abs(value - getMaxOpenPosition()) < 15;
        if (newIsAtTop !== isAtTop) {
          setIsAtTop(newIsAtTop);
        }
      };
    
      const panResponder = useRef(
        PanResponder.create({
          onMoveShouldSetPanResponder: (_, gestureState) => {
            if (isAtTop && gestureState.dy > 0 && scrollY <= 5) {
              return true;
            }
            return Math.abs(gestureState.dy) > 10;
          },
    
          onPanResponderGrant: () => {
            slideAnim.stopAnimation();
          },
    
          onPanResponderMove: (_, gestureState) => {
            let newPosition = currentPosition.current + gestureState.dy;
    
            const maxOpenPosition = getMaxOpenPosition(); // читаем актуальное значение из ref
            newPosition = Math.max(
              maxOpenPosition,
              Math.min(newPosition, CLOSED_POSITION)
            );
    
            setBtmCoo(newPosition);
             //console.log('translateY:', newPosition);
    
    
            slideAnim.setValue(newPosition);
            updateIsAtTop(newPosition);
          },
    
          onPanResponderRelease: () => {
            const finalPosition = slideAnim._value;
            currentPosition.current = finalPosition;
            updateIsAtTop(finalPosition);
          },
        })
      ).current;
    
      useEffect(() => {
        slideAnim.setValue(screenHeight);
        Animated.timing(slideAnim, {
          toValue: INITIAL_TRANSLATE_Y,
          duration: 350,
          useNativeDriver: true,
        }).start(() => {
          updateIsAtTop(INITIAL_TRANSLATE_Y);
        });
      }, []);
    
      return (
        <View style={styles.container}>
          <View style={styles.backgroundContent}>
            <Text style={styles.demoTitle}>Основной экран</Text>
            <Text style={{ marginBottom: 240 }}>1 материалы</Text>
            <Text style={{ marginBottom: 240 }}>2 материалы</Text>
    <Text style={{ marginBottom: 240 }}>3 материалы</Text>
    <Text style={{ marginBottom: 240 }}>4 материалы</Text>
    <Text style={{ marginBottom: 240 }}>5 материалы</Text>
            <Text style={{  }}>3 материалы</Text>
           
          </View>
    
    
         {btmCoo < 0 && (
      <View style={{backgroundColor: '#529b00',position: 'absolute',top: 0,left: 0,right: 0,zIndex: 1999, }}>
        <Text style={[styles.title, { color: '#fff' }]}>
          Панель {btmCoo}
        </Text>
      </View>
    )}
          
    
          <Animated.View
            style={[
              styles.overlay,
              {
                backgroundColor: '#000',
                transform: [{ translateY: slideAnim }],
              },
            ]}
            {...panResponder.panHandlers}
          >
    
             
            
            <View
              onLayout={(e) => {
                const { height } = e.nativeEvent.layout;
                contentHeightRef.current = height; // используется внутри PanResponder
                measuredRef.current = true;
                setHeightBottom(height); // для рендера/отображения, если нужно
                console.log('CONTENT HEIGHT:', height);
              }}
              style={{ backgroundColor: '#000' }}>
    
    
    
            
         {btmCoo > 0 && (
      <View style={{backgroundColor: '#580597',position: 'absolute',top: 0,left: 0,right: 0,zIndex: 1999, }}>
        <Text style={[styles.title, { color: '#fff' }]}>
          Панель {btmCoo}
        </Text>
      </View>
    )}
    
    
    
      <View style={{paddingBottom:20}}>
              <Text style={{ marginBottom: 240, color: '#fff' }}>Вытягиваемый контент</Text>
              <Text style={{ color: '#fff' }}>1 материалы</Text>     
    <Text style={{ color: '#fff',marginBottom: 240 }}>3 материалы</Text>
            <Text style={{ color: '#fff',marginBottom: 240 }}>4 материалы</Text>
            <Text style={{ color: '#fff',marginBottom: 240 }}>5 материалы</Text>
    <Text style={{ color: '#fff',marginBottom: 240 }}>3 материалы</Text>
            <Text style={{ color: '#fff',marginBottom: 240 }}>4 материалы</Text>
            <Text style={{ color: '#fff',marginBottom: 240 }}>5 материалы</Text>     
    		    </View>
    		  
              
            </View>
          </Animated.View>
        </View>
      );
    };
    
    const styles = StyleSheet.create({
      container: { flex: 1, backgroundColor: '#f0f2f5' },
      backgroundContent: {
        flex: 1,
        justifyContent: 'center',
        alignItems: 'center',
        padding: 40,
      },
      demoTitle: { fontSize: 28, fontWeight: 'bold', color: '#333', marginBottom: 8 },
      overlay: {
        position: 'absolute',
        left: 0,
        right: 0,
        bottom: 0,
        height: screenHeight,
        borderTopLeftRadius: 24,
        borderTopRightRadius: 24,
        shadowColor: '#000',
        shadowOffset: { width: 0, height: -6 },
        shadowOpacity: 0.3,
        shadowRadius: 16,
        elevation: 25,
        zIndex: 1000,
      },
      handleContainer: { alignItems: 'center', paddingVertical: 12 },
      handle: {
        width: 42,
        height: 5,
        backgroundColor: '#ccc',
        borderRadius: 999,
      },
      title: { fontSize: 24, fontWeight: '700', marginBottom: 24 },
    });
    
    export default ScreenDemo1;
    Ответ написан
    Комментировать
  • Как встроить уже готовую базу данных в apk файл?

    @User782 Автор вопроса
    Кратко о себе
    решил вопрос если кому надо базу надо закидывать сюда
    ${FileSystem.documentDirectory}SQLite/base.db
    я закидывал без SQLite
    Ответ написан
    Комментировать
  • Как вставить курсор в добавленный блок?

    @User782 Автор вопроса
    Кратко о себе
    нашел ответ. Если кому надо:
    function s() {
            var editableDiv = document.getElementById('t');
            // Создаем новый элемент div
            var newDiv = document.createElement('div');
            // Вставляем внутренний контент, в данном случае <br>
            newDiv.innerHTML = '<br>';
            // Добавляем новый div в родительский элемент
            editableDiv.appendChild(newDiv);
            // Устанавливаем курсор в новый div
            var range = document.createRange();
            var selection = window.getSelection();
            range.setStart(newDiv, 0);
            range.collapse(true);
            selection.removeAllRanges();
            selection.addRange(range);
            newDiv.focus();
        }
    Ответ написан
    Комментировать
  • Почему второй раз не срабатывает google reCaptcha (Uncaught (in promise) TypeError)?

    @User782 Автор вопроса
    Кратко о себе
    может кому пригодится.
    создаем капчу так (если подгрузка скрипта идет одновременно с созданием капчи, то нужно создание капчи отложить на 2-3 секунды):
    откладываем на три секунды:
    setTimeout( function(){
    widgetId = grecaptcha.render('recaptchacontainer', {
              'sitekey' : 'sitekey'         
            }) }, 3000);

    или не откладываем на три секунды:
    widgetId = grecaptcha.render('recaptchacontainer', {
              'sitekey' : 'sitekey'         
            }) }

    в html вставляем:
    <div id="recaptchacontainer"></div>
    в js в переменную помещаем ответ так:
    var res = grecaptcha.getResponse(widgetId);
    больше таких проблем нет, капчу сбрасывать не нужно.
    Ответ написан
    Комментировать
  • Динамический Input mask для разных стран?

    @User782 Автор вопроса
    Кратко о себе
    так понимаю этот плагин переделывать надо
    вот решение
    https://unmanner.github.io/imaskjs/guide.html#pattern
    Вариант intl-tel-input для меня тяжелый
    Ответ написан
    Комментировать
  • Как продлить бесплатный сертификат от COMODO?

    @User782 Автор вопроса
    Кратко о себе
    разобрался, comodo дает free ssl только один раз для домена. По истечению 90 дней дальше только покупка.
    Ответ написан
    Комментировать
  • Как в выдаче вставить переменную?

    @User782 Автор вопроса
    Кратко о себе
    $i = 0;
    foreach($zapros as $row){ 
       $tpl->set('{title}', $row['title']);
       if (++$i == 2) {
          $tpl->set('{title}', $peremennaya);
       }
    }

    это не помогает, происходит подмена, но подмена не нужна, нужно вклинить
    Ответ написан
    Комментировать
  • Удалить всё что в теги div с определенным классом, вместе с этим тэгом?

    @User782 Автор вопроса
    Кратко о себе
    может кому понадобиться
    preg_replace("/(<div class=\"qwe\">)(.*)(<\/div>)/",'',$text);
    Ответ написан
  • Запретить временное расширение страницы при эффекте появления блока (anijs)?

    @User782 Автор вопроса
    Кратко о себе
    может кому пригодиться, нужно телу body добавить
    overflow-x: hidden;
    Ответ написан
    Комментировать
  • Из PHP передать в AJAX авторизация?

    @User782 Автор вопроса
    Кратко о себе
    нашел решение, если кому пригодиться

    //php
    ...
    if( `успешные условия логина` ){
    $response[status] = 1;
    }else{
    $response[error] = 'Some error';//в зависимости от того, что стало причиной ошибки - формируем текст ошибки
    echo json_encode($response);
    }

    //js
    ...
    success:function(data){
    var response = JSON.parse(data);
    if(response.status){
    alert('You have been successfully logged in.');
    }else{
    alert(response.error);
    }
    Ответ написан
    Комментировать