Обновление встроенного события Onscroll для всех компонентов оболочки одного типа - PullRequest
1 голос
/ 24 марта 2019

У меня есть компонент плоского списка оболочки, используемый в библиотеке реагирующей навигации. Этот компонент находится на другой вкладке навигации по стеку для обработки анимации заголовка.

import React, { Component } from "react";
import { Constants } from 'expo';
// import PropTypes from "prop-types";
import {
  Animated,
  Dimensions,
  // PanResponder,
  // Platform,
  // ScrollView,
  StyleSheet,
  FlatList,
  // ScrollView,
  // StatusBar,
  // Text,
  // TouchableWithoutFeedback,
  // View
} from "react-native";
// import Icon from "react-native-vector-icons/Ionicons";

// Get screen dimensions
const { width, height } = Dimensions.get("window");

const AnimatedFlatList = Animated.createAnimatedComponent(FlatList);
const HEADER_HEIGHT= 40;
const FILTER_HEIGHT= 50;
const STATUS_BAR_HEIGHT = Constants.statusBarHeight;
const NAVBAR_HEIGHT = HEADER_HEIGHT+FILTER_HEIGHT-2;
const scrollAnim = new Animated.Value(0);
const offsetAnim = new Animated.Value(0);

export default class AnimatedFlatListComp extends React.PureComponent {
  // Define state
  state = {
    scrollAnim,
    offsetAnim,
    clampedScroll: Animated.diffClamp(
      Animated.add(
        scrollAnim.interpolate({
          inputRange: [0, 1],
          outputRange: [0, 1],
          extrapolateLeft: 'clamp',
        }),
        offsetAnim,
      ),
      0,
      // NAVBAR_HEIGHT - STATUS_BAR_HEIGHT,
      HEADER_HEIGHT //i mede this one cuz the code abode not work is the value 40
    ),
  };

  componentWillUnmount() {
    console.log('smontoooo');
    // this._isMounted = false;
    // Don't forget to remove the listeners!
    // this.state.scrollAnim.removeAllListeners();
    // this.state.offsetAnim.removeAllListeners();
    this._disableListener();
  }

  componentDidMount() {
    this._clampedScrollValue = 0;
    this._offsetValue = 0;
    this._scrollValue = 0;
    this._enableLister()
    this._handleScroll()
  }

  _onMomentumScrollBegin = () => {
    console.log('_onMomentumScrollBegin');
      clearTimeout(this._scrollEndTimer);
  }

  _onScrollEndDrag = () => {
    this._scrollEndTimer = setTimeout(this._onMomentumScrollEnd, 250);
  }

  _onMomentumScrollEnd = () => {
    console.log('_onMomentumScrollEnd');
    console.log(this._scrollValue, NAVBAR_HEIGHT, this._clampedScrollValue, (NAVBAR_HEIGHT - STATUS_BAR_HEIGHT) / 2);
    const toValue = this._scrollValue > NAVBAR_HEIGHT &&
      this._clampedScrollValue > (NAVBAR_HEIGHT - STATUS_BAR_HEIGHT) / 2
      ? this._offsetValue + NAVBAR_HEIGHT
      : this._offsetValue - NAVBAR_HEIGHT;

    Animated.timing(this.state.offsetAnim, {
      toValue,
      duration: 350,
      useNativeDriver: true,
    }).start();
  }

  _handleScroll = () => this.props._handleScroll(this.state.clampedScroll)

  // _handleScroll = event => {
  //   const { y } = event.nativeEvent.contentOffset;
  //   // // console.log(y);
  //   this.setState({ scrollOffset: y }, () => {
  //     this.props._handleScroll(this.state.clampedScroll)
  //   });
  //
  // };

  _scrollToTop = () => {
    console.log('_scrollToTop');
    if (!!this.flatListRef) {
      // this.flatListRef.getNode().scrollTo({ y: 0, animated: true });
      this.flatListRef.getNode().scrollToOffset({ offset: 0, animated: true });
    }
  };

  _enableLister = () => {
    // this._firstMountFunction();
    this.state.scrollAnim.addListener(({ value }) => {
      // This is the same calculations that diffClamp does.
      const diff = value - this._scrollValue;
      this._scrollValue = value;
      this._clampedScrollValue = Math.min(
        Math.max(this._clampedScrollValue + diff, 0),
        NAVBAR_HEIGHT - STATUS_BAR_HEIGHT,
      );
    });
    this.state.offsetAnim.addListener(({ value }) => {
      this._offsetValue = value;
    });
  }

  _disableListener = () => {
    this.state.scrollAnim.removeAllListeners();
    this.state.offsetAnim.removeAllListeners();
  }

  _keyExtractor = (item, index) => index.toString();

  // _onScroll = event => {
  // 
  // }

  render() {

    return (
      <AnimatedFlatList
        {...this.props}
        ref={(ref) => { this.flatListRef = ref; }}
        showsVerticalScrollIndicator={false}
        onScroll={Animated.event(
          [{nativeEvent: {contentOffset: {y: this.state.scrollAnim}}}],
          {
            useNativeDriver: true,
            // listener: this._handleScroll
          },
        )}
        // onScroll={this._onScroll}
        removeClippedSubviews={true}
        keyExtractor={this._keyExtractor}
        onMomentumScrollBegin={this._onMomentumScrollBegin}
        onMomentumScrollEnd={this._onMomentumScrollEnd}
        onScrollEndDrag={this._onScrollEndDrag}
        scrollEventThrottle={1}
      />

    );
  }
}

это родитель

_handleScroll = clampedScroll => this.setState({ clampedScroll: clampedScroll })
render(){
const { clampedScroll } = this.state;
      //
      const navbarTranslate = clampedScroll.interpolate({
        inputRange: [0, NAVBAR_HEIGHT - STATUS_BAR_HEIGHT],
        outputRange: [0, -(NAVBAR_HEIGHT - STATUS_BAR_HEIGHT)],
        extrapolate: 'clamp',
      });
return (
          <AnimatedFlatList
            // debug={true}
            ref={(ref) => { this.flatListRef = ref; }}
            maxToRenderPerBatch={4}
            contentContainerStyle={{
              paddingTop: NAVBAR_HEIGHT+STATUS_BAR_HEIGHT,
            }}
            data={this.state.dataSource}
            renderItem={
              ({item, index}) =>
                <CardAgenda
                  item={JSON.parse(item.JSON)}
                  ChangeSelectedEvent={this.ChangeSelectedEvent}
                  colorTrail={JSON.parse(item.colorTrail)}
                  // _sendBackdata={this._getChildrenCategoryData}
                  searchData={JSON.parse(item.searchData)}
                  NumAncillary={item.NumAncillary}
                  indexItinerary={item.id}
                  index={index}
                />
            }
            ListEmptyComponent={this._emptyList}
            ItemSeparatorComponent={() => <View style={{width: width-40, backgroundColor: 'rgba(0,0,0,0.1)', height: 1, marginTop: 20, marginLeft: 20, marginRight: 20}}/>}
            _handleScroll={this._handleScroll}
          />
)}

Работает нормально, но событие onscroll вызывает переменную this.state.scrollAnim для всех оболочек. Я имею в виду, если я прокручиваю вверх первый AnimatedFlatList, заголовок поднимается, но и другой заголовок на новой навигационной странице повышается.

Правильным поведением должно быть то, что весь заголовок должен быть независимым от собственного плоского списка.

Заранее спасибо

1 Ответ

1 голос
/ 24 марта 2019

Это потому, что вы настраиваете ссылку на состояние при создании анимированных значений obj. Вы не должны хранить их как константы за пределами границ вашего класса.

Попробуйте удалить следующие константы.

const scrollAnim = new Animated.Value(0);
const offsetAnim = new Animated.Value(0);

Затем определите их внутри конструктора.

 export default class AnimatedFlatListComp extends React.PureComponent {
  constructor(props){
   super(props);
   this.scrollAnim = new Animated.Value(0);
   this.offsetAnim = new Animated.Value(0);
   // Define state
   state = {
        scrollAnim: this.scrollAnim,
        offsetAnim:  this.offsetAnim,
        clampedScroll: Animated.diffClamp(
          Animated.add(
            this.scrollAnim.interpolate({
              inputRange: [0, 1],
              outputRange: [0, 1],
              extrapolateLeft: 'clamp',
            }),
           this.offsetAnim,
          ),
        0,
        // NAVBAR_HEIGHT - STATUS_BAR_HEIGHT,
        HEADER_HEIGHT //i mede this one cuz the code abode not work is 
        the value 40
        ),
      };
    }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...