当前位置: 首页 > news >正文

【React Native】ScrollView 和 FlatList 组件

ScrollView 组件

基础使用

import { View, Text, StyleSheet } from 'react-native';export default function App() {return (<View style={styles.container}><Text style={styles.content}>君不见黄河之水天上来,奔流到海不复回。君不见高堂明镜悲白发,朝如青丝暮成雪。人生得意须尽欢,莫使金樽空对月。天生我材必有用,千金散尽还复来。烹羊宰牛且为乐,会须一饮三百杯。岑夫子,丹丘生,将进酒,杯莫停。与君歌一曲,请君为我倾耳听。钟鼓馔玉不足贵,但愿长醉不愿醒。古来圣贤皆寂寞,惟有饮者留其名。陈王昔时宴平乐,斗酒十千恣欢谑。主人何为言少钱,径须沽取对君酌。五花马、千金裘,呼儿将出换美酒,与尔同销万古愁。</Text></View>);
};const styles = StyleSheet.create({container: {flex: 1,backgroundColor: '#fff'},content: {fontSize: 60}
});

在这里插入图片描述

可以看到字体很大的情况下,文本溢出,但是不支持滚动(因为View组件不支持滚动)

但是此时将 View 组件改为 ScrollView 组件,会发现可以正常滚动:

<ScrollView style={styles.container}>// ...
</ScrollView>

ScrollView经常会作为一个页面里最大的容器,里面再嵌套View,和其他各种组件。

SafeAreaView 处理刘海屏问题

如果大家用的是iOS设备,会发现文字到最顶上去了,被iPhone的刘海给挡住了。如果用Android倒是没有这个问题。解决方案是使用SafeAreaView的组件。

ScrollView的外面,包上一层SafeAreaView,并且把ScrollView的样式,挪到SafeAreaView上来。

export default function App() {return (<SafeAreaView style={styles.container}><ScrollView>// ...</ScrollView></SafeAreaView>);
};

RefreshControl 实现下拉刷新

ScrollView经常还会搭配RefreshControl组件来使用,这样可以实现下拉刷新。

import { useState } from "react";
import {View,Text,StyleSheet,ScrollView,SafeAreaView,RefreshControl,
} from "react-native";export default function App() {const [refreshing, setRefreshing] = useState(false);const onRefresh = () => {setRefreshing(true);// 模拟重新读取接口console.log("开始读取接口了");setTimeout(() => {setRefreshing(false);}, 2000);};return (<SafeAreaView style={styles.container}><ScrollViewrefreshControl={<RefreshControlrefreshing={refreshing}onRefresh={onRefresh}tintColor={"#1f99b0"}/>}><Text style={styles.content}>君不见黄河之水天上来,奔流到海不复回。君不见高堂明镜悲白发,朝如青丝暮成雪。人生得意须尽欢,莫使金樽空对月。 天生我材必有用,千金散尽还复来。烹羊宰牛且为乐,会须一饮三百杯。 岑夫子,丹丘生,将进酒,杯莫停。与君歌一曲,请君为我倾耳听。 钟鼓馔玉不足贵,但愿长醉不愿醒。古来圣贤皆寂寞,惟有饮者留其名。 陈王昔时宴平乐,斗酒十千恣欢谑。主人何为言少钱,径须沽取对君酌。 五花马、千金裘,呼儿将出换美酒,与尔同销万古愁。</Text></ScrollView></SafeAreaView>);
}const styles = StyleSheet.create({container: {flex: 1,backgroundColor: "#fff",},content: {fontSize: 60,},
});

配置了RefreshControl,并把这几个参数传进去:

  • refreshing,控制是否显示加载中指示器。
  • onRefresh,表示当用户下拉了,要执行什么函数。
  • 最后一个tintColor参数是加载中指示器的颜色,注意下,这个属性值只在iOS上有效,Android无效。

FlatList 组件

FlatList 组件用于处理长列表渲染。

以下这种直接渲染在数据量少的情况下可以正常使用,但是一旦数据量非常大,map 会遍历数组,然后一次性全部渲染出来。无论这个元素是否在屏幕的可见区域内,这样就会造成了大量的性能浪费。

import { Text, ScrollView, StyleSheet } from 'react-native';
import { SafeAreaView } from 'react-native';export default function App() {const data = [{ "id": 1, "title": "静夜思" },{ "id": 2, "title": "望庐山瀑布" },{ "id": 3, "title": "早发白帝城" },{ "id": 4, "title": "黄鹤楼送孟浩然之广陵" },{ "id": 5, "title": "将进酒" },{ "id": 6, "title": "行路难·其一" },{ "id": 7, "title": "蜀道难" },{ "id": 8, "title": "月下独酌·其一" },{ "id": 9, "title": "赠汪伦" },{ "id": 10, "title": "梦游天姥吟留别" },{ "id": 11, "title": "宣州谢朓楼饯别校书叔云" },{ "id": 12, "title": "送友人" },{ "id": 13, "title": "登金陵凤凰台" },{ "id": 14, "title": "清平调·其一" },{ "id": 15, "title": "秋浦歌·白发三千丈" },{ "id": 16, "title": "渡荆门送别" },{ "id": 17, "title": "夜宿山寺" },{ "id": 18, "title": "独坐敬亭山" },{ "id": 19, "title": "关山月" },{ "id": 20, "title": "子夜吴歌·秋歌" },{ "id": 21, "title": "下终南山过斛斯山人宿置酒" },{ "id": 22, "title": "月下独酌·其二" },{ "id": 23, "title": "塞下曲六首·其一" },{ "id": 24, "title": "玉阶怨" },{ "id": 25, "title": "春夜洛城闻笛" },{ "id": 26, "title": "越中览古" },{ "id": 27, "title": "山中问答" },{ "id": 28, "title": "清平调·其一" },{ "id": 29, "title": "清平调·其二" },{ "id": 30, "title": "清平调·其三" }]return (<SafeAreaView style={styles.container}><ScrollView>{data.map((item) => (<Text key={item.id} style={styles.title}>{item.title}</Text>))}</ScrollView></SafeAreaView>);
};const styles = StyleSheet.create({container: {flex: 1,backgroundColor: '#fff'},header: {textAlign: 'center',fontSize: 50,lineHeight: 60,fontWeight: 'bold',},footer: {textAlign: 'center',fontSize: 30,lineHeight: 60,color: '#999',},title: {textAlign: 'center',fontSize: 30,lineHeight: 60,}
});

更好的办法是使用FlatList,它是一个专门用来渲染长列表的组件,用它可以实现按需渲染。也就说只渲染当前屏幕可见的元素。当你滚动时,就动态加载新元素,回收不可见的元素。这样就只有比较小的性能开销了。

export default function App() {// ...return (<SafeAreaView style={styles.container}><FlatListdata={data}renderItem={({ item }) => <Text style={styles.title}>{item.title}</Text>}keyExtractor={item => item.id}/></SafeAreaView>);
};
  • 它里面接受一个data参数,这就是要遍历的数据了。
  • renderItem,就是要遍历渲染出来的内容。
  • keyExtractor,与map里的key是一回事。
  • ListHeaderComponent和ListFooterComponent,可以在同一个页面里,顶部和底部渲染其他组件。

还有个特别要注意的事情,如果在FlatList外面加了一层ScrollView,应用会直接报错。

在这里插入图片描述

提示我们,不要把相同方向的虚拟列表,放到ScrollView里。这也就是说,ScrollView是上下滚动的,FlatList也是上下滚动的,这两个之间是有冲突的。所以这里有了FlatList了,它自己就可以实现滚动,就不要再额外加上ScrollView了。

但是如果FlatList不是上下滚动,而是横向的左右滚动,与ScrollView方向不同,就不会出现这个报错。

export default function App() {// ...return (<SafeAreaView style={styles.container}><ScrollView><FlatListdata={data}renderItem={renderItem}keyExtractor={item => item.id}horizontal={true}ListHeaderComponent={<Text style={styles.header}>《唐诗 李白》</Text>}ListFooterComponent={<Text style={styles.footer}>没有更多了...</Text>}/></ScrollView></SafeAreaView>);
};

添加上horizontal属性,设置成true,就会变成横向滚动了。

  • 如果要实现下拉刷新,FlatList也直接支持使用RefreshControl
  • onEndReached表示触底后,要执行什么函数。
  • onEndReachedThreshold,表示距离列表底部还有多少可见区域时触发。例如我们这里设置成0.1,这表示距离底部还剩10%的时候,就会触发要执行的函数。
import { useState } from "react";
import {Text,ScrollView,StyleSheet,FlatList,RefreshControl,
} from "react-native";
import { SafeAreaView } from "react-native";export default function App() {const [refreshing, setRefreshing] = useState(false);const onRefresh = () => {setRefreshing(true);// 模拟重新读取接口console.log("开始读取接口了");setTimeout(() => {setRefreshing(false);}, 2000);};const onEndReached = () => {console.log('开始加载更多了');};const data = [{ id: 1, title: "静夜思" },{ id: 2, title: "望庐山瀑布" },{ id: 3, title: "早发白帝城" },{ id: 4, title: "黄鹤楼送孟浩然之广陵" },{ id: 5, title: "将进酒" },{ id: 6, title: "行路难·其一" },{ id: 7, title: "蜀道难" },{ id: 8, title: "月下独酌·其一" },{ id: 9, title: "赠汪伦" },{ id: 10, title: "梦游天姥吟留别" },{ id: 11, title: "宣州谢朓楼饯别校书叔云" },{ id: 12, title: "送友人" },{ id: 13, title: "登金陵凤凰台" },{ id: 14, title: "清平调·其一" },{ id: 15, title: "秋浦歌·白发三千丈" },{ id: 16, title: "渡荆门送别" },{ id: 17, title: "夜宿山寺" },{ id: 18, title: "独坐敬亭山" },{ id: 19, title: "关山月" },{ id: 20, title: "子夜吴歌·秋歌" },{ id: 21, title: "下终南山过斛斯山人宿置酒" },{ id: 22, title: "月下独酌·其二" },{ id: 23, title: "塞下曲六首·其一" },{ id: 24, title: "玉阶怨" },{ id: 25, title: "春夜洛城闻笛" },{ id: 26, title: "越中览古" },{ id: 27, title: "山中问答" },{ id: 28, title: "清平调·其一" },{ id: 29, title: "清平调·其二" },{ id: 30, title: "清平调·其三" },];return (<SafeAreaView style={styles.container}><FlatListdata={data}renderItem={({ item }) => (<Text style={styles.title}>{item.title}</Text>)}keyExtractor={(item) => item.id}ListHeaderComponent={<Text style={styles.header}>《唐诗 李白》</Text>}ListFooterComponent={<Text style={styles.footer}>没有更多了...</Text>}refreshControl={<RefreshControlrefreshing={refreshing}onRefresh={onRefresh}tintColor={"#1f99b0"}/>}onEndReached={onEndReached}onEndReachedThreshold={0.1}/></SafeAreaView>);
}const styles = StyleSheet.create({container: {flex: 1,backgroundColor: "#fff",},header: {textAlign: "center",fontSize: 50,lineHeight: 60,fontWeight: "bold",},footer: {textAlign: "center",fontSize: 30,lineHeight: 60,color: "#999",},title: {textAlign: "center",fontSize: 30,lineHeight: 60,},
});
http://www.lryc.cn/news/588295.html

相关文章:

  • C++中STL六大组件List的简单介绍
  • UI前端大数据处理新挑战:如何高效处理实时数据流?
  • AI创作系列第18篇:海狸IM移动端UI统一大升级 - 从混乱到规范的技术重构之路
  • 华为MateBook D 16 SE版 2024款 12代酷睿版i5集显(MCLF-XX,MCLF-16)原厂OEM预装Win11系统
  • 浏览器自动化领域的MCP
  • Spring Boot + Thymeleaf + RESTful API 前后端整合完整示例
  • 单片机(STM32-串口通信)
  • 延迟双删
  • 【ASP.NET Core】内存缓存(MemoryCache)原理、应用及常见问题解析
  • 位置编码类型彩色图解
  • 张艺兴探班RED女团一周年舞台,见证21岁的梦想落地生根
  • 代码随想录算法训练营第二十天
  • 一文读懂现代卷积神经网络—稠密连接网络(DenseNet)
  • Journal of Engineering Mechanics and Machinery,工程力学期刊,1-2天录用,7天出版,即将送检!
  • 自定义类型 - 联合体与枚举(百度笔试题算法优化)
  • 前端将传回的List数据组织成树形数据并展示
  • 用于监测线性基础设施的分布式声学传感:现状与趋势
  • 深度剖析:动态接口代理核心原理与高级应用
  • APP测试之Monkey压力测试
  • Relocations in generic ELF (EM: 40)
  • Qt小组件 - 2(布局)瀑布流布局,GridLayout,FlowLayout
  • 虚拟列表组件如果滑动速度过快导致渲染性能问题
  • UART寄存器介绍
  • 前端学习5:Float学习(仅简单了解,引出flex)
  • 015 程序地址空间入门
  • Life:Internship in OnSea Day 22
  • 某ctv视频下载逆向思路
  • 云原生技术与应用-Containerd容器技术详解
  • Git LFS 操作处理Github上传大文件操作记录
  • Spring Boot 双数据源配置