How do I make a list (FlatList) automatically scroll through the elements using Animated?

久未见 提交于 2019-12-11 05:38:33

问题


I have a horizontal FlatList, where each time it reaches the end, it automatically adds new elements to the list, so it kind of is an infinite list. I want the app to scroll through the list by itself automatically, while the user must still be able to scroll back and forth. This is what I have to far

export default class ImageCarousel extends Component {
  constructor(props) {
    super(props);

    this.scrollX = 0;
    this.offset = new Animated.Value(0);
    this.scrollTo = this.scrollTo.bind(this);
    this.handleScroll = this.handleScroll.bind(this);
    this.stopAnimation = this.stopAnimation.bind(this);
    // Listener to call the scrollToOffset function
    this.offset.addListener(this.scrollTo);
  }

  _scroller() {
    toValue = this.scrollX + 10; // Scroll 10 pixels in each loop
    this.animation = Animated.timing(
      this.offset,
      {
        toValue: toValue,
        duration: 1000, // A loop takes a second
        easing: Easing.linear,
      }
    );
    this.animation.start(() => this._scroller()); //Repeats itself when done
  }

  scrollTo(e) {
    this.carousel.scrollToOffset({offset: e.value});
  }

  handleScroll(event) {
    // Save the x (horizontal) value each time a scroll occurs
    this.scrollX = event.nativeEvent.contentOffset.x;
  }

  componentDidMount() {
    this._scroller();
  }
  render() {
    return (
      <View>
        <FlatList
          ref={el => this.carousel = el}
          data={someData}
          renderItem={renderFunction}
          horizontal={true}
          keyExtractor={someKeyFunction}
          onEndReached={loadMoreElementsFunction}
          onScroll={this.handleScroll}
        />
      </View>
    );
  }
}

It works in the sense that it is automatically scrolling through the list, the problem however, is I cannot manually scroll through the list, since the scroll position is constantly updated by the scrollTo listener. I have tried to add an onPress callback to disable the animation when the FlatList is pressed, I have however not been able to get it to work.


回答1:


Just in case you're still not found the answer yet, this is my approach to create autoscroll carousel using FlatList

import React, { Component } from 'react'
import {
  StyleSheet,
  View,
  FlatList,
  ScrollView,
  Dimensions,
  Image
} from 'react-native'

const { width } = Dimensions.get('window');
const height = width * 0.2844;

export default class App extends Component {
  constructor(props) {
    super(props);

    this.state = {
      search: '',
      sliderIndex: 0,
      maxSlider: 2,
      banners: [
        {_id: 1, imageUrl: 'https://www.do-cart.com/img/slider/1.jpg'},
        {_id: 2, imageUrl: 'https://www.do-cart.com/img/slider/2.jpg'},
        {_id: 3, imageUrl: 'https://www.do-cart.com/img/slider/3.jpg'},
      ],
    }
 }

 setRef = (c) => {
   this.listRef = c;
 }

 scrollToIndex = (index, animated) => {
   this.listRef && this.listRef.scrollToIndex({ index, animated })
 }

 componentWillMount() {
   setInterval(function() {
     const { sliderIndex, maxSlider } = this.state
     let nextIndex = 0

     if (sliderIndex < maxSlider) {
       nextIndex = sliderIndex + 1
     }

     this.scrollToIndex(nextIndex, true)
     this.setState({sliderIndex: nextIndex})
   }.bind(this), 3000)
 }

 render() {
   return (
     <View style={styles.container}>
       <View style={{height: 80, backgroundColor: '#123866', width:'100%'}}></View>

    <ScrollView style={styles.scrollContainer} showsVerticalScrollIndicator={false}>
      <FlatList
        ref={this.setRef}
        data={this.state.banners}
        horizontal
        showsHorizontalScrollIndicator={false}
        pagingEnabled
        keyExtractor={item => item._id}
        renderItem={({item, i}) => (
          <View key={i} style={{ height, width}}>
            <Image style={{ height, width }} source={{ uri: item.imageUrl }} />
          </View>
        )}
        onMomentumScrollEnd={(event) => {
          let sliderIndex = event.nativeEvent.contentOffset.x ? event.nativeEvent.contentOffset.x/width : 0
          this.setState({sliderIndex})
        }}
      />
      <View style={styles.sliderContainer}>
        {
          this.state.banners.map(function(item, index) {
            return (
              <View key={index} style={styles.sliderBtnContainer}>
                <View style={styles.sliderBtn}>
                  {
                    this.state.sliderIndex == index ? <View style={styles.sliderBtnSelected}/> : null
                  }
                </View>
              </View>
            )
          }.bind(this))
        }
      </View>
    </ScrollView>
  </View>
);
   }
 }

const styles = StyleSheet.create({
  container: {
    flex: 1,
    justifyContent: 'center',
    alignItems: 'center',
    backgroundColor: '#F5FCFF',
  },
  scrollContainer: {
    flex: 1
  },
  sliderContainer: {
    flexDirection: 'row',
    position: 'absolute',
    top: 80,
    alignSelf: 'center'
  },
  sliderBtn: {
    height: 13,
    width: 13,
    borderRadius: 12,
    borderWidth: 1,
    borderColor: 'white',
    alignItems: 'center',
    justifyContent: 'center',
    marginRight: 10
  },
  sliderBtnSelected: {
    height: 12,
    width: 12,
    borderRadius: 6,
    backgroundColor: 'white',
  },
  sliderBtnContainer: {
    flexDirection: 'row', marginBottom: 24
  },
});

https://snack.expo.io/rJ9DOn0Ef



来源:https://stackoverflow.com/questions/44475202/how-do-i-make-a-list-flatlist-automatically-scroll-through-the-elements-using

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!