react native學習筆記13——FlatList上拉載入
我們可以利用官方元件RefreshControl
實現下拉重新整理功能,但React Native官方沒有提供相應的上拉載入的元件,因此在RN中實現上拉載入比下拉重新整理要複雜一點。
雖然沒有直接提供上拉載入的元件,不過我們仍可以通過FlatList的onEndReached與onEndReachedThreshold屬性來實現相應效果。
ActivityIndicator
這裡上拉載入的轉圈效果用ActivityIndicator表現。在開始上拉載入的實現之前先介紹一下官方元件ActivityIndicator——載入指示器。ActivityIndicator
的使用很簡單。
<ActivityIndicator
animating={true }
color='red'
size="large"
/>
屬性
屬性 | 型別 | 描述 |
---|---|---|
animating | bool | 是否要顯示指示器,預設為true,表示顯示。 |
color | string | 滾輪的前景顏色(預設為灰色)。 |
hidesWhenStopped(ios) | bool | 在沒有動畫的時候,是否要隱藏指示器(預設為true)。 |
size | enum(‘small’, ‘large’) | 指示器的大小。small的高度為20,large為36。 |
載入頁
根據上述ActivityIndicator屬性的介紹,可以使用ActivityIndicator實現一個簡單的載入頁面:
import React, {Component} from "react";
import {ActivityIndicator, StyleSheet, View} from "react-native";
export default class ActivityIndicatorDemo extends Component {
render() {
return (
<View style={styles.container}>
<ActivityIndicator
animating ={true}
color='red'
size="large"
/>
</View>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
flexDirection: 'row',
justifyContent: 'center',
alignItems: 'center',
backgroundColor: '#F5FCFF',
},
});
其效果如下:
上拉載入的實現
下面進入正篇——上拉載入的實現
上拉載入一般應用於分頁載入的情況,為了真實的模擬網路請求資料上拉重新整理載入更多的使用場景,這裡使用github提供的api。
思路
當FlatList滑動到底部時,頁面數加一,觸發請求新一頁的網路資料,更新到元件state中的資料來源dataArray中,dataArray也作為FlatList的資料來源data。實現滑動到底部觸發網路請求通過FlatList的onEndReached和onEndReachedThreshold屬性,onEndReached是在當列表被滾動到距離內容最底部不足onEndReachedThreshold的距離時呼叫。
具體實現
全域性變數
const REQUEST_URL = 'https://api.github.com/search/repositories?q=javascript&sort=stars&page=';
let pageNo = 1;//當前第幾頁
let totalPage=5;//總的頁數
let itemNo=0;//item的個數
初始化state
constructor(props) {
super(props);
this.state = {
isLoading: true,
//網路請求狀態
error: false,
errorInfo: "",
dataArray: [],
showFoot:0, // 控制foot, 0:隱藏footer 1:已載入完成,沒有更多資料 2 :顯示載入中
isRefreshing:false,//下拉控制
}
}
網路請求——獲取第n頁資料
//網路請求——獲取第pageNo頁資料
fetchData(pageNo) {
//這個是js的訪問網路的方法
fetch(REQUEST_URL+pageNo)
.then((response) => response.json())
.then((responseData) => {
let data = responseData.items;
let dataBlob = [];
let i = itemNo;
data.map(function (item) {
dataBlob.push({
key: i,
value: item,
})
i++;
});
itemNo = i;
console.log("itemNo:"+itemNo);
let foot = 0;
if(pageNo>=totalPage){
foot = 1;//listView底部顯示沒有更多資料了
}
this.setState({
//複製資料來源
dataArray:this.state.dataArray.concat(dataBlob),
isLoading: false,
showFoot:foot,
isRefreshing:false,
});
data = null;
dataBlob = null;
})
.catch((error) => {
this.setState({
error: true,
errorInfo: error
})
})
.done();
}
準備載入元件
在初始化state之後,渲染元件前,請求網路資料。
componentDidMount() {
//請求資料
this.fetchData( pageNo );
}
渲染元件
render() {
//第一次載入等待的view
if (this.state.isLoading && !this.state.error) {
return this.renderLoadingView();
} else if (this.state.error) {
//請求失敗view
return this.renderErrorView();
}
//載入資料
return this.renderData();
}
載入等待頁
利用上面介紹的ActivityIndicator
,實現載入等待頁。
renderLoadingView() {
return (
<View style={styles.container}>
<ActivityIndicator
animating={true}
color='red'
size="large"
/>
</View>
);
}
載入網路請求失敗頁
網路請求失敗,顯示失敗資訊頁。
renderErrorView() {
return (
<View style={styles.container}>
<Text>
Fail
</Text>
</View>
);
}
載入資料顯示頁
renderData() {
return (
<FlatList
data={this.state.dataArray}
renderItem={this._renderItemView}
ListFooterComponent={this._renderFooter.bind(this)}
onEndReached={this._onEndReached.bind(this)}
onEndReachedThreshold={1}
ItemSeparatorComponent={this._separator}
/>
);
}
每個item元件渲染
renderItem
根據行資料data渲染每一行的元件。
//返回itemView
_renderItemView({item}) {
return (
<View>
<Text style={styles.title}>name: {item.value.name} ({item.value.stargazers_count}
stars)</Text>
<Text style={styles.content}>description: {item.value.description}</Text>
</View>
);
}
尾部元件的渲染
ListFooterComponent
為尾部元件的渲染
當showFoot為2時顯示loading的動態效果是用ActivityIndicator
來實現的。
_renderFooter(){
if (this.state.showFoot === 1) {
return (
<View style={{height:30,alignItems:'center',justifyContent:'flex-start',}}>
<Text style={{color:'#999999',fontSize:14,marginTop:5,marginBottom:5,}}>
沒有更多資料了
</Text>
</View>
);
} else if(this.state.showFoot === 2) {
return (
<View style={styles.footer}>
<ActivityIndicator />
<Text>正在載入更多資料...</Text>
</View>
);
} else if(this.state.showFoot === 0){
return (
<View style={styles.footer}>
<Text></Text>
</View>
);
}
}
上拉載入
上拉載入的關鍵onEndReached
,當列表被滾動到距離內容最底部不足onEndReachedThreshold
的距離時呼叫。注意:onEndReachedThreshold
的值不是畫素單位而是比值,例如,0.5表示距離內容最底部的距離為當前列表可見長度的一半時觸發。
_onEndReached(){
//如果是正在載入中或沒有更多資料了,則返回
if(this.state.showFoot != 0 ){
return ;
}
//如果當前頁大於或等於總頁數,那就是到最後一頁了,返回
if((pageNo!=1) && (pageNo>=totalPage)){
return;
} else {
pageNo++;
}
//底部顯示正在載入更多資料
this.setState({showFoot:2});
//獲取資料
this.fetchData( pageNo );
}
}
分隔線
ItemSeparatorComponent
行與行之間的分隔線元件,不會出現在第一行之前和最後一行之後。
_separator(){
return <View style={{height:1,backgroundColor:'#999999'}}/>;
}
效果圖如下:
最後附上完整程式碼:
import React, {Component} from "react";
import {ActivityIndicator, FlatList, StyleSheet, Text, View} from "react-native";
const REQUEST_URL = 'https://api.github.com/search/repositories?q=javascript&sort=stars&page=';
let pageNo = 1;//當前第幾頁
let totalPage=5;//總的頁數
let itemNo=0;//item的個數
export default class LoadMoreDemo extends Component {
constructor(props) {
super(props);
this.state = {
isLoading: true,
//網路請求狀態
error: false,
errorInfo: "",
dataArray: [],
showFoot:0, // 控制foot, 0:隱藏footer 1:已載入完成,沒有更多資料 2 :顯示載入中
isRefreshing:false,//下拉控制
}
}
//網路請求——獲取第pageNo頁資料
fetchData(pageNo) {
//這個是js的訪問網路的方法
fetch(REQUEST_URL+pageNo)
.then((response) => response.json())
.then((responseData) => {
let data = responseData.items;
let dataBlob = [];
let i = itemNo;
data.map(function (item) {
dataBlob.push({
key: i,
value: item,
})
i++;
});
itemNo = i;
console.log("itemNo:"+itemNo);
let foot = 0;
if(pageNo>=totalPage){
foot = 1;//listView底部顯示沒有更多資料了
}
this.setState({
//複製資料來源
dataArray:this.state.dataArray.concat(dataBlob),
isLoading: false,
showFoot:foot,
isRefreshing:false,
});
data = null;
dataBlob = null;
})
.catch((error) => {
this.setState({
error: true,
errorInfo: error
})
})
.done();
}
componentDidMount() {
//請求資料
this.fetchData( pageNo );
}
//載入等待頁
renderLoadingView() {
return (
<View style={styles.container}>
<ActivityIndicator
animating={true}
color='red'
size="large"
/>
</View>
);
}
//載入失敗view
renderErrorView() {
return (
<View style={styles.container}>
<Text>
Fail
</Text>
</View>
);
}
//返回itemView
_renderItemView({item}) {
return (
<View>
<Text style={styles.title}>name: {item.value.name}</Text>
<Text style={styles.content}>stars: {item.value.stargazers_count}</Text>
<Text style={styles.content}>description: {item.value.description}</Text>
</View>
);
}
renderData() {
return (
<FlatList
data={this.state.dataArray}
renderItem={this._renderItemView}
ListFooterComponent={this._renderFooter.bind(this)}
onEndReached={this._onEndReached.bind(this)}
onEndReachedThreshold={1}
ItemSeparatorComponent={this._separator}
/>
);
}
render() {
//第一次載入等待的view
if (this.state.isLoading && !this.state.error) {
return this.renderLoadingView();
} else if (this.state.error) {
//請求失敗view
return this.renderErrorView();
}
//載入資料
return this.renderData();
}
_separator(){
return <View style={{height:1,backgroundColor:'#999999'}}/>;
}
_renderFooter(){
if (this.state.showFoot === 1) {
return (
<View style={{height:30,alignItems:'center',justifyContent:'flex-start',}}>
<Text style={{color:'#999999',fontSize:14,marginTop:5,marginBottom:5,}}>
沒有更多資料了
</Text>
</View>
);
} else if(this.state.showFoot === 2) {
return (
<View style={styles.footer}>
<ActivityIndicator />
<Text>正在載入更多資料...</Text>
</View>
);
} else if(this.state.showFoot === 0){
return (
<View style={styles.footer}>
<Text></Text>
</View>
);
}
}
_onEndReached(){
//如果是正在載入中或沒有更多資料了,則返回
if(this.state.showFoot != 0 ){
return ;
}
//如果當前頁大於或等於總頁數,那就是到最後一頁了,返回
if((pageNo!=1) && (pageNo>=totalPage)){
return;
} else {
pageNo++;
}
//底部顯示正在載入更多資料
this.setState({showFoot:2});
//獲取資料
this.fetchData( pageNo );
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
flexDirection: 'row',
justifyContent: 'center',
alignItems: 'center',
backgroundColor: '#F5FCFF',
},
title: {
fontSize: 15,
color: 'blue',
},
footer:{
flexDirection:'row',
height:24,
justifyContent:'center',
alignItems:'center',
marginBottom:10,
},
content: {
fontSize: 15,
color: 'black',
}
});
相關推薦
react native學習筆記13——FlatList上拉載入
我們可以利用官方元件RefreshControl實現下拉重新整理功能,但React Native官方沒有提供相應的上拉載入的元件,因此在RN中實現上拉載入比下拉重新整理要複雜一點。 雖然沒有直接提供上拉載入的元件,不過我們仍可以通過FlatList的onEnd
React Native學習筆記之--ListView和RefreshControl實現下拉重新整理
React Native學習筆記之–ListView和RefreshControl實現下拉重新整理 今天利用React Native中的ListView來實現原生開發中的UITableView(Android中就叫ListView)的介面效果。 資料數利用Ch
React-Native 學習筆記-Android開發平臺-開發環境搭建
環境變量 最新版 下載 and 系統 系統環境變量 新版本 開發環境 studio 詳細步驟請查看官網對應文檔,BUT,有些註意事項請註意! 1,優先安裝Node.js,因為後面可以使用npm安裝軟件, 2,註意不要使用CNPM!!!!!!!!! 3,Android
React Native學習筆記 -- 開發環境搭建
ebo 安裝完成 原因 包管理工具 chown iss 運行 遇到 命令 工欲善其事,必先利其器。這次主要介紹mac osx下React Native的開發環境的搭建。 homebrew mac上的包管理工具,用於安裝nodejs和其他一些工具軟件,在terminal輸入下
react native學習筆記24——Modal實現自定義彈出對話方塊
前言 上一篇文章介紹React Native系統提供的兩個彈出框的api——Alert與AlertIOS,Alert可以在雙平臺通用,但是隻能展示資訊量有限功能單一的文字對話方塊。AlertIOS比Alert稍微豐富一點,可以展示供使用者輸入的對話方塊,但只能
React Native學習筆記2:Android環境搭建
背景 各位童鞋有木有感覺官方文件很坑啊,根據官網的描述,首先在chocolate就直接卡死了,VPN沒什麼卵用,於是逐個去官網下載,直到昨天才發現不用VPN也可以下!公司是windows環境,這裡就先用windows搭建。 因為本身是移動開發者,所以
React Native 學習筆記十三(原生模組之Toast)
在學習官網上的Toast 的過程中 出現很多的坑 廢話就不說了 官網上都有 官網講解 實現思路 : 我們之前已經將react-native 嵌入原生了 那麼 我們就在之前的基礎上進行修改就好了 建立ToastUtils.java 繼承ReactContextBas
React-Native學習筆記之:導航器Navigator實現頁面間跳轉
Navigator用來實現不同頁面的切換,想設定Navigator,必須確定一個或多個呼叫routes物件,去定義每個場景。 還可以利用renderScene方法,導航欄可以根據指定的路由來渲染場景。
React Native 學習筆記(二)
坑一,環境好了,但是因為專案需求經常要安裝一些三方庫,xcode-select: error: tool ‘xcodebuild’ requires Xcode, but active developer directory ‘/Library/Develope
React Native學習筆記一之搭建開發環境
因為專案需要,今天開始正式學習React Native,先來搭建個開發環境 忐忑的心情 因為專案比較急,而且客戶要求使用React Native開發,只能先學點基礎然後在專案中使用的時候,邊做邊學了,在保證工期的前提下,進擊的程式猿, go,go,go!
React Native學習筆記之--向原生應用中整合RN頁面
React Native學習筆記之–向原生應用中整合RN頁面 根據在官方文件的學習要向已有的原生專案中新增RN元件最重要的就是以下幾步: 1.Understand what React Native components you want to in
react native 學習筆記----將react native嵌入到Android原生應用
不僅可以在react native 的js介面和現有工程的介面之間跳轉,而且可以把js寫的介面當成一個控制元件,嵌入到現有的activity,作為原生介面的一部分使用。 第一節:按照官方的例子,把js寫頁面放在一個activity,在原生應用裡啟動該activity。 開
React Native學習安卓手機上的返回鍵BackAndroid
使用 React Native開發,iOS搞完,開始適配安卓,由於木有接觸過安卓,所以碰到了很多問題,第一個問題,安卓的返回鍵BackAndroid問題,我寫了一個工具類,來搞定,其中用到了java原
React-Native學習筆記——正確整合到現有Android工程中
背景 我們可能需要將react-native整合到已有工程的某個module中,而不是從頭建立一個新工程。下面記錄了筆者一個demo的整合過程。 已有工程結構 下圖中,app為application型別module,rntrial為library型別的mo
React Native 學習筆記(一)--init 專案 和 執行專案
宣告:此篇blog是在Windows環境下開發Android專案的學習筆記,最近也是在網上翻找資料發現,網上的資源基本上都是Mac環境下的,而且大部分的資料都是關於React Native + Web / Service 的,關於android的學習資源不多,因此也就想通過
react native 學習筆記-----理解redux的一個極其簡單例子
'use strict'; import React, { Component, PropTypes} from 'react'; import { StyleSheet, Text, View, Image, Button, AppRegistry, TouchableHighl
react native學習筆記15——Picker、Switch、Slider
本文將介紹三個常用的元件Picker、Switch、Slider,它們都是官方提供的,並且均可以在android與ios渲染對應的原生元件。這三個元件的使用很簡單,在實戰開發中也很常見,因此這裡放在一起介紹。 Picker選擇器 Picker選擇器,通常
React-Native學習筆記——技術棧及簡介
推薦的技術棧順序清單 1、阮一峰es6: http://es6.ruanyifeng.com/ es6中的新特性是後續內容的基礎,重點內容有let關鍵字、解構賦值、建構函式和原型鏈、Promise物件、yield關鍵字、Generator函式、aysnc/await等
React Native學習筆記(一)Mac OS X下React Native的環境搭建
本文介紹Mac OS X系統下的React Native環境搭建過程。 1.環境要求: 1) Mac OS X作業系統 2) Xcode6.4或以上版本 3) Node.js4.0或以上版本 4) watchman和flow 2.安裝過程 1) N
React Native學習筆記之--元件之間資料的傳遞和跳轉
React Native學習筆記之–元件之間資料的傳遞和跳轉 自定義屬性的定義方式和傳遞 假定元件ComponentA中的自定義屬性為 static props = { tit