从 URL 加载图像时正在加载旋转器

发布于 2025-01-11 09:06:09 字数 6135 浏览 0 评论 0原文

在我的 React Native 应用程序中,我使用图像渲染 。我将直接 imageurl 作为源传递到 组件中。

<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。当图像在视图中完全可见时是否存在“触发”?我想我不能只为每个图像构建一个状态。

将会有数百张图片!

我认为重要的是要知道我从 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',

    }
})

In my React Native applikation I render a <FlatList> with Images. I pass the direct imageurl as source into the <Image> Component.

<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" />    )}    />

This means that the images are loaded in a different order because they are also different sizes. I would like to show a placeholder during loading.

The listAll() function resets isLoading to false before all images are displayed. Is there a 'trigger' when an image is fully visible in the view? I can't just build a single state for each image - I guess.

There will be many hundreds of pictures!

I think it's important to know that I extract the url from the google firestore images and store they as an array in state beforehand. See function getDownloadURL

Fullcode

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',

    }
})

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

热风软妹 2025-01-18 09:06:09

它再次表明正确阅读文档是多么重要如果您有任何疑问,请先查看那里。

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

loadingIndicatorSource link

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

onLoad link

调用时加载成功完成。

onLoadEnd 链接

调用时加载成功或失败。

onLoadStart 链接

调用于加载启动。

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

And again it shows how important it is to read the documentation properly beforehand and to look there first if you have any questions.

You can achieve the behavior I mentioned above with the following parameters.

loadingIndicatorSource link

Similarly to source, this property represents the resource used to render the loading indicator for the image, displayed until image is ready to be displayed, typically after when it got downloaded from network.

onLoad link

Invoked when load completes successfully.

onLoadEnd link

Invoked when load either succeeds or fails.

onLoadStart link

Invoked on load start.

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

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文