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还没有值)。