Реагировать на собственный анимированный список разделов, который перемещается вверх при изменении состояния/реквизита

Я создаю представление в собственном приложении для реагирования с компонентом списка разделов, и у него также есть заголовок выше, который будет отображать совокупные данные о списке. Вид заголовка должен уменьшаться с анимацией при прокрутке. У меня вся анимация работает нормально, но возникают проблемы при добавлении бесконечной прокрутки с использованием реквизита onEndreached. Когда добавляются новые данные или изменяются состояние/реквизиты, они перескакивают вверх списка.

Чтобы сделать SectionList анимированным, я обернул его с помощью Animated.createAnimatedComponent для создания компонента <AnimatedSectionList />. Проблемы возникают, когда он обернут Animated.

На приведенном ниже gif-файле вы можете видеть, что он перемещается в начало списка, когда я прокручиваю вниз. Это когда состояние меняется, и мы начинаем получать больше данных. https://monosnap.com/file/2aH5iPF2XcygEz381bpHW9QGPGHA2Z

Я пытался использовать getItemLayout для расчета размера списка, надеясь, потому что я читал, что когда реакция не знает высоту списка, это может быть нервным.

Я также пробовал прокручивать раздел после загрузки новых данных с помощью scrollTo, но это тоже не работает. Я делал это с помощью метода жизненного цикла componentDidUpdate, но componentDidUpdate не вызывался последовательно, когда поступали новые данные.

Вот мой код.


const DataItem = [
  { name: "test name", value: "testvalue" },
  { name: "test name", value: "testvalue" },
  { name: "test name", value: "testvalue" },
  { name: "test name", value: "testvalue" },
  { name: "test name", value: "testvalue" }
];

const initialSections = [
  { title: "MY DETAILS", data: DataItem },
  { title: "MY COMMUNITY", data: DataItem },
  { title: "MY FAMILY", data: DataItem }
];

const styles = {
  item: {
    flex: 1,
    height: 50,
    marginTop: 1,
    backgroundColor: "#dddddd"
  },
  sectionHeader: {
    flex: 1,
    height: 20,
    marginTop: 1,
    backgroundColor: "#00ff00"
  }
};



class Edit extends Component {
  constructor(props) {
    super(props);

    this.state = {
      scrollEnabled: true,
      scrollY: new Animated.Value(0),
      sections: initialSections,
      refreshing: false
    };


  _renderSectionHeader(section) {
    return (
      <View style={styles.sectionHeader}>
        <Text> {section.title} </Text>
      </View>
    );
  }

  _renderItem(item) {
    return (
      <View style={styles.item}>
        <Text>{item.name}</Text>
      </View>
    );
  }


  handleStateButton() {
    this.setState({ refreshing: true });
  }

  fetchMoreData() {
    this.setState({ refreshing: true });

    const newData = [...this.state.sections, ...initialSections];

    setTimeout(
      function() {
        this.setState({ sections: newData, refreshing: false });       }.bind(this),
      2000
    );
  }

  render() {
    const backgroundScrollY = this.state.scrollY.interpolate({
      inputRange: [0, 224],
      outputRange: [0, -50],
      extrapolate: "clamp"
    });

    const backgroundScrollHeight = this.state.scrollY.interpolate({
      inputRange: [0, 224],
      outputRange: [1, 0.75],
      extrapolate: "clamp"
    });

    const listScrollY = this.state.scrollY.interpolate({
      inputRange: [0, 224],
      outputRange: [0, -10],
      extrapolate: "clamp"
    });

    const infoOpacity = this.state.scrollY.interpolate({
      inputRange: [0, 0.5, 150],
      outputRange: [1, 1, 0],
      extrapolate: "clamp"
    });

    const AnimatedSectionList = Animated.createAnimatedComponent(SectionList);

    return (
      <View
        style={{
          flex: 1,
          //   alignItems: "flex-start",
          flexDirection: "column"
        }}
      >
        <Animated.View
          style={[
            {
              position: "relative",
              // flex: 1,
              // alignSelf: "flex-start",
              top: 0,
              minHeight: 200,
              height: 300,
              backgroundColor: "#ddee99",
              border: "1px solid #0000FF",
              justifyContent: "center",
              alignItems: "center"
            },
            { transform: [{ scaleY: backgroundScrollHeight }] }
          ]}
        >
          <Animated.Image
            source={{
              uri:
                "https://images.unsplash.com/photo-1558901591-3a5f333830dd?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=1350&q=80"
            }}
            style={[
              { position: "absolute", backgroundColor: "#cccccc" },
              { transform: [{ translateY: backgroundScrollY }] }
            ]}
            blurRadius={1.5}
          />

          <Text>{this.state.refreshing && `Fetching data`}</Text>

          <Button onPress={this.fetchMoreData} title="Get More Data" />
          <Button onPress={this.handleStateButton} title="Changing State" />
        </Animated.View>

        <AnimatedSectionList
          ref={ref => (this.sectionListRef = ref)}
          bounces={false}
          scrollEnabled={this.state.scrollEnabled}
          style={[
            { position: "relative" },
            { transform: [{ translateY: listScrollY }] }
          ]}
          onScroll={Animated.event(
            [{ nativeEvent: { contentOffset: { y: this.state.scrollY } } }],
            { listener: this._onScroll.bind(this) }
          )}
          sections={this.state.sections}
          renderSectionHeader={({ section }) =>
            this._renderSectionHeader(section)
          }
          ListHeaderComponent={() => (
            <View
              style={{
                flex: 1,
                flexDirection: "row",
                alignItems: "center",
                height: 40,
                backgroundColor: "#ff00ff"
              }}
            >
              <Text>List Header</Text>
            </View>
          )}
          ListFooterComponent={() => (
            <View
              style={{
                flex: 1,
                flexDirection: "row",
                alignItems: "center",
                height: 80,
                backgroundColor: "#FF0"
              }}
            >
              <Text>List Footer</Text>
            </View>
          )}
          getItemLayout={this.getItemLayout}
          renderItem={({ item }) => this._renderItem(item)}
          keyExtractor={(item, index) => index}
          stickySectionHeadersEnabled={true}
          onEndReachedThreshold={0.75}
          onEndReached={d => {
            this.fetchMoreData();
          }}
        />
      </View>
    );
  }
}


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

Буду признателен за любые мысли о наилучшем способе решения этой проблемы.


person all9lives    schedule 28.05.2019    source источник


Ответы (1)


я положил

const AnimatedSectionList = Animated.createAnimatedComponent(SectionList);

из класса и перестал прыгать на вершину

person Douglas Ramaldes    schedule 28.10.2020