React Native 實現下拉自動切換分類

如圖所示,總體爲 FlatList,頂部分類欄吸頂,底部爲 feed 流。要實現下拉商品列表到底後,繼續下拉,自動切換到一下個分類的效果。react

rn-flatlist-autochange-tab-android

代碼層面,能夠在 FlatListonScrollEndDrag 中添加自動 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) 表示彈性上拉的高度,即下圖中紅色框的高度。函數

rn-flatlist-autochange-tab-ios

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);
    }        
}
相關文章
相關標籤/搜索