React Native ScrollView不会滚动到底部

时间:2019-02-14 18:13:03

标签: css reactjs react-native hybrid-mobile-app

所以我在这里有一个稍微独特的案例,在弄清flexbox布局时遇到很多麻烦。我基本上有一个固定在顶部的“标头”(“ headerContainer”),然后是位于其下方的ScrollView,它包装了HTMLView容器(https://github.com/jsdf/react-native-htmlview)。

问题是ScrollView不会滚动到HTMLView内容的底部。我曾尝试在HTMLView中添加边距,但是我不得不滚动的额外内容似乎是可变的,因此有时我在滚动的内容和内容之间会有很大的差距。您还将看到,我在HTMLView下方有一个TouchableOpacity,而且距离ScrollView太远了。有关如何更改样式以使其正常工作的任何建议?

const visitWebsiteVersion = (url) => {
    OutOfAppLinking(url)
}
const PostView = (props) => {
    let postTypeName;
    let postIcon;
    switch (props.postType) {
        case 'something1':
            postTypeName = 'something1'
            postIcon = <FontAwesome name={'bell'} size={20} color={gray500} style={styles.iconStyles}/>
            break;
        case 'something2':
            postTypeName = 'Something2'
            postIcon = <FontAwesome name={'newspaper-o'} size={15} color={gray500} style={styles.iconStyles}/>
            break;
        case 'something3':
            postTypeName = 'Something3'
            postIcon = <FontAwesome name={'book'} size={15} color={gray500} style={styles.iconStyles}/>
            break;
        case 'something4':
            postTypeName = 'Something4'
            postIcon = <FontAwesome name={'book'} size={15} color={gray500} style={styles.iconStyles}/>
            break;
        default:
            postTypeName = ''
            postIcon = ''
    }

    return(
        <View style={styles.postContainer}>
            <View style={styles.headerContainer}>
                <View style={styles.headerTopRow}>
                    <View style={{flexDirection: 'row'}}>
                        {postIcon}
                        <Text style={styles.postType}>{postTypeName}</Text>
                    </View>
                    <Text style={styles.postDate}>{monthDayYearConversion(props.postDate)}</Text>
                </View>
                <Text style={styles.postTitle}>{props.title}</Text>
                <View style={styles.headerBottomRow}>
                    <View>
                        <View style={{flexDirection: 'row'}}>
                            <Text style={styles.authorName}>By {props.author.name}</Text>
                        </View>
                        <View style={{flexDirection: 'row'}}>
                            <Text style={styles.subscriptionTitle}>{props.subscription}</Text>
                        </View>
                    </View>
                </View>
            </View>
            <ScrollView
                style={styles.scrollContainer}
                showsVerticalScrollIndicator={false}
            >
                <HTMLView
                    value={props.content}
                    stylesheet={htmlContentStylesheet}
                    style={styles.contentContainer}
                    renderNode={htmlNodeRendering}
                />
                <TouchableOpacity
                    onPress={() => visitWebsiteVersion(props.postLink)}
                    style={{...inContentButton}}
                >
                    <Text style={{fontSize: 15, color: gray100}}>Read Website Version</Text>
                </TouchableOpacity>
            </ScrollView>
        </View>
    )
}

PostView.propTypes = {
    postID: PropTypes.number.isRequired,
    title: PropTypes.string.isRequired,
    excerpt: PropTypes.string,
    content: PropTypes.string.isRequired,
    postDate: PropTypes.string.isRequired,
    author: PropTypes.object.isRequired,
    postType: PropTypes.string.isRequired,
    subscription: PropTypes.string,
    postLink: PropTypes.string.isRequired,
    actionsToTake: PropTypes.oneOfType([
        PropTypes.bool,
        PropTypes.array
    ]).isRequired
}
PostView.defaultProps = {
    actionsToTake: false
}

const styles = StyleSheet.create({
    postContainer: {

    },
    headerTopRow: {
        flexDirection: 'row',
        justifyContent: 'space-between'
    },
    headerBottomRow: {
        flexDirection: 'row',
        marginTop: 15,
        backgroundColor: postHeaderGray,
        marginBottom: -16,
        marginRight: -15,
        marginLeft: -15,
        padding: 15,
        borderColor: gray200,
        borderTopWidth: 2
    },
    headerContainer: {
        borderBottomWidth: 1,
        borderColor: gray100,
        shadowColor: '#000',
        backgroundColor: gray100,
        shadowOffset: { width: 0, height: 2 },
        shadowOpacity: 0.8,
        shadowRadius: 2,
        elevation: 1,
        padding: 15

    },
    scrollContainer: {
        ...htmlContentScrollContainer
    },
    iconStyles: {
        alignSelf: 'flex-start'
    },
    postTitle: {
        ...PostTitle,
        fontSize: 25
    },
    postType: {
        ...MetaTitle,
        marginLeft: 5
    },
    postDate: {
        alignSelf: 'flex-end',
        ...MetaTitle
    },
    authorName: {
        ...MetaTitle,
        flex: 1,
        flexWrap: 'wrap'
    },
    authorImage: {
        width: 75,
        height: 75,
        borderRadius: 35
    },
    subscriptionTitle: {
        ...MetaTitle,
        flexWrap: 'wrap',
        fontWeight: '700'
    },
    // This isn't the best solution but I think it will work for now
    contentContainer: {
        // marginBottom: 600
    }
})

export default PostView

1 个答案:

答案 0 :(得分:0)

好吧,我知道了!他们的关键是对ScrollView使用stickyHeaderIndices属性,然后将所有内容都考虑在内,并且我能够一直滚动到最底端。以下是有效的代码:

const visitWebsiteVersion = (url) => {
    OutOfAppLinking(url)
}
const PostView = (props) => {
    let postTypeName;
    let postIcon;
    switch (props.postType) {
        case 'something1':
            postTypeName = 'Something1'
            postIcon = <FontAwesome name={'bell'} size={20} color={gray500} style={styles.iconStyles}/>
            break;
        case 'something2':
            postTypeName = 'Something2'
            postIcon = <FontAwesome name={'newspaper-o'} size={15} color={gray500} style={styles.iconStyles}/>
            break;
        case 'something3':
            postTypeName = 'Something3'
            postIcon = <FontAwesome name={'book'} size={15} color={gray500} style={styles.iconStyles}/>
            break;
        case 'something4':
            postTypeName = 'Something4'
            postIcon = <FontAwesome name={'book'} size={15} color={gray500} style={styles.iconStyles}/>
            break;
        default:
            postTypeName = ''
            postIcon = ''
    }

    const {actionsToTake, content, postDate, title, author, subscription, postLink} = props
    return(
        <View style={styles.postContainer}>

            <ScrollView
                style={styles.scrollContainer}
                showsVerticalScrollIndicator={false}
                stickyHeaderIndices={[0]}
            >
                <View style={styles.headerContainer}>
                    <View style={styles.headerTopRow}>
                        <View style={{flexDirection: 'row'}}>
                            {postIcon}
                            <Text style={styles.postType}>{postTypeName}</Text>
                        </View>
                        <Text style={styles.postDate}>{monthDayYearConversion(postDate)}</Text>
                    </View>
                    <Text style={styles.postTitle}>{title}</Text>
                    <View style={styles.headerBottomRow}>
                        <View>
                            <View style={{flexDirection: 'row'}}>
                                <Text style={styles.authorName}>By {author.name}</Text>
                            </View>
                            <View style={{flexDirection: 'row'}}>
                                <Text style={styles.subscriptionTitle}>{subscription}</Text>
                            </View>
                        </View>
                    </View>
                </View>
                <View style={{...htmlContentScrollContainer}}>
                    {actionsToTake ?
                        <ActionsToTake actions={actionsToTake}/>
                    :null}
                    <HTMLView
                        value={content}
                        stylesheet={htmlContentStylesheet}
                        style={styles.contentContainer}
                        renderNode={htmlNodeRendering}
                    />
                    <TouchableOpacity
                        onPress={() => visitWebsiteVersion(postLink)}
                        style={{...inContentButton}}
                    >
                        <Text style={{fontSize: 15, color: gray100}}>Read Website Version</Text>
                    </TouchableOpacity>
                </View>
            </ScrollView>
        </View>
    )
}

PostView.propTypes = {
    postID: PropTypes.number.isRequired,
    title: PropTypes.string.isRequired,
    excerpt: PropTypes.string,
    content: PropTypes.string.isRequired,
    postDate: PropTypes.string.isRequired,
    author: PropTypes.object.isRequired,
    postType: PropTypes.string.isRequired,
    subscription: PropTypes.string,
    postLink: PropTypes.string.isRequired,
    actionsToTake: PropTypes.oneOfType([
        PropTypes.bool,
        PropTypes.array
    ]).isRequired
}
PostView.defaultProps = {
    actionsToTake: false
}

const styles = StyleSheet.create({
    postContainer: {

    },
    headerTopRow: {
        flexDirection: 'row',
        justifyContent: 'space-between'
    },
    headerBottomRow: {
        flexDirection: 'row',
        marginTop: 15,
        backgroundColor: postHeaderGray,
        marginBottom: -16,
        marginRight: -15,
        marginLeft: -15,
        padding: 15,
        borderColor: gray200,
        borderTopWidth: 2
    },
    headerContainer: {
        borderBottomWidth: 1,
        borderColor: gray100,
        shadowColor: '#000',
        backgroundColor: gray100,
        shadowOffset: { width: 0, height: 2 },
        shadowOpacity: 0.8,
        shadowRadius: 2,
        elevation: 1,
        padding: 15,
        marginBottom: 15
    },
    scrollContainer: {

    },
    iconStyles: {
        alignSelf: 'flex-start'
    },
    postTitle: {
        ...PostTitle,
        fontSize: 25
    },
    postType: {
        ...MetaTitle,
        marginLeft: 5
    },
    postDate: {
        alignSelf: 'flex-end',
        ...MetaTitle
    },
    authorName: {
        ...MetaTitle,
        flex: 1,
        flexWrap: 'wrap'
    },
    authorImage: {
        width: 75,
        height: 75,
        borderRadius: 35
    },
    subscriptionTitle: {
        ...MetaTitle,
        flexWrap: 'wrap',
        fontWeight: '700'
    },
    // This isn't the best solution but I think it will work for now
    contentContainer: {
        // marginBottom: 600
    }
})

export default PostView