如何使用 Animated 使列表 (FlatList) 自动滚动元素? [英] How do I make a list (FlatList) automatically scroll through the elements using Animated?
问题描述
我有一个水平的 FlatList,每次到达末尾时,它都会自动向列表中添加新元素,因此它是一个无限列表.我希望应用程序自己自动滚动列表,而用户仍然必须能够来回滚动.这就是我要远的
export default class ImageCarousel extends Component {构造函数(道具){超级(道具);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);//监听器调用 scrollToOffset 函数this.offset.addListener(this.scrollTo);}_scroller() {toValue = this.scrollX + 10;//在每个循环中滚动 10 个像素this.animation = Animated.timing(this.offset,{toValue: toValue,duration: 1000,//一个循环需要一秒钟缓动:缓动.线性,});this.animation.start(() => this._scroller());//完成后重复自己}滚动到(e){this.carousel.scrollToOffset({offset: e.value});}句柄滚动(事件){//每次滚动发生时保存 x(水平)值this.scrollX = event.nativeEvent.contentOffset.x;}componentDidMount() {this._scroller();}使成为() {返回 (<查看><平面列表ref={el =>this.carousel = el}数据={someData}renderItem={renderFunction}水平={真}keyExtractor={someKeyFunction}onEndReached={loadMoreElementsFunction}onScroll={this.handleScroll}/></查看>);}}
它的工作原理是它会自动滚动列表,但是问题是我无法手动滚动列表,因为滚动位置会由 scrollTo 侦听器不断更新.我尝试添加一个 onPress 回调以在按下 FlatList 时禁用动画,但是我无法让它工作.
- 这是我的数据.
<块引用>
块引用
state = {关联: ['https://image.shutterstock.com/image-vector/online-exam-computer-web-app-260nw-1105800884.jpg','https://image.shutterstock.com/image-vector/online-exam-computer-web-app-260nw-1105800884.jpg','https://image.shutterstock.com/image-vector/online-exam-computer-web-app-260nw-1105800884.jpg','https://image.shutterstock.com/image-vector/online-exam-computer-web-app-260nw-1105800884.jpg',],};
<块引用>
- 定义 FlatList 引用
flatList = createRef();
<块引用>
- FlatList 组件
<块引用>
- 下一张幻灯片
_goToNextPage = () =>{if (CurrentSlide >= this.state.link.length-1) CurrentSlide = 0;this.flatList.current.scrollToIndex({索引:++CurrentSlide,动画:真实,});};
<块引用>
- 开始和停止间隔
_startAutoPlay = () =>{this._timerId = setInterval(this._goToNextPage, IntervalTime);};_stopAutoPlay = () =>{如果(this._timerId){clearInterval(this._timerId);this._timerId = null;}};
<块引用>
- 相关功能
componentDidMount() {this._stopAutoPlay();this._startAutoPlay();}componentWillUnmount() {this._stopAutoPlay();}_renderItem({item, index}) {return <Image source={{uri: item}} style={styles.sliderItems}/>;}_keyExtractor(项目,索引){返回 index.toString();}
<块引用>
完整代码:
import React, {Component, createRef} from 'react';进口 {文本,看法,滚动视图,图像,样式表,方面,平面列表,来自'反应原生';让 CurrentSlide = 0;让间隔时间 = 4000;导出默认类滑块扩展组件{flatList = createRef();//待办事项 _goToNextPage()_goToNextPage = () =>{if (CurrentSlide >= this.state.link.length-1) CurrentSlide = 0;this.flatList.current.scrollToIndex({索引:++CurrentSlide,动画:真实,});};_startAutoPlay = () =>{this._timerId = setInterval(this._goToNextPage, IntervalTime);};_stopAutoPlay = () =>{如果(this._timerId){clearInterval(this._timerId);this._timerId = null;}};componentDidMount() {this._stopAutoPlay();this._startAutoPlay();}componentWillUnmount() {this._stopAutoPlay();}//待办事项 _renderItem()_renderItem({item, index}) {return <Image source={{uri: item}} style={styles.sliderItems}/>;}//待办事项 _keyExtractor()_keyExtractor(项目,索引){//console.log(item);返回 index.toString();}状态 = {关联: ['https://image.shutterstock.com/image-vector/online-exam-computer-web-app-260nw-1105800884.jpg','https://image.shutterstock.com/image-vector/online-exam-computer-web-app-260nw-1105800884.jpg',//'https://picsum.photos/200/300','https://image.shutterstock.com/image-vector/online-exam-computer-web-app-260nw-1105800884.jpg','https://image.shutterstock.com/image-vector/online-exam-computer-web-app-260nw-1105800884.jpg',],};使成为() {返回 (<视图样式={{marginTop: 10, marginBottom: 10}}><平面列表风格={{弹性:1,//TODO 移除额外的全局填充//marginLeft: -size.padding,//marginRight: -size.padding,}}数据={this.state.link}keyExtractor={this._keyExtractor.bind(this)}renderItem={this._renderItem.bind(this)}水平={真}flatListRef={React.createRef()}ref={this.flatList}/></查看>);}}const 样式 = StyleSheet.create({滑块项目:{左边距:5,边距:5,高度:200,宽度:Dimensions.get('window').width,},});
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.
- This is my Data.
Blockquote
state = {
link: [
'https://image.shutterstock.com/image-vector/online-exam-computer-web-app-260nw-1105800884.jpg',
'https://image.shutterstock.com/image-vector/online-exam-computer-web-app-260nw-1105800884.jpg',
'https://image.shutterstock.com/image-vector/online-exam-computer-web-app-260nw-1105800884.jpg',
'https://image.shutterstock.com/image-vector/online-exam-computer-web-app-260nw-1105800884.jpg',
],};
- Define FlatList Ref
flatList = createRef();
- FlatList component
<FlatList
style={{flex: 1}}
data={this.state.link}
keyExtractor={this._keyExtractor.bind(this)}
renderItem={this._renderItem.bind(this)}
horizontal={true}
flatListRef={React.createRef()}
ref={this.flatList}
/>
- Next slide
_goToNextPage = () => {
if (CurrentSlide >= this.state.link.length-1) CurrentSlide = 0;
this.flatList.current.scrollToIndex({
index: ++CurrentSlide,
animated: true,
});
};
- Start and stop Interval
_startAutoPlay = () => {
this._timerId = setInterval(this._goToNextPage, IntervalTime);
};
_stopAutoPlay = () => {
if (this._timerId) {
clearInterval(this._timerId);
this._timerId = null;
}
};
- Associated function
componentDidMount() {
this._stopAutoPlay();
this._startAutoPlay();
}
componentWillUnmount() {
this._stopAutoPlay();
}
_renderItem({item, index}) {
return <Image source={{uri: item}} style={styles.sliderItems} />;
}
_keyExtractor(item, index) {
return index.toString();
}
Full Code:
import React, {Component, createRef} from 'react';
import {
Text,
View,
ScrollView,
Image,
StyleSheet,
Dimensions,
FlatList,
} from 'react-native';
let CurrentSlide = 0;
let IntervalTime = 4000;
export default class Slider extends Component {
flatList = createRef();
// TODO _goToNextPage()
_goToNextPage = () => {
if (CurrentSlide >= this.state.link.length-1) CurrentSlide = 0;
this.flatList.current.scrollToIndex({
index: ++CurrentSlide,
animated: true,
});
};
_startAutoPlay = () => {
this._timerId = setInterval(this._goToNextPage, IntervalTime);
};
_stopAutoPlay = () => {
if (this._timerId) {
clearInterval(this._timerId);
this._timerId = null;
}
};
componentDidMount() {
this._stopAutoPlay();
this._startAutoPlay();
}
componentWillUnmount() {
this._stopAutoPlay();
}
// TODO _renderItem()
_renderItem({item, index}) {
return <Image source={{uri: item}} style={styles.sliderItems} />;
}
// TODO _keyExtractor()
_keyExtractor(item, index) {
// console.log(item);
return index.toString();
}
state = {
link: [
'https://image.shutterstock.com/image-vector/online-exam-computer-web-app-260nw-1105800884.jpg',
'https://image.shutterstock.com/image-vector/online-exam-computer-web-app-260nw-1105800884.jpg',
// 'https://picsum.photos/200/300',
'https://image.shutterstock.com/image-vector/online-exam-computer-web-app-260nw-1105800884.jpg',
'https://image.shutterstock.com/image-vector/online-exam-computer-web-app-260nw-1105800884.jpg',
],
};
render() {
return (
<View style={{marginTop: 10, marginBottom: 10}}>
<FlatList
style={{
flex: 1,
// TODO Remove extera global padding
// marginLeft: -size.padding,
// marginRight: -size.padding,
}}
data={this.state.link}
keyExtractor={this._keyExtractor.bind(this)}
renderItem={this._renderItem.bind(this)}
horizontal={true}
flatListRef={React.createRef()}
ref={this.flatList}
/>
</View>
);
}
}
const styles = StyleSheet.create({
sliderItems: {
marginLeft: 5,
marginRight: 5,
height: 200,
width: Dimensions.get('window').width,
},
});
这篇关于如何使用 Animated 使列表 (FlatList) 自动滚动元素?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!