React Native中ScorllView嵌套的处理。
众所周知:FlatList 是基于 ScrollView 封装的,底层都是 VirtualizedList 组件。安卓端是有提示的:ScrollView和FlatList是禁止嵌套的。
先上布局,最终做出来的显示页面如下:
简单分析下布局:整个页面是可以下拉刷新的,日历是吸顶的一个横向可滚动的FlatList,下面内容区域:左侧是可滚动的列表,右侧也是可滚动的列表。右侧滚动下拉时,如果是触顶了,也可以触发整个页面的下拉刷新。右侧列表的顶部又是一小块可横向滚动的标签列表。
刚接到这个稿子是崩溃的,试了很多方案都不行,特别是在安卓机器上,低端安卓机上挺让人崩溃的。此处忽略尝试过的N种方案(尝试过很多用定位的方案)
本方案的核心绊脚石是页面的下拉刷新,难就难在这,由于它的存在,导致了滚动容器必须内外嵌套。
直接说下最终的处理方案:安卓上实在是难以兼容各种低端机型,下拉刷新直接放右上角点击刷新(有点蠢),ios上的布局处理,页面最外层用的是ScrollView,内部左侧和右侧都是用的ScrollView组件。
页面最外层的scrollEnabled 通过变量来控制,当内部左侧或者右侧滚动容器触顶的时候,把变量开关打开,则外侧容易可滚动,下拉结束之后立刻关闭变量。
<ScrollView scrollEnabled={flatListScrollEnable} bounces={true} alwaysBounceVertical={false} style={styles.flatWrap} refreshControl={<ZTRefreshControl ref={ref => this.innerModel._refreshControl = ref} refreshing={isRefreshing} onRefresh={() => { this.onRefresh() }} stateLabelColor={'#fff'} loadingStyleName={"white"} />} showsVerticalScrollIndicator={false} keyExtractor={(item, index) => index.toString()} stickyHeaderIndices={[0]} scrollEventThrottle={1} onMomentumScrollEnd={(event) => { if (flatListScrollEnable) { setState({ flatListScrollEnable: false }) } }} > {/* 左侧列表 */} <ScrollView bounces={isIos} onScroll={() => { Animated.event( [{}], { listener: (event) => { const yOffset = event?.nativeEvent?.contentOffset?.y; if (yOffset <= 1) { if (!flatListScrollEnable) { scrollEnable() } } else { if (flatListScrollEnable) { scrollInhibit() } } } }) }} style={styles.scrollWrap} showsVerticalScrollIndicator={false} > {/* 内容列表 */} </ScrollView > {/* 右侧也如此 */} <ScrollView bounces={isIos} onScroll={() => { Animated.event( [{}], { listener: (event) => { const yOffset = event?.nativeEvent?.contentOffset?.y; if (yOffset <= 1) { if (!flatListScrollEnable) { scrollEnable() } } else { if (flatListScrollEnable) { scrollInhibit() } } } }) }} style={styles.scrollWrap} showsVerticalScrollIndicator={false} > {/* 内容列表 */} </ScrollView > </ScrollView>
也曾尝试过通过监听手势来处理,但是触顶之后的弹性根本不会触发手势响应。很是令人头疼,以上方案也是自己琢磨尝试出来的结果。
该页面为 ios app 智行火车票 智慧出行搜索结果页。
如果您有更好的处理这类布局的方案,还请不吝赐教!