Flutter---ListView

核心功能

用于显示​​可滚动的线性列表​​(垂直/水平)

支持​​懒加载​ ​(builder系列)和​​静态列表​ ​(children

内置​​滚动物理效果​​(弹性和边界效果)

四种构造方法

ListView():一次性构建所有子项

ListView.builder():按需构建子项,性能最优

ListView.separated():自动添加分隔组件

ListView.custom():使用 SliverChildDelegate

ListView的基础列表

Dart 复制代码
ListView.builder(
  itemCount: data.length,
  itemBuilder: (ctx, index) {
    return ListTile(
      title: Text(data[index].title),
      subtitle: Text(data[index].subtitle),
    );
  },
)

构建列表的数据流

①初始化列表数据

②ListView.builder初始化

③读取 itemCount: users.length(值为10)

④框架传入当前的 contextindex

⑤通过 users[index]获取对应数据

⑥返回构建好的 CardWidget

当用户点击列表时

①框架检测滚动位置变化

②动态计算新的 index范围(如滚动后需要显示index 2-5)

③销毁已离开屏幕的列表项(如index 0-1)

④调用 itemBuilder构建新进入屏幕的项(如index 4-5)

当用户点击列表项时

①触发点击事件

②获取当前 contextuser.name

③创建并显示SnackBar

④点击"关闭"按钮时销毁SnackBar

代码实例

main.dart

Dart 复制代码
import 'package:flutter/material.dart';

void main() {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        colorScheme: ColorScheme.fromSeed(seedColor: Colors.blue),
      ),
      home: const MyHomePage(title: '水果用户列表'),
    );
  }
}

//列表项的类
class User {
  final String name;
  final String email;
  final String imageAsset;  // 存储本地图片路径
  //构造函数
  User({
    required this.name,
    required this.email,
    required this.imageAsset,
  });
}

class MyHomePage extends StatefulWidget {
  const MyHomePage({super.key, required this.title});

  final String title;

  @override
  State<MyHomePage> createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {

  // 子项数据,每个用户关联不同的本地图片
  final List<User> users = [
    User(
      name: "苹果用户",
      email: "apple@example.com",
      imageAsset: 'assets/images/apple.png',
    ),
    User(
      name: "香蕉用户",
      email: "banana@example.com",
      imageAsset: 'assets/images/banana.png',
    ),
    User(
      name: "樱桃用户",
      email: "cherry@example.com",
      imageAsset: 'assets/images/cherry.png',
    ),
    User(
      name: "芒果用户",
      email: "mango@example.com",
      imageAsset: 'assets/images/mango.png',
    ),
    User(
      name: "菠萝用户",
      email: "pineapple@example.com",
      imageAsset: 'assets/images/pineapple.png',
    ),
    User(
      name: "苹果用户",
      email: "apple@example.com",
      imageAsset: 'assets/images/apple.png',
    ),
    User(
      name: "香蕉用户",
      email: "banana@example.com",
      imageAsset: 'assets/images/banana.png',
    ),
    User(
      name: "樱桃用户",
      email: "cherry@example.com",
      imageAsset: 'assets/images/cherry.png',
    ),
    User(
      name: "芒果用户",
      email: "mango@example.com",
      imageAsset: 'assets/images/mango.png',
    ),
    User(
      name: "菠萝用户",
      email: "pineapple@example.com",
      imageAsset: 'assets/images/pineapple.png',
    ),
  ];

  //UI建造
  @override
  Widget build(BuildContext context) {
    return Scaffold(

      appBar: AppBar(
        backgroundColor: Theme.of(context).colorScheme.inversePrimary,
        title: Text(widget.title),
        centerTitle: true,//居中标题
      ),

      body: ListView.builder(//构造列表
        itemCount: users.length,//列表项总数
        //动态构建每个列表项的UI
        itemBuilder: (context, index) {//框架自动传递index

          final user = users[index];//用index取User对象数据,通过 index实现 ListView与数据的间接关联

          return Card(//Card 容器
            margin: const EdgeInsets.symmetric(vertical: 8, horizontal: 16),//外边距
            child: ListTile(
              leading: Image.asset( //左侧图标
                user.imageAsset,
                width: 50,
                height: 50,
                errorBuilder: (context, error, stackTrace) {
                  return const Icon(Icons.error); // 图片加载失败时显示错误图标
                },
              ),
              title: Text(user.name),//第一个text
              subtitle: Text(user.email),//第二个text
              trailing: const Icon(Icons.arrow_forward),//右侧箭头图标
              //点击事件
              onTap: () {
                ScaffoldMessenger.of(context).showSnackBar( //SnackBar底部提示条
                  SnackBar(
                    content: Text("选择了: ${user.name}"), //文本提示
                    action: SnackBarAction(
                      label: '关闭',
                      onPressed: () {},
                    ),
                  ),
                );
              },
            ),
          );
        },

      ),
    );
  }
}
相关推荐
程序员老刘18 小时前
老刘给大家道个歉
flutter·ai编程
binbin_5220 小时前
Flutter 开发鸿蒙实战:Windows 环境下从 HAP 构建到四 Tab 页面运行
windows·flutter·harmonyos
阳光予你21 小时前
Flutter 字体渲染与字重
flutter
恋猫de小郭1 天前
Flutter 开发怎么做 Agent ?从工程实战详细给你解读下
android·前端·flutter
binbin_521 天前
Flutter 调用鸿蒙原生组件:MethodChannel 与 PlatformView 的选择和落地
开发语言·深度学习·flutter·harmonyos
GitLqr2 天前
Flutter 3.44 插件内置 Kotlin (KGP) 双向兼容适配指南
android·flutter·dart
SoaringHeart4 天前
Flutter进阶:基于 EasyRefresh 的下拉刷新封装 n_easy_refresh_mixin.dart
前端·flutter
月光下的丝瓜5 天前
Flutter 国内安装指南
前端·flutter
恋猫de小郭7 天前
Amper 正式转正 Kotlin Toolchain ,Gradle 未来何去何从
android·前端·flutter
张风捷特烈7 天前
Flutter 类库大揭秘#02 | path_provider 各平台实现
前端·flutter