如何让一个模态在反应原生的FlatList中工作?

时间:2018-04-03 11:20:41

标签: react-native react-native-flatlist

我正在使用Flatlist来渲染图片列表。我想点击一张单独的图片,然后在一个模态中呈现相同图片的更大版本。我似乎无法找到一种方法来确保模式打开时使用我点击的更大版本的图片。

这是我到目前为止所写的内容。

import React, { Component } from 'react';
import { Text, View, FlatList, 
        Image,
        TouchableOpacity,
        Modal,
        Alert,

} from 'react-native';

class TestPage extends Component {
    constructor() {
        super();
        this.state = {
            albums: [],
            modalIsOpen: false,
            selectedAlbum: { album: null }
        };
    }

    componentWillMount() {
        console.log('component did mount');
        fetch('https://rallycoding.herokuapp.com/api/music_albums')
            .then((response) => response.json())
            .then((responseData) => {
                this.setState({
                    albums: responseData
                });
            });
    }

    selectAlbumPic() {
        console.log('her is the selectAlbumPic thing');
    }
    pictureOpen(item) {
        console.log('here is your item ', item.title);
        this.setState({ 
                modalIsOpen: !this.state.modalIsOpen,
                selectedAlbum: { album: item }
            });
            console.log('here is your state after the fuction', this.state.selectedAlbum.album);
    }

    closeModal(item) {
        //console.log('here is your seleected album', this.state.selectedAlbum.album.title);

        // console.log('close modal is being pressed irght now');
        this.setState({
            modalIsOpen: false,
            selectedAlbum: { album: null }
        });
        // console.log('here is the album data ', item.album);
    }
    singleAlbumRender(item) {        
        const pictureUrl = item.image;

        return this.state.selectedAlbum === { album: null } ?

            <View style={styles.singleAlbum}>
                <TouchableOpacity
                    onPress={() => { 
                        console.log('hey man');
                        console.log('here is your state', this.state.selectedAlbum);
                        this.pictureOpen(item); 
                    }}
                >
                <Image
                    source={{ uri: `${pictureUrl}` }}
                    style={{
                        width: 50,
                        height: 50,
                    }}

                />
                </TouchableOpacity>

            </View>
            :
            <View style={styles.singleAlbum}>
                <TouchableOpacity
                    onPress={() => { 
                        console.log('this is the second batch');
                        this.pictureOpen(item); }}
                >
                <Image
                    source={{ uri: `${pictureUrl}` }}
                    style={{
                        width: 50,
                        height: 50,
                    }}

                />
                </TouchableOpacity>
                <Modal
                    animationType="slide"    
                    onRequestClose={() => {}}
                    visible={this.state.modalIsOpen}
                    transparent={false}
                >
                    <View>

                        <TouchableOpacity
                            onPress={() => { 
                                console.log('this text should close the modal'); 
                                console.log(this.state.selectedAlbum.album.image);
                                this.closeModal(item);
                            }}
                        >
                            <Image
                                style={{
                                    width: 200,
                                    height: 200,
                                }}
                                source={{ uri: `${this.state.selectedAlbum.image}` }}
                            />
                        </TouchableOpacity>
                    </View>
                </Modal>


            </View>;
    }

    renderAlbumList() {
        return (<FlatList
                    data={this.state.albums}
                    renderItem={({ item }) => {                        
                        return (
                            this.singleAlbumRender(item)
                            //<Image
                            // style={{
                            //     width: 50,
                            //     height: 50,
                            // }}
                            //source={{ uri: `${pictureStuff}` }}
                        // />
                    );
                    }}
                    keyExtractor={(item) => item.title}
                    extraData={this.state.selectedAlbum}
        />);
    }
    render() {
        return (
            <View style={styles.mainContainer}>
                <View style={styles.viewOne}>
                    {this.renderAlbumList()}
                </View>
            </View>
        );
    }
}

const styles = {
    mainContainer: {
        flex: 1,
        //backgroundColor: 'blue',
        justifyContent: 'center',
        alignItems: 'center',
    },
    viewOne: {
        // backgroundColor: 'green',
    },
    singleAlbum: {
        backgroundColor: 'yellow',
    }
};

export default TestPage;

2 个答案:

答案 0 :(得分:1)

这是我想要的代码。我选择将所有内容保存在一个组件中。

import React, { Component } from 'react';
import { Text, View, FlatList, 
        Image,
        TouchableOpacity,
        Modal,
        Alert,

} from 'react-native';

class TestPage extends Component {
    constructor() {
        super();
        this.state = {
            albums: [],
            modalIsOpen: false,
            selectedAlbum: null
        };
    }

    componentWillMount() {
        console.log('component did mount');
        fetch('https://rallycoding.herokuapp.com/api/music_albums')
            .then((response) => response.json())
            .then((responseData) => {
                this.setState({
                    albums: responseData,
                    isLoaded: true,
                });
            });
    }

    pictureOpen(item) {
        this.setState({ 
                modalIsOpen: !this.state.modalIsOpen,
                selectedAlbum: item
            });
    }

    closeModal(item) {
        this.setState({
            modalIsOpen: false,
            selectedAlbum: { album: null }
        });
        console.log('here is the album data ', item.image);
    }
    singleAlbumRender(item) {        
        const pictureUrl = item.image;

        return this.state.selectedAlbum === null ?
            <TouchableOpacity
                    onPress={() => { 
                        console.log('hey man no button pressed yet');
                        console.log('here is your state', this.state.selectedAlbum);
                        this.pictureOpen(item); 
                    }}
            >
                <Image
                    source={{ uri: `${pictureUrl}` }}
                    style={{
                        width: 50,
                        height: 50,
                    }}

                />
                </TouchableOpacity>


            : 
            <View style={styles.singleAlbum}>
                <TouchableOpacity
                    onPress={() => { 
                        console.log('hey man first');
                        console.log('here is your state', this.state.selectedAlbum);
                        this.pictureOpen(item); 
                    }}
                >
                <Image
                    source={{ uri: pictureUrl }}
                    style={{
                        width: 50,
                        height: 50,
                    }}

                />
                </TouchableOpacity>
            </View>;
    }

    renderAlbumList() {
        return (<FlatList
                    data={this.state.albums}
                    renderItem={({ item }) => {                        
                        return (
                            this.singleAlbumRender(item)
                            //<Image
                            // style={{
                            //     width: 50,
                            //     height: 50,
                            // }}
                            //source={{ uri: `${pictureStuff}` }}
                        // />
                    );
                    }}
                    keyExtractor={(item) => item.title}
                    extraData={this.state.selectedAlbum}
        />);
    }
    render() {
        return (
            <View style={styles.mainContainer}>
                <View style={styles.viewOne}>
                    {this.renderAlbumList()}
                </View>

                <Modal
                animationType="slide"    
                onRequestClose={() => {}}
                visible={this.state.modalIsOpen}
                transparent
                >
                    <View>

                        <TouchableOpacity
                            onPress={() => { 
                                const selectItem = this.state.selectedAlbum;
                                console.log('this text should close the modal'); 
                                this.closeModal(selectItem);
                            }}
                        >
                            <Image
                                style={{
                                    width: 200,
                                    height: 200,
                                }}
                                source={this.state.selectedAlbum === null 
                                    ? null
                                    : { uri: this.state.selectedAlbum.image }}
                            />
                        </TouchableOpacity>
                    </View>
                </Modal> 
            </View>
        );
    }
}

const styles = {
    mainContainer: {
        flex: 1,
        //backgroundColor: 'blue',
        justifyContent: 'center',
        alignItems: 'center',
    },
    viewOne: {
        // backgroundColor: 'green',
    },
    singleAlbum: {
        backgroundColor: 'yellow',
    }
};

export default TestPage;

答案 1 :(得分:0)

首先,我建议您为相册创建一个新组件,这样可以使代码更简单,更干净,在这个新组件中使用模态。

import React, { Component } from 'react';
import { Text, View, Image, TouchableOpacity, Modal, StyleSheet } from 'react-native';

class ImageModal extends Component {
    constructor(props){
        super(props);
        this.state = {
           modalIsOpen: false
        }
    }
    handleModal = () => {
        this.setState({
            modalIsOpen: !this.state.modalIsOpen,
        });
    }
    render() {
        return (
            <View> 
                <View style={styles.singleAlbum}>
                    <TouchableOpacity
                        onPress={this.handleModal()}
                    >
                        <Image
                            source={{ uri: `${this.state.selectedAlbum}` }}
                            style={{
                                width: 50,
                                height: 50,
                            }}
                        />
                    </TouchableOpacity>
                </View>
                <Modal
                    animationType="slide"    
                    onRequestClose={() => {}}
                    visible={this.state.modalIsOpen}
                    transparent={false}
                >
                    <View>
                        <TouchableOpacity
                            onPress={this.handleModal()}
                        >
                            <Image
                                style={{
                                    width: 200,
                                    height: 200,
                                }}
                                source={{ uri: `${this.props.album.image}` }}
                            />
                        </TouchableOpacity>
                    </View>
                </Modal>
            </View>
        );
    }
}

const styles = StyleSheet.create({
    ...
});

export default ImageModal;

然后在main中你需要渲染这个新组件。

import React, { Component } from 'react';
import { View, FlatList, StyleSheet } from 'react-native';
import ImageModal from './ImageModal';

class TestPage extends Component {
    constructor() {
        super();
        this.state = {
            albums: [],
            isLoad: false
        };
    }
    componentWillMount() {
        console.log('component did mount');
        fetch('https://rallycoding.herokuapp.com/api/music_albums')
            .then((response) => response.json())
            .then((responseData) => {
                this.setState({
                    albums: responseData, isLoad: true
                });
            });
    }
    singleAlbumRender(item) {        
        return (
            <ImageModal album={item}/>
        )
    }
    render() {
        return (
            <View style={styles.mainContainer}>
                <View style={styles.viewOne}>
                    {this.state.isLoad ? 
                        <FlatList
                            data={this.state.albums}
                            renderItem={(item) => this.singleAlbumRender(item) }
                            keyExtractor={(item) => item.title}
                        /> : null }
                </View>
            </View>
        );
    }
}

const styles = StyleSheet.create({
    ...
});

export default TestPage;