简体   繁体   中英

Dismissible & extendable scroll view in React Native

I am looking for a way to achieve the effect shown below in React Native. I have already achieved the navigation bar and tab bar setup using React Navigation.

Now comes the part when I integrate a scroll like the one shown below. Effectively there is a view with lots of rows in it. I tried setting this up in a view wrapped in a ScrollView but this is too simplistic as the view just remains fixed on the screen and I'm looking to move the map with the view.

I'm looking for pseudocode if anything. Can anyone with experience in React Native suggest a good layout to achieve this effect?

在此处输入图片说明

I had a bit of fun with this. We could achieve the same effect by just creating a simple overlay on your map to display your list of services. The state of the overlay would be rendered visible from a callback on a button and rendered invisible by the 'refresh' or pull-down from an encapsulating <ScrollView /> .

Here's what this component renders:

工作正常!工作正常!

Here's the component class:

import React, { Component } from 'react';
import {
  Text,
  View,
  TouchableOpacity,
  StyleSheet,
  ScrollView,
  FlatList,
  Dimensions,
  RefreshControl
} from 'react-native';

export default class SO_MapOverlay extends Component {

    constructor(props) {
        super(props)
        this.state = {
            // Simple state variable to hide and show service list
            serviceListVisible: false,
            refreshing: false,
            data: [
                { key: 'item1' },
                { key: 'item2' },
                { key: 'item3' },
                { key: 'item4' },
                { key: 'item5' },
                { key: 'item6' },
                { key: 'item7' },
                { key: 'item8' }
            ],
        }
    }

    // Simply hides the button and shows the list overlay
    showRouteOverview() {
        this.setState({ serviceListVisible: true });
    }

    // Reverses showRouteOverview() when the user pulls down
    onRefresh() {
        this.setState({ refreshing: true });
        this.setState({ serviceListVisible: false });
        this.setState({ refreshing: false });
    }

    // Indicate the offset you want from the BOTTOM of the page
    renderSpacer(offset) {
        const { height } = Dimensions.get('window');
        const spacerOffset = height - parseInt(offset);
        return (
            <View style={{ height: spacerOffset, backgroundColor: 'transparent' }} />
        )
    }

    // Just renders each item in your flat list
    renderItem(itemData) {
        return(
            <View style={[styles.item]}>
                <Text style={{ color: 'black'}}>{itemData.item.key}</Text>
            </View>
        )
    }

    renderRefreshControl() {
        return (
            <RefreshControl
        refreshing={this.state.refreshing}
        onRefresh={this.onRefresh.bind(this)}
        // Note: I'm just hiding the activity monitor with these paramteres
          color='transparent'
          tintColor='transparent'
          />
        )
    }

    render() {
        const { serviceListVisible } = this.state;
        const listHeight = 56 * this.state.data.length;
        return (
          <View style={styles.container}>
            <View style={styles.mapContainer}>
                <Text style={{color: 'white'}}>I am map.</Text>
                <TouchableOpacity
                    style={[styles.showRouteOverviewButton, serviceListVisible ? styles.invisible : null]}
                    onPress={() => { this.showRouteOverview() }}>
                    <Text>Show Services</Text>
                </TouchableOpacity>
              </View>
              <ScrollView
                style={[styles.listContainer, serviceListVisible ? styles.visible : null ]}
                refreshControl={ this.renderRefreshControl() }>
                { this.renderSpacer(100) }
                <FlatList
                    style={[styles.list, { height: listHeight }]}
                    data={this.state.data}
                    renderItem={(itemData) => this.renderItem(itemData)}
                    keyExtractor={(item, index) => index}
                    scrollEnabled={false}
                    />
            </ScrollView>
          </View>
        );
    }
}

const styles = StyleSheet.create({
    container: {
        flex: 1,
    },
    visible: {
        display: 'flex'
    },
    invisible: {
        display: 'none'
    },
    mapContainer: {
        flex: 1,
        alignItems: 'center',
        justifyContent: 'center',
        backgroundColor: 'gray',
        position: 'absolute',
        bottom: 0,
        right: 0,
        left: 0,
        top: 0,
    },
    showRouteOverviewButton: {
        position: 'absolute',
        bottom: 40,
        backgroundColor: 'white',
        paddingHorizontal: 20,
        paddingVertical: 10,
    },
    listContainer: {
        display: 'none',
        flex: 1,
    },
    list: {
        backgroundColor: 'red'
    },
    item: {
        alignItems: 'center',
        justifyContent: 'center',
        flex: 1,
        padding: 20,
        backgroundColor: 'white',
    }
});

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM