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

Flutter | 基于函数式编程的通用单选列表设计

请添加图片描述

背景

项目中多次用到如下图的通用单选列表页:

在这里插入图片描述

常规封装

此列表需要三样东西:

  1. 标题数组
  2. 当前选中项的 index
  3. 点击 cell 的回调

封装大体如下:

import 'package:flutter/material.dart';

class ListPage1 extends StatefulWidget {
  const ListPage1({
    super.key,
    required this.titles,
    required this.selectedIndex,
    required this.onSelected,
  });

  // 标题数组	
  final List<String> titles;
  // 当前选中项的 index
  final int selectedIndex;
  // 点击 cell 的回调
  final ValueChanged<int> onSelected;

  
  State<ListPage1> createState() => _ListPage1State();
}

class _ListPage1State extends State<ListPage1> {
  
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text("ListPage1")),
      body: ListView.builder(
        itemCount: widget.titles.length,
        itemBuilder: (context, index) {
          // 根据传入的index判断是否选中
          final isSelected = widget.selectedIndex == index;
          return GestureDetector(
            onTap: () {
              Navigator.pop(context);
              widget.onSelected(index);
            },
            child: Container(
              width: double.infinity,
              color: isSelected ? Colors.orange : Colors.white,
              height: 50,
              child: Text(
                widget.titles[index],
                style: const TextStyle(fontSize: 30),
              ),
            ),
          );
        },
      ),
    );
  }
}

使用:

final person1 = Person(name: 'amy', age: 10);
final person2 = Person(name: 'bob', age: 20);
final person3 = Person(name: 'candy', age: 30);
final persons = [person1, person2, person3];
final normalList = ListPage1(
  titles: persons.map((e) => e.name).toList(),
  selectedIndex: _selectedIndex,
  onSelected: (selectIndex) {
    setState(() {
      // 保存选中的index
      _selectedIndex = selectIndex;
    });
  },
);
Navigator.push(
  context,
  MaterialPageRoute(builder: (context) => normalList),
);

存在的问题:

必须在外部保存这个 selectedIndex,但我们真正需要的其实是这个 index 对应的 person

函数式封装

目标是在功能不变的前提下消除 selectedIndex

代码如下:

import 'package:flutter/material.dart';

class ListPage2<T> extends StatefulWidget {
  const ListPage2({
    super.key,
    required this.values,
    required this.titleBuilder,
    required this.selectedStateBuilder,
    required this.onSelected,
  });

  final List<T> values;

  // 用函数创建 title
  final String Function(T) titleBuilder;
  // 用函数表示选中状态
  final bool Function(T) selectedStateBuilder;
  // 选中回调,返回 model
  final ValueChanged<T> onSelected;

  
  State<ListPage2<T>> createState() => _ListPage2State<T>();
}

class _ListPage2State<T> extends State<ListPage2<T>> {
  
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text("ListPage2")),
      body: ListView.builder(
        itemCount: widget.values.length,
        itemBuilder: (context, index) {
          final currentItem = widget.values[index];
          final isSelected = widget.selectedStateBuilder(currentItem);
          return GestureDetector(
            onTap: () {
              Navigator.pop(context);
              widget.onSelected(currentItem);
            },
            child: Container(
              width: double.infinity,
              color: isSelected ? Colors.orange : Colors.white,
              height: 50,
              child: Text(
                widget.titleBuilder(currentItem),
                style: const TextStyle(fontSize: 30),
              ),
            ),
          );
        },
      ),
    );
  }
}

使用:

final person1 = Person(name: 'amy', age: 10);
final person2 = Person(name: 'bob', age: 20);
final person3 = Person(name: 'candy', age: 30);
final persons = [person1, person2, person3];
final listPage = ListPage2<Person>(
    values: persons,
    titleBuilder: (person) {
      return person.name;
    },
    selectedStateBuilder: (person) {
      return person.name == _currentPerson?.name;
    },
    onSelected: (person) {
      setState(() {
        _currentPerson = person;
      });
    });
Navigator.push(
  context,
  MaterialPageRoute(builder: (context) => listPage),
);

这种写法直接保存了选中的 person,没有了中间变量 selectedIndex,选中状态从之前的通过 selectedIndex 决定,到现在直接由外部函数判断。

所有功能未做任何改变,只是编程思想由命令式变成了函数式。


http://www.kler.cn/a/418916.html

相关文章:

  • ARM架构下安装新版docker及docker-compose
  • 【聚类】K-Means 聚类(无监督)及K-Means ++
  • 看华为,引入IPD的正确路径
  • TiDB 调度概述
  • HTTPS 加密
  • OCR实现微信截图改名
  • unity工程转为安卓使用的aar文件
  • 黑马2024AI+JavaWeb开发入门Day05-数据库DDL、DML、DQL飞书作业
  • windows电脑上安装树莓派操作系统
  • Ubuntu问题 -- 使用scp将本机文件传输至ubuntu服务器中
  • Linux 链接概念
  • antd table 自定义表头过滤表格内容
  • flutter 解决webview加载重定向h5页面 返回重复加载问题
  • 电脑cpu带的字母代表啥
  • 牛客面经学习【2024/12/1】
  • 剪映自动批量替换视频、图片素材教程,视频批量复刻、混剪裂变等功能介绍
  • PDF版地形图矢量出现的问题
  • Linux下的root密码重置
  • Dockerfile打包部署
  • MYSQL 什么是内连接 外连接 左连接 右连接?及适用场景
  • C++11新增特性2
  • vue3typescript,shims-vue.d.ts中declare module的vue声明
  • C-操作符
  • Linux虚拟机安装nginx踩坑记录
  • 《UDS协议从入门到精通(UDS速查手册)》(完结撒花版)
  • Java之链表1