如圖所示,總體爲 FlatList
,頂部分類欄吸頂,底部爲 feed
流。要實現下拉商品列表到底後,繼續下拉,自動切換到一下個分類的效果。react
代碼層面,能夠在 FlatList
的 onScrollEndDrag
中添加自動 Tab 切換函數,藉助 FlatList
實例的內容區高度 contentLength
,滑動偏移量 offset
和可視區高度 visibleLength
三者關係,實現下拉自動切換Tab功能。android
//頁面佈局相關 <FlatList data = {[{banner:[]},{tab:[]},{goodList:[]}]} renderItem={this.renderItem} stickyHeaderIndices={(Platform.OS !== 'web')?[1]:null} ListFooterComponent={this._renderFooter} onScroll={this._onScroll} //滑動監聽 ref={this._setScrollRef} keyExtractor = {(item, index) => { `hScrollView-${index}` }} refreshing={this.state.isRefreshing} onRefresh={this._onRefresh.bind(this)} //下拉刷新 getItemLayout={(data, index) => ( {length: 305, offset: 305 * index, index} )} onScrollEndDrag = {()=>{ //滑動到底監聽函數 if(Platform.OS != 'web'){ this._onScrollEndDragFun(); } }} /> /** * 獲取flatList 實例 * @param ref * @private */ _setScrollRef = (ref) => { this._secondGoodFlatListRef = ref; };
import isEmpty from "lodash/isEmpty"; import {Platform} from "react-native"; import {JDDevice} from "@jdreact/jdreact-core-lib"; /** * 底部列表頁滑動事件 實現上拉切換品類功能 * @param e * @private */ _onScrollEndDragFun = (e) => { let scrollMetrics = (this._secondGoodFlatListRef && this._secondGoodFlatListRef._listRef && this._secondGoodFlatListRef._listRef._scrollMetrics) || null; let {contentLength = 0, offset = 0, visibleLength = 0} = scrollMetrics; // console.log('===scrollMetrics',scrollMetrics); // //判斷是否最後一Tab 若是是就不卻換下個目錄 // console.log('===this.props',this.props); // console.log('===this.state',this.state); if (contentLength && offset && visibleLength) { let {selectedIndex = 0} = this.state; //當前選中的三級分類index let {tabListData = []} = this.props; if (!isEmpty(tabListData) && (selectedIndex + 1) < tabListData.length) { //排除最後一個分類 let item = tabListData[selectedIndex + 1]; if (Platform.OS === 'ios') { //IOS 系統存在彈性上拉 if (offset + visibleLength > contentLength + JDDevice.getRpx(100)) { this._secondGoodFlatListRef.scrollToIndex({ animated: false, index: 0, viewOffset: 1, viewPosition: 0 }); this.ItemCategory._clickCategoryTab2 && this.ItemCategory._clickCategoryTab2(item, selectedIndex + 1); } } else { //android 無彈性滑動,滑動到底時,offset + visibleLength = contentLength。IOS有彈性滑動,須要改變判斷條件 lbs 2019-03-10 if (offset + visibleLength > contentLength - JDDevice.getRpx(10)) { this._secondGoodFlatListRef.scrollToIndex({ animated: false, index: 0, viewOffset: 1, viewPosition: 0 }); this.ItemCategory._clickCategoryTab2 && this.ItemCategory._clickCategoryTab2(item, selectedIndex + 1); } } } } };
其中,contentLength
爲內容區高度,offset
爲滑動偏移量,visibleLength
爲可視區高度。ios
關於三種高度定義,可參考 React Native中ListView和ScrollView實現上拉加載
let scrollMetrics = (this._secondGoodFlatListRef && this._secondGoodFlatListRef._listRef && this._secondGoodFlatListRef._listRef._scrollMetrics) || null; let { contentLength = 0, // 內容區高度 offset = 0, // 滑動偏移量 visibleLength = 0 // 可視區高度 } = scrollMetrics;
對於 Android 平臺,當 offset + visibleLength = contentLength
時,表示滑動到底部。爲了之前進行切換,對條件進行修正,當滑動到距離底部 10px 時,觸發切換 Tab 函數,以下代碼所示web
//android 無彈性滑動,滑動到底時,offset + visibleLength = contentLength。IOS有彈性滑動,須要改變判斷條件 lbs 2019-03-10 if (offset + visibleLength > contentLength - JDDevice.getRpx(10)) { this._secondGoodFlatListRef.scrollToIndex({ animated: false, index: 0, viewOffset: 1, viewPosition: 0 }); //切換Tab this.ItemCategory._clickCategoryTab2 && this.ItemCategory._clickCategoryTab2(item, selectedIndex + 1); }
對於 IOS 平臺,由於 IOS 系統存在彈性上拉,以下圖所示。所以對滑動到底條件修正爲 offset + visibleLength > contentLength + JDDevice.getRpx(100)
。react-native
其中,JDDevice.getRpx(100)
表示彈性上拉的高度,即下圖中紅色框的高度。函數
if (Platform.OS === 'ios') { if (offset + visibleLength > contentLength + JDDevice.getRpx(100)) { this._secondGoodFlatListRef.scrollToIndex({ animated: false, index: 0, viewOffset: 1, viewPosition: 0 }); this.ItemCategory._clickCategoryTab2 && this.ItemCategory._clickCategoryTab2(item, selectedIndex + 1); } }