正在从 URL 加载图像时加载微调器

Loadingspinner while Images is loading from URL

在我的 React Native 应用程序中,我渲染了一个带有图像的 <FlatList>。我将直接图像 url 作为源传递给 <Image> 组件。

<FlatList 
           data={this.state.images}
           keyExtractor={item => item.imageToken}
           renderItem={({ item }) => (                         
                    <Image key={item.imageToken} style={{ marginRight: 2, marginTop: 2, width: '50%', opacity: 1 }} source={{ uri: item.imageUrl }} alt="Alternate Text" size="xl" />    )}    />

这意味着图片的加载顺序不同,因为它们的大小也不同。我想在加载过程中显示一个占位符。

在显示所有图像之前,listAll() 函数将 isLoading 重置为 false。当图像在视图中完全可见时是否有 'trigger'?我不能只为每个图像构建一个状态 - 我猜。

会有好几百张图片!

我认为重要的是要知道我从 google firestore 图像中提取 url 并将它们预先存储为状态数组。参见函数 getDownloadURL

完整代码

import React, { Component } from 'react'
import { StyleSheet, SafeAreaView, ActivityIndicator } from 'react-native'
import { Image, FlatList, Center, Box } from "native-base"
import EventGalleryHeader from '../components/EventGalleryHeader.js'
import { getStorage, ref, getDownloadURL, list, listAll } from "firebase/storage"
import { LongPressGestureHandler, State } from 'react-native-gesture-handler'

export default class EventScreen extends Component {

    constructor(props) {
        super(props);
        this.storage = getStorage()
        this.pathToImages = '/eventimages/'
        this.eventImageSource = this.props.route.params.eventData.key
        this.imagesRef = this.pathToImages + this.eventImageSource
        this.state = {
            isLoading: true,
            images: [],
            event: {
                adress: this.props.route.params.eventData.adress,
                hosts: this.props.route.params.eventData.hosts,
                description: this.props.route.params.eventData.description,
                eventtitle: this.props.route.params.eventData.eventtitle,
                invitecode: this.props.route.params.eventData.invitecode,
                key: this.props.route.params.eventData.key,
                timestamp: this.props.route.params.eventData.timestamp,
            }
        }
    }

    componentDidMount() {
        this.getEventImageData()
    }

    componentWillUnmount() {
    }

    getEventImageData() {
        const images = []
        const event = {
            adress: this.props.route.params.eventData.adress,
            description: this.props.route.params.eventData.description,
            eventtitle: this.props.route.params.eventData.eventtitle,
            key: this.props.route.params.eventData.key,
            timestamp: this.props.route.params.eventData.timestamp,
        }

        listAll(ref(this.storage, this.imagesRef))
            .then((res) => {
                res.items.forEach((itemRef) => {   
                    getDownloadURL(itemRef)
                        .then((url) => {

                            const indexOfToken = url.indexOf("&token=")
                            const token = url.slice(indexOfToken + 7)
                            images.push({
                                "imageUrl": url,
                                "imageToken": token
                            });
                            this.setState({
                                images,
                                event,
                                isLoading: false,
                            });
                            // console.log(this.state.images)
                        })
                        .catch((error) => {
                            switch (error.code) {
                                case 'storage/object-not-found':
                                    break;
                                case 'storage/unauthorized':
                                    break;
                                case 'storage/canceled':
                                    break;
                                case 'storage/unknown':
                                    break;
                            }
                        });
                });

            }).catch((error) => {
            });
    }

    onLongPress = (event) => {
        if (event.nativeEvent.state === State.ACTIVE) {
            alert("I've been pressed for 800 milliseconds");
        }
    };

    render() {

        if (this.state.isLoading) {
            return (<Center style={styles.container} _dark={{ bg: "blueGray.900" }} _light={{ bg: "blueGray.50" }}>
                <ActivityIndicator size="large" color="#22d3ee" />
            </Center>
            )
        } else {
            return (
                <SafeAreaView style={styles.container} >
                    <FlatList _dark={{ bg: "blueGray.900" }} _light={{ bg: "blueGray.50" }}
                        style={styles.list}
                        numColumns={2}
                        ListHeaderComponent={<EventGalleryHeader data={this.state.event} />}
                        data={this.state.images}
                        keyExtractor={item => item.imageToken}
                        renderItem={({ item }) => (
                            <LongPressGestureHandler
                                onHandlerStateChange={this.onLongPress}
                                minDurationMs={800}
                            >
                                <Image key={item.imageToken} style={{ marginRight: 2, marginTop: 2, width: '50%', opacity: 1 }} source={{ uri: item.imageUrl }} alt="Alternate Text" size="xl" />
                            </LongPressGestureHandler>
                        )}
                    />
                </SafeAreaView>
            );
        }
    };

}
const styles = StyleSheet.create({
    container: {
        flex: 1,
    },
    image: {
        maxHeight: 450,
        width: '100%',
        height: 200,
        overflow: 'hidden',
    },
    list: {
        alignSelf: 'center',
    },
    gallery: {
        flex: 1,
        width: '100%',
        flexDirection: 'row',

    }
})

这再次表明事先正确阅读 documentation 并在有任何问题时先查看那里是多么重要。

您可以使用以下参数实现我上面提到的行为。

loadingIndicatorSource link

source 类似,此 属性 表示用于呈现图像加载指示器的资源,显示直到图像准备好显示,通常是在从网络下载后。

onLoad link

加载成功完成时调用。

onLoadEnd link

加载成功或失败时调用。

onLoadStart link

加载开始时调用。

示例: onLoadStart={() => this.setState({loading: true})}

1)进程加载时(初始isLoading将为false);显示 activity 指标。 2)然后显示图像。 *。在平面列表中:

{this.state.isLoading ? <ActivityIndicator.../> : (<Image..../>)}