眾所周知: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 智行火車票 智慧出行搜索結果頁。
如果您有更好的處理這類布局的方案,還請不吝賜教!
