【问题标题】:React-Native: Listview not scrolling to bottom of screen in IOS onlyReact-Native:Listview 仅在 IOS 中不滚动到屏幕底部
【发布时间】:2018-06-05 11:45:29
【问题描述】:

ListView 滚动在 Android 上运行完美,但在 IOS 上,当我尝试从屏幕底部向下滚动时,它无法识别触摸并且在从 listView 顶部滚动时无法向下滚动。下面是代码sn-p。

render()
{
    return(
        <View style={styles.MainContainerViewCamp}>
            <View>
                <View>
                    <TextInput />
                </View>
                <View>
                    <TouchableOpacity>
                    </TouchableOpacity>
                </View>
            </View>
            <View style = {{ flex:1 }}>
                <ScrollView horizontal={true}>
                    <ListView
                        ...
                        renderRow {(rowData) =>
                            <View style={{ flex: 1, flexDirection: 'row' }}>
                            </View>
                        }
                    />
                </ScrollView>
            </View>
        </View> 
    );
}

const styles = StyleSheet.create({

    MainContainerViewCamp: 
    {
        justifyContent: 'center',
        flex: 1,
        paddingTop: (Platform.OS === 'ios') ? 20 : 20,
        padding: 5,
    },

 });

我已将 {flex:1} 应用于根视图和所有其他可能的解决方案,例如将 {flex:1} 或 {height} 添加到 listView/ScrollView。但没有任何工作。请帮忙。

已编辑:我正在添加整个代码以便更好地理解。还要知道我的数据源有 200 多个条目。

    import React, { Component } from 'react';

    import { AppRegistry, StyleSheet, TextInput,Keyboard,TouchableWithoutFeedback, ActivityIndicator, Switch, ListView, Text, View, 
    Alert, Platform, TouchableHighlight, Image, TouchableOpacity, ScrollView} from 'react-native';

    import FontAwesomeIcon from 'react-native-vector-icons/FontAwesome';
    import MaterialIcon from 'react-native-vector-icons/MaterialIcons';
    import EntypoIcon from 'react-native-vector-icons/Entypo';
    import FoundationIcon from 'react-native-vector-icons/Foundation';

    import { StackNavigator } from 'react-navigation';

    //import { add_campaign } from './add_campaign';

    class view_camp extends Component {


    static navigationOptions = {
        title: 'View Campaigns',
        headerLeft : null,
    };

    listViewRef;

    constructor(props) {
        super(props);
        this.state = {
        isLoading: true,
        text: '',
        stat: '',
        isPopupMenu : false,
        menu_camp_id : '',
        menu_status : '',
        menu_camp_name : '',
        enableScrollViewScroll : true,
        }
        this.setEnableScrollViewScroll = this.setEnableScrollViewScroll.bind(this);
        this.onStartShouldSetResponderCapture = this.onStartShouldSetResponderCapture.bind(this);
        this.arrayholder = [];
    }

    setEnableScrollViewScroll(value) {
        // we need to manually handle the ScrollView scrollEnabled to allow child ListView to scroll in there parent
        this.setState({ enableScrollViewScroll: value });
    }

    onStartShouldSetResponderCapture() {
        // when there is scroll in the result list - we set the parent's ScrollView scrollEnabled to false
        // so the child ListView can handle the scroll events
        this.props.setEnableScrollViewScroll(false);

        // if the scroll is out of the ListView we reset the parent's ScrollView scrollEnabled to true
        if (this.listViewRef.scrollProperties.offset === 0 && this.state.enableScrollViewScroll === false) {
        this.setEnableScrollViewScroll(true);
        }
    }



    componentDidMount() { 
        const base64 = require('base-64');
        return fetch('APIURL', {
        method: 'GET',
        headers: {
            'Accept': 'application/json',
            'Content-Type': 'application/json',
            "Authorization": "Basic " + base64.encode("demo:QZMW]C")
        }
        }).then((response) => response.json())
        .then((responseJson) => { 
            let ds = new ListView.DataSource({ rowHasChanged: (r1, r2) => r1 !== r2 });
            this.setState({
            isLoading: false,
            dataSource: ds.cloneWithRows(responseJson),
            }, function () {
            this.arrayholder = responseJson;
            });
        })
        .catch((error) => {
            console.error(error);
        });
    }

    _onSearchFilterFunction(text) {
        const newData = this.arrayholder.filter(function (item) {
        const itemData = item.Ad_name.toUpperCase()
        const textData = text.toUpperCase()
        return itemData.indexOf(textData) > -1
        })
        this.setState({
        dataSource: this.state.dataSource.cloneWithRows(newData),
        text: text
        })
    }

    _onPressButton = () => {
        this.props.navigation.navigate('Third', { ClientId: this.props.navigation.state.params.ClientId });
    }


    ListViewItemSeparator = () => {
        return (
        <View
            style={{
            height: .5,
            width: "100%",
            backgroundColor: "#000",

            }}
        />
        );
    }

    RenderListViewHeader = () => {

        var header = (

        <View style={{ flex: 1, flexDirection: 'row' }} >
            <ScrollView horizontal={true}>

            <Text style={styles.stickyTextViewContainer} >Ad Name</Text>

            <Text style={styles.stickyTextViewContainer} >Ad Type</Text>

            <Text style={styles.stickyTextViewContainer} >CPR</Text>

            <Text style={styles.stickyTextViewContainer} >CPM</Text>

            <Text style={styles.stickyTextViewContainer} >Budget</Text>

            <Text style={styles.stickyTextViewContainer} >Daily Budget</Text>

            <Text style={styles.stickyTextViewContainer} >Total Budget Spent</Text>

            <Text style={styles.stickyTextViewContainer} >Imps</Text>

            <Text style={styles.stickyTextViewContainer} >Recalls</Text>

            <Text style={styles.stickyTextViewContainer} >Correct Recalls</Text>

            <Text style={styles.stickyTextViewContainer} >Clicks</Text>

            <Text style={styles.stickyTextViewContainer} >Start Date</Text>

            <Text style={styles.stickyTextViewContainer} >End Date</Text>

            <Text style={styles.stickyTextViewContainer} >Status</Text>

            {/* <Text style={styles.stickyActionTextViewContainer} >Action</Text> */}

            </ScrollView>
        </View>

        );

        return header;
    };

    getMenuParams = (camp_id,status,camp_name) => 
    {
        //console.log("camp_id: "+camp_id +" status: "+status+" camp_name: "+camp_name);
        this.setState({
        isPopupMenu : true,
        menu_camp_id : camp_id,
        menu_status : status,
        menu_camp_name : camp_name
        });
        //console.log("ispopupmenu: "+this.state.isPopupMenu+" menu_camp_id: "+this.state.menu_camp_id +" menu_status: "+this.state.menu_status+" menu_camp_name: "+this.state.menu_camp_name);
    }  

    toggleCancel = () => 
    { 
        this.setState({
        isPopupMenu:false,
        });
    }

    setMenuRef = ref => { 
        this._menu = ref;
        this.showMenu();
    };

    hideMenu = () => {
        this._menu.hide();
    };

    showMenu = () => { //console.log("start");
        this._menu.show();
        //console.log("end");
    };

    render() {
        const { navigate } = this.props.navigation;
        //const screenHeight = Dimensions.get('window').height;
        if (this.state.isLoading) {
        return (
            <View style={{ flex: 1, paddingTop: 20 }}>
            <ActivityIndicator />
            </View>
        );
        }

        return (
        <View style={styles.MainContainerViewCamp} 
         // when scrolling the parent scroll view we reset the enableScroll to true
            onStartShouldSetResponderCapture={() =>{this.setEnableScrollViewScroll(true);}}
            >

            <Text style={{ padding: 5, fontSize: 35, backgroundColor: '#00BCD4' }}>All Campaigns</Text>
            <View style={styles.OuterSectionStyle}>
            <View style={styles.SectionStyle}>
                <FontAwesomeIcon name='search' style={styles.icon} />
                <TextInput
                onChangeText={(text) => this._onSearchFilterFunction(text)}
                value={this.state.text}
                style={{ flex: 1 }}
                placeholder="Search Here"
                underlineColorAndroid="transparent"
                />
            </View>
            <TouchableOpacity
                style={styles.SubmitButtonStyle}
                activeOpacity={.5}
                onPress={this._onPressButton}>
                <MaterialIcon name='add-box' style={styles.icon} />
            </TouchableOpacity>

            </View>

            <ScrollView horizontal={true} 
            // enable ScrollView scroll according to state's value
            scrollEnabled = {this.state.enableScrollViewScroll} 
            >

            <ListView

                onRef={(ref) => this.listViewRef = ref}

                onStartShouldSetResponderCapture={this.onStartShouldSetResponderCapture}

                enableEmptySections={true}

                dataSource={this.state.dataSource}

                stickyHeaderIndices={[0]}

                renderHeader={this.RenderListViewHeader}

                renderSeparator={this.ListViewItemSeparator}

                renderRow={(rowData) =>

                <View style={{ flex: 1, flexDirection: 'row'}}>

                    <TouchableOpacity
                        //style={styles.showMenuContainer}
                        activeOpacity={.5}
                        onPress={this.getMenuParams.bind(this,rowData.campaign_id,rowData.Status,rowData.Ad_name)}
                    >
                    <Text style={styles.textViewContainer}> {rowData.Ad_name} </Text>
                    </TouchableOpacity>


                    {/* <Text style={styles.textViewContainer} >{rowData.Ad_name}</Text> */}

                    <TouchableOpacity
                        //style={styles.showMenuContainer}
                        activeOpacity={.5}
                        onPress={this.getMenuParams.bind(this,rowData.campaign_id,rowData.Status,rowData.Ad_name)}
                    >
                    <Text style={styles.textViewContainer} >{rowData.Ad_type}</Text>
                    </TouchableOpacity>

                    <TouchableOpacity
                        //style={styles.showMenuContainer}
                        activeOpacity={.5}
                        onPress={this.getMenuParams.bind(this,rowData.campaign_id,rowData.Status,rowData.Ad_name)}
                    >
                    <Text style={styles.textViewContainer} >{rowData.CPR}</Text>
                    </TouchableOpacity>

                    <TouchableOpacity
                        //style={styles.showMenuContainer}
                        activeOpacity={.5}
                        onPress={this.getMenuParams.bind(this,rowData.campaign_id,rowData.Status,rowData.Ad_name)}
                    >
                    <Text style={styles.textViewContainer} >{rowData.CPM}</Text>
                    </TouchableOpacity>

                    <TouchableOpacity
                        //style={styles.showMenuContainer}
                        activeOpacity={.5}
                        onPress={this.getMenuParams.bind(this,rowData.campaign_id,rowData.Status,rowData.Ad_name)}
                    >
                    <Text style={styles.textViewContainer} >{rowData.Budget}</Text>
                    </TouchableOpacity>

                    <TouchableOpacity
                        //style={styles.showMenuContainer}
                        activeOpacity={.5}
                        onPress={this.getMenuParams.bind(this,rowData.campaign_id,rowData.Status,rowData.Ad_name)}
                    >
                    <Text style={styles.textViewContainer} >{rowData.Daily_budget}</Text>
                    </TouchableOpacity>

                    <TouchableOpacity
                        //style={styles.showMenuContainer}
                        activeOpacity={.5}
                        onPress={this.getMenuParams.bind(this,rowData.campaign_id,rowData.Status,rowData.Ad_name)}
                    >
                    <Text style={styles.textViewContainer} >{rowData.Total_budget_spent}</Text>
                    </TouchableOpacity>

                    <TouchableOpacity
                        //style={styles.showMenuContainer}
                        activeOpacity={.5}
                        onPress={this.getMenuParams.bind(this,rowData.campaign_id,rowData.Status,rowData.Ad_name)}
                    >
                    <Text style={styles.textViewContainer} >{rowData.Imps}</Text>
                    </TouchableOpacity>

                    <TouchableOpacity
                        //style={styles.showMenuContainer}
                        activeOpacity={.5}
                        onPress={this.getMenuParams.bind(this,rowData.campaign_id,rowData.Status,rowData.Ad_name)}
                    >
                    <Text style={styles.textViewContainer} >{rowData.Recalls}</Text>
                    </TouchableOpacity>

                    <TouchableOpacity
                        //style={styles.showMenuContainer}
                        activeOpacity={.5}
                        onPress={this.getMenuParams.bind(this,rowData.campaign_id,rowData.Status,rowData.Ad_name)}
                    >
                    <Text style={styles.textViewContainer} >{rowData.Correct_recalls}</Text>
                    </TouchableOpacity>

                    <TouchableOpacity
                        //style={styles.showMenuContainer}
                        activeOpacity={.5}
                        onPress={this.getMenuParams.bind(this,rowData.campaign_id,rowData.Status,rowData.Ad_name)}
                    >                
                    <Text style={styles.textViewContainer} >{rowData.Clicks}</Text>
                    </TouchableOpacity>

                    <TouchableOpacity
                        //style={styles.showMenuContainer}
                        activeOpacity={.5}
                        onPress={this.getMenuParams.bind(this,rowData.campaign_id,rowData.Status,rowData.Ad_name)}
                    >
                    <Text style={styles.textViewContainer} >{rowData.Start_date}</Text>
                    </TouchableOpacity>

                    <TouchableOpacity
                        //style={styles.showMenuContainer}
                        activeOpacity={.5}
                        onPress={this.getMenuParams.bind(this,rowData.campaign_id,rowData.Status,rowData.Ad_name)}
                    >
                    <Text style={styles.textViewContainer} >{rowData.End_date}</Text>
                    </TouchableOpacity>

                    {rowData.Status == '0' ?
                    <View style={styles.SwitchOuterSectionStyle}>
                        <Text style={styles.textWithSwitch}>
                        Inactive </Text>
                        <Switch
                        onValueChange={this.onStatusButtonPressed.bind(this, rowData.Status, rowData.campaign_id)}
                        value={false} />
                    </View>

                    :
                    <View style={styles.SwitchOuterSectionStyle}>
                        <Text style={styles.textWithSwitch}>
                        Active </Text>
                        <Switch
                        onValueChange={this.onStatusButtonPressed.bind(this, rowData.Status, rowData.campaign_id)}
                        value={true} />
                    </View>}
                    </View>
                }
            />
            </ScrollView>
            </View>
            </View>



        );
    }
    }

    const styles = StyleSheet.create({

    MainContainerViewCamp: {

        // Setting up View inside content in Vertically center.
        justifyContent: 'center',
        flex: 1,
        paddingTop: (Platform.OS === 'ios') ? 20 : 20,
        padding: 5,
    },

    textViewContainer: {

        textAlignVertical: 'center',
        padding: 7,
        borderWidth: 1,
        borderColor: '#87ceeb',
        fontSize: 13,
        width: 150,
    },
    stickyTextViewContainer: {

        textAlignVertical: 'center',
        fontSize: 17,
        fontWeight: 'bold',
        padding: 7,
        height: 45,
        backgroundColor: '#00BFFF',
        borderWidth: 1,
        borderColor: '#87ceeb',
        fontSize: 13,
        width: 150,
        marginBottom: 3,
    },

    stickyActionTextViewContainer: {

        textAlignVertical: 'center',
        textAlign: 'center',
        fontSize: 17,
        fontWeight: 'bold',
        padding: 7,
        justifyContent: 'center',
        alignItems: 'center',
        height: 45,
        backgroundColor: '#00BFFF',
        borderWidth: 1,
        borderColor: '#87ceeb',
        fontSize: 13,
        width: 550,
    },
    textWithSwitch: {

        fontSize: 13,
    },
    imageClass: {
        height: 40,
        width: 40,
        marginLeft: 25,
        borderRadius: 7,
    },
    SubmitButtonStyle: {

        marginTop: 10,
        marginLeft: 10,
        marginBottom: 5,
        backgroundColor: '#D6EAF8',
        borderRadius: 10,
        borderWidth: 1,
        borderColor: '#fff'
    },

    TextStyle: {
        color: '#fff',
        textAlign: 'center',
    },

    icon: {
        fontSize: 30,
        padding: 5
    },
    TextInputStyleClass: {

        textAlign: 'center',
        height: 40,
        borderWidth: 1,
        borderColor: '#009688',
        borderRadius: 7,
        backgroundColor: "#FFFFFF"

    },
        OuterSectionStyle: {
        flexWrap: 'wrap',
        alignItems: 'flex-start',
        flexDirection: 'row',
        margin: 10,
        height: 50,

        },
    SwitchOuterSectionStyle: {
        flexWrap: 'wrap',
        padding: 7,
        alignItems: 'center',
        flexDirection: 'row',
        justifyContent: 'center',
        width: 150,
        borderWidth: 1,
        borderColor: '#87ceeb',
    },
    IconOuterSectionStyle: {
        flexWrap: 'wrap',
        padding: 7,
        alignItems: 'flex-start',
        flexDirection: 'row',
        justifyContent: 'center',
        width: 550,
        borderWidth: 1,
        borderColor: '#87ceeb',
    },
    SectionStyle: {
        flexDirection: 'row',
        justifyContent: 'center',
        alignItems: 'center',
        backgroundColor: '#fff',
        borderWidth: .5,
        borderColor: '#000',
        height: 40,
        width: 220,
        borderRadius: 5,
        margin: 10
    },
    });

    module.exports = view_camp;

【问题讨论】:

    标签: android listview react-native scrollview react-native-ios


    【解决方案1】:

    根据这个React Native issue,ListView 可能没有滚动。

    以下内容在 IOS 和 Android 上都运行良好,如果触摸在 List 上,则滚动 ListView,否则滚动 ScrollView。

    尝试如下更改您的代码:

    class MainContainerViewCamp extends React.Component {
    
      listViewRef; // hold list view reference 
    
      constructor() {
        this.state={ enableScrollViewScroll: true};
    
        this.setEnableScrollViewScroll = this.setEnableScrollViewScroll.bind(this);
        this.onStartShouldSetResponderCapture = this.onStartShouldSetResponderCapture.bind(this);
      }
    
      setEnableScrollViewScroll(value) {
        // we need to manually handle the ScrollView scrollEnabled to allow child ListView to scroll in there parent
        this.setState({ enableScrollViewScroll: value });
      }
    
      onStartShouldSetResponderCapture() {
        // when there is scroll in the result list - we set the parent's ScrollView scrollEnabled to false
        // so the child ListView can handle the scroll events
        this.props.setEnableScrollViewScroll(false);
    
        // if the scroll is out of the ListView we reset the parent's ScrollView scrollEnabled to true
        if (this.listViewRef.scrollProperties.offset === 0 && this.state.enableScrollViewScroll === false) {
          this.setEnableScrollViewScroll(true);
        }
      }
    
      render() {
        ...
        <View style = {{ flex:1 }}
           // when scrolling the parent scroll view we reset the enableScroll to true
           onStartShouldSetResponderCapture={() =>{this.setEnableScrollViewScroll(true);}>
           <ScrollView
             horizontal={true}
             // enable ScrollView scroll according to state's value
             scrollEnabled={this.state.enableScrollViewScroll}
             >
             <ListView
               ...
               onRef={(ref) => this.listViewRef = ref}
               onStartShouldSetResponderCapture={this.onStartShouldSetResponderCapture}
               renderRow {(rowData) =>
                 <View style={{ flex: 1, flexDirection: 'row' }}>
                    </View>
               }
              />
          </ScrollView>
        </View>
        ...
      }
    }
    

    【讨论】:

    • 仍然无法在 IOS 上运行。问题是如果我从 listview 的下半部分向下滚动它不起作用,但如果我从 listview 的上半部分向下滚动它会向下滚动。
    猜你喜欢
    • 2022-11-17
    • 2013-01-23
    • 2018-12-06
    • 1970-01-01
    • 2013-09-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-02-20
    相关资源
    最近更新 更多