ReactNative 之FlatList使用及踩坑封装总结(2)
MetroListView(内部实行是ScrollView)是旧的ListView实现方式,VirtualizedList是新的性能比较好的实现。我们去该文件
//省略部分代码
const itemCount = this.props.getItemCount(data);
if (itemCount > 0) {
....省略部分代码
} else if (ListEmptyComponent) {
const element = React.isValidElement(ListEmptyComponent)
? ListEmptyComponent // $FlowFixMe
: <ListEmptyComponent />;
cells.push(
/* $FlowFixMe(>=0.53.0 site=react_native_fb,react_native_oss) This
* comment suppresses an error when upgrading Flow's support for React.
* To see the error delete this comment and run Flow. */
<View
key="$empty"
onLayout={this._onLayoutEmpty}
style={inversionStyle}>
{element}
</View>,
);
}
再此处看到我们定义的ListEmptyComponent外面包了一层view,该view加了样式inversionStyle。
const inversionStyle = this.props.inverted
? this.props.horizontal
? styles.horizontallyInverted
: styles.verticallyInverted
: null;
样式:
verticallyInverted: {
transform: [{scaleY: -1}],
},
horizontallyInverted: {
transform: [{scaleX: -1}],
},
上面的样式就是添加了一个动画,并没有设置高度,所以我们在ListEmptyComponent使用height:'100%'或者flex:1都没有效果,都没有撑起高度。
为了实现我们想要的效果,我们需要将height设置为具体的值。那么该值设置多大呢?你如果给FlatList设置一个样式,背景属性设置一个颜色,发现FlatList是默认有占满剩余屏的高度的(flex:1)。那么我们可以将ListEmptyComponent中view的高度设置为FlatList的高度,要获取FlatList的高度,我们可以通过onLayout获取。
代码调整:
//创建变量
fHeight = 0;
<FlatList
data={this.state.dataList} extraData={this.state}
refreshing={this.state.isRefreshing}
onRefresh={() => this._onRefresh()}
keyExtractor={(item, index) => item.id}
ItemSeparatorComponent={() => <View style={{
height: 1,
backgroundColor: '#D6D6D6'
}}/>}
renderItem={this._renderItem}
onLayout={e => this.fHeight = e.nativeEvent.layout.height}
ListEmptyComponent={this.emptyComponent}/>
//定义空布局
emptyComponent = () => {
return <View style={{
height: this.fHeight,
alignItems: 'center',
justifyContent: 'center',
}}>
<Text style={{
fontSize: 16
}}>暂无数据</Text>
</View>
}
通过上面的调整发现在Android上运行时达到我们想要的效果了,但是在iOS上,不可控,偶尔居中显示,偶尔又显示到最上面。原因就是在iOS上onLayout调用的时机与Android略微差别(iOS会出现emptyComponent渲染时onLayout还没有回调,此时fHeight还没有值)。
