【Flutter&Dart】 [ListView] or [GridView] 丝滑切换 例子七(19 /100)

上效果图

在这里插入图片描述
官网的demo例子,这个比较完整;基本上网格和列表数据加载框架用这一套就够用了;

上代码:

import 'package:flutter/material.dart';

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

  
  Widget build(BuildContext context) {
    return MaterialApp(
      home: ListTileSelectDemo(),
    );
  }
}

class ListTileSelectDemo extends StatefulWidget {
  const ListTileSelectDemo({super.key});

  
  createState() => ListTileSelectDemoState();
}

class ListTileSelectDemoState extends State<ListTileSelectDemo> {
  bool isSelectionMode = false;
  final int listLength = 30;
  late List<bool> _selected;
  bool _selectAll = false;
  bool _isGridMode = false;
  
  void initState() {
    super.initState();
    initializeSelection();
  }

  void initializeSelection() {
    _selected = List<bool>.generate(listLength, (_) => false);
  }

  
  void dispose() {
    _selected.clear();
    super.dispose();
  }

  
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('ListTile selection'),
        leading: isSelectionMode
            ? IconButton(
                onPressed: () {
                  setState(() {
                    isSelectionMode = false;
                  });
                  initializeSelection();
                },
                icon: Icon(Icons.close))
            : SizedBox(),
        actions: [
          if (_isGridMode)
            IconButton(
              icon: const Icon(Icons.grid_on),
              onPressed: () {
                setState(() {
                  _isGridMode = false;
                });
              },
            )
          else
            IconButton(
              icon: const Icon(Icons.list),
              onPressed: () {
                setState(() {
                  _isGridMode = true;
                });
              },
            ),
          if (isSelectionMode)
            TextButton(
                child: !_selectAll
                    ? const Text(
                        'select all',
                        style: TextStyle(color: Colors.white),
                      )
                    : const Text(
                        'unselect all',
                        style: TextStyle(color: Colors.white),
                      ),
                onPressed: () {
                  _selectAll = !_selectAll;
                  setState(() {
                    _selected =
                        List<bool>.generate(listLength, (_) => _selectAll);
                  });
                }),
        ],
      ),
      body: _isGridMode
          ? GridBuilder(
              isSelectionMode: isSelectionMode,
              selectedList: _selected,
              onSelectionChange: (bool x) {
                setState(() {
                  isSelectionMode = x;
                });
              },
            )
          : ListBuilder(
              isSelectionMode: isSelectionMode,
              selectedList: _selected,
              onSelectionChange: (bool x) {
                setState(() {
                  isSelectionMode = x;
                });
              },
            ),
    );
  }
}

class GridBuilder extends StatefulWidget {
  const GridBuilder(
      {super.key,
      required this.isSelectionMode,
      this.onSelectionChange,
      required this.selectedList});

  final bool isSelectionMode;
  final ValueChanged<bool>? onSelectionChange;
  final List<bool> selectedList;
  
  createState() => GridBuilderState();
}

class GridBuilderState extends State<GridBuilder> {
  void _toggle(int index) {
    if (widget.isSelectionMode) {
      setState(() {
        widget.selectedList[index] = !widget.selectedList[index];
      });
    }
  }

  
  Widget build(BuildContext context) {
    return GridView.builder(
        itemCount: widget.selectedList.length,
        gridDelegate:
            SliverGridDelegateWithFixedCrossAxisCount(crossAxisCount: 2),
        itemBuilder: (_, int index) {
          return InkWell(
            onTap: () => _toggle(index),
            onLongPress: () {
              if (!widget.isSelectionMode) {
                setState(() {
                  widget.selectedList[index] = true;
                });
                widget.onSelectionChange!(true);
              }
            },
            child: GridTile(
                child: Container(
              child: widget.isSelectionMode
                  ? Checkbox(
                      onChanged: (bool? x) => _toggle(index),
                      value: widget.selectedList[index])
                  : const Icon(Icons.image),
            )),
          );
        });
  }
}

class ListBuilder extends StatefulWidget {
  const ListBuilder(
      {super.key,
      required this.isSelectionMode,
      required this.selectedList,
      this.onSelectionChange});

  final bool isSelectionMode;
  final List<bool> selectedList;
  final ValueChanged<bool>? onSelectionChange;
  
  createState() => ListBuilderState();
}

class ListBuilderState extends State<ListBuilder> {
  void _toggle(int index) {
    if (widget.isSelectionMode) {
      setState(() {
        widget.selectedList[index] = !widget.selectedList[index];
      });
    }
  }

  
  Widget build(BuildContext context) {
    return ListView.builder(
      itemCount: widget.selectedList.length,
      itemBuilder: (_, int index) {
        return ListTile(
            onTap: () => _toggle(index),
            onLongPress: () {
              if (!widget.isSelectionMode) {
                setState(() {
                  widget.selectedList[index] = true;
                });
                widget.onSelectionChange!(true);
              }
            },
            trailing: widget.isSelectionMode
                ? Checkbox(
                    value: widget.selectedList[index],
                    onChanged: (bool? x) => _toggle(index),
                  )
                : const SizedBox.shrink(),
            title: Text('item $index'));
      },
    );
  }
}

这个列表和选中效果用在SmartApi左侧菜单栏里刚刚好!!!
======================END

开始扣UI布局细节了!!!!

不知不觉已经搞到19篇了,快接近目标的五分之一了,按以前的情况大概率干到50篇左右应该完事了。但我想加强一下,把GitHub里开源的比较好的工具项目多搞几个。
有兴趣的大佬可以推荐或者一起搞搞蛤!小工具开发一般也就一周或者两周,一个月的估计都算种大型项目了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

lichong951

你的鼓励决定更新的动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值