美文网首页
18.flutter-两级折叠List

18.flutter-两级折叠List

作者: ChaosHeart | 来源:发表于2022-08-13 17:22 被阅读0次

插件部分

///初始数据
abstract class BaseBean {
  bool isOpen = true;
  int index = 0;
  int getChildSize();
}

import 'package:flutter/material.dart';

import 'base_bean.dart';

typedef GroupChildViewCreate = Widget Function(int parentIndex, int childIndex);
typedef SectionViewCreate = Widget Function(int index);

///折叠列表 - 2
class TwoLevelWidget<T extends BaseBean> extends StatefulWidget {
  final GroupChildViewCreate groupChildViewCreate;
  final SectionViewCreate sectionViewCreate;
  final T data;
  TwoLevelWidget(
    this.groupChildViewCreate,
    this.sectionViewCreate,
    this.data,
  );

  @override
  State<StatefulWidget> createState() => _TwoLevelWidgetState();
}

class _TwoLevelWidgetState extends State<TwoLevelWidget> {
  @override
  Widget build(BuildContext context) {
    return Column(
      children: <Widget>[
        Container(
          width: double.infinity,
          child: widget.sectionViewCreate(widget.data.index),
        ),
        widget.data.isOpen
            ? Padding(
                padding: EdgeInsets.only(left: 30),
                child: ListView.builder(
                  itemBuilder: (context, index) {
                    return widget.groupChildViewCreate(widget.data.index, index);
                  },
                  itemCount: widget.data.getChildSize(),
                  //内嵌listView 这个值要设置成true
                  shrinkWrap: true,
                  primary: true,
                  //嵌套滑动这个也得限制 不然 滑动子列表 外层不滚动
                  physics: NeverScrollableScrollPhysics(),
                ))
            : Container()
      ],
    );
  }
}

import 'package:flutter/gestures.dart';
import 'package:flutter/material.dart';

import 'base_bean.dart';
import 'two_level_widget.dart';

///折叠列表 - 1
class GroupListView<T extends BaseBean> extends StatefulWidget {
  ///Function which returns the number of items(rows) in a specified section.
  final int Function(int section) countOfItemInSection;

  ///Fields from ListView.builder constructor

  /// The axis along which the scroll view scrolls.
  ///
  /// Defaults to [Axis.vertical].
  final Axis scrollDirection;

  /// Whether the scroll view scrolls in the reading direction.
  ///
  /// For example, if the reading direction is left-to-right and
  /// [scrollDirection] is [Axis.horizontal], then the scroll view scrolls from
  /// left to right when [reverse] is false and from right to left when
  /// [reverse] is true.
  ///
  /// Similarly, if [scrollDirection] is [Axis.vertical], then the scroll view
  /// scrolls from top to bottom when [reverse] is false and from bottom to top
  /// when [reverse] is true.
  ///
  /// Defaults to false.
  final bool reverse;

  /// An object that can be used to control the position to which this scroll
  /// view is scrolled.
  ///
  /// Must be null if [primary] is true.
  ///
  /// A [ScrollController] serves several purposes. It can be used to control
  /// the initial scroll position (see [ScrollController.initialScrollOffset]).
  /// It can be used to control whether the scroll view should automatically
  /// save and restore its scroll position in the [PageStorage] (see
  /// [ScrollController.keepScrollOffset]). It can be used to read the current
  /// scroll position (see [ScrollController.offset]), or change it (see
  /// [ScrollController.animateTo]).
  final ScrollController controller;

  /// Whether this is the primary scroll view associated with the parent
  /// [PrimaryScrollController].
  ///
  /// When this is true, the scroll view is scrollable even if it does not have
  /// sufficient content to actually scroll. Otherwise, by default the user can
  /// only scroll the view if it has sufficient content. See [physics].
  ///
  /// On iOS, this also identifies the scroll view that will scroll to top in
  /// response to a tap in the status bar.
  ///
  /// Defaults to true when [scrollDirection] is [Axis.vertical] and
  /// [controller] is null.
  final bool primary;

  /// How the scroll view should respond to user input.
  ///
  /// For example, determines how the scroll view continues to animate after the
  /// user stops dragging the scroll view.
  ///
  /// Defaults to matching platform conventions. Furthermore, if [primary] is
  /// false, then the user cannot scroll if there is insufficient content to
  /// scroll, while if [primary] is true, they can always attempt to scroll.
  ///
  /// To force the scroll view to always be scrollable even if there is
  /// insufficient content, as if [primary] was true but without necessarily
  /// setting it to true, provide an [AlwaysScrollableScrollPhysics] physics
  /// object, as in:
  ///
  /// ```dart
  ///   physics: const AlwaysScrollableScrollPhysics(),
  /// ```
  ///
  /// To force the scroll view to use the default platform conventions and not
  /// be scrollable if there is insufficient content, regardless of the value of
  /// [primary], provide an explicit [ScrollPhysics] object, as in:
  ///
  /// ```dart
  ///   physics: const ScrollPhysics(),
  /// ```
  ///
  /// The physics can be changed dynamically (by providing a new object in a
  /// subsequent build), but new physics will only take effect if the _class_ of
  /// the provided object changes. Merely constructing a new instance with a
  /// different configuration is insufficient to cause the physics to be
  /// reapplied. (This is because the final object used is generated
  /// dynamically, which can be relatively expensive, and it would be
  /// inefficient to speculatively create this object each frame to see if the
  /// physics should be updated.)
  final ScrollPhysics physics;

  /// Whether the extent of the scroll view in the [scrollDirection] should be
  /// determined by the contents being viewed.
  ///
  /// If the scroll view does not shrink wrap, then the scroll view will expand
  /// to the maximum allowed size in the [scrollDirection]. If the scroll view
  /// has unbounded constraints in the [scrollDirection], then [shrinkWrap] must
  /// be true.
  ///
  /// Shrink wrapping the content of the scroll view is significantly more
  /// expensive than expanding to the maximum allowed size because the content
  /// can expand and contract during scrolling, which means the size of the
  /// scroll view needs to be recomputed whenever the scroll position changes.
  ///
  /// Defaults to false.
  final bool shrinkWrap;

  /// The amount of space by which to inset the children.
  final EdgeInsetsGeometry padding;

  /// If non-null, forces the children to have the given extent in the scroll
  /// direction.
  ///
  /// Specifying an [itemExtent] is more efficient than letting the children
  /// determine their own extent because the scrolling machinery can make use of
  /// the foreknowledge of the children's extent to save work, for example when
  /// the scroll position changes drastically.
  final double itemExtent;

  /// Whether to wrap each child in an [AutomaticKeepAlive].
  ///
  /// Typically, children in lazy list are wrapped in [AutomaticKeepAlive]
  /// widgets so that children can use [KeepAliveNotification]s to preserve
  /// their state when they would otherwise be garbage collected off-screen.
  ///
  /// This feature (and [addRepaintBoundaries]) must be disabled if the children
  /// are going to manually maintain their [KeepAlive] state. It may also be
  /// more efficient to disable this feature if it is known ahead of time that
  /// none of the children will ever try to keep themselves alive.
  ///
  /// Defaults to true.
  final bool addAutomaticKeepAlives;

  /// Whether to wrap each child in a [RepaintBoundary].
  ///
  /// Typically, children in a scrolling container are wrapped in repaint
  /// boundaries so that they do not need to be repainted as the list scrolls.
  /// If the children are easy to repaint (e.g., solid color blocks or a short
  /// snippet of text), it might be more efficient to not add a repaint boundary
  /// and simply repaint the children during scrolling.
  ///
  /// Defaults to true.
  final bool addRepaintBoundaries;

  /// Whether to wrap each child in an [IndexedSemantics].
  ///
  /// Typically, children in a scrolling container must be annotated with a
  /// semantic index in order to generate the correct accessibility
  /// announcements. This should only be set to false if the indexes have
  /// already been provided by an [IndexedChildSemantics] widget.
  ///
  /// Defaults to true.
  ///
  /// See also:
  ///
  ///  * [IndexedChildSemantics], for an explanation of how to manually
  ///    provide semantic indexes.
  final bool addSemanticIndexes;

  /// {@macro flutter.rendering.viewport.cacheExtent}
  final double cacheExtent;

  /// The number of children that will contribute semantic information.
  ///
  /// Some subtypes of [ScrollView] can infer this value automatically. For
  /// example [ListView] will use the number of widgets in the child list,
  /// while the [new ListView.separated] constructor will use half that amount.
  ///
  /// For [CustomScrollView] and other types which do not receive a builder
  /// or list of widgets, the child count must be explicitly provided. If the
  /// number is unknown or unbounded this should be left unset or set to null.
  ///
  /// See also:
  ///
  ///  * [SemanticsConfiguration.scrollChildCount], the corresponding semantics property.
  final int semanticChildCount;

  /// {@macro flutter.widgets.scrollable.dragStartBehavior}
  final DragStartBehavior dragStartBehavior;
  final GroupChildViewCreate groupChildViewCreate;
  final List<T> data;
  final SectionViewCreate sectionViewCreate;

  const GroupListView(
      {Key key,
      @required this.countOfItemInSection,
      this.scrollDirection = Axis.vertical,
      this.reverse = false,
      this.controller,
      this.primary,
      this.physics,
      this.shrinkWrap = false,
      this.padding,
      this.itemExtent,
      this.addAutomaticKeepAlives = true,
      this.addRepaintBoundaries = true,
      this.addSemanticIndexes = true,
      this.cacheExtent,
      this.semanticChildCount,
      this.dragStartBehavior = DragStartBehavior.start,
      this.groupChildViewCreate,
      @required this.data,
      @required this.sectionViewCreate})
      : assert(data != null),
        assert(countOfItemInSection != null),
        super(key: key);

  @override
  _GroupListViewState createState() => _GroupListViewState();
}

class _GroupListViewState extends State<GroupListView> {
  @override
  Widget build(BuildContext context) {
    return ListView.builder(
      scrollDirection: widget.scrollDirection,
      reverse: widget.reverse,
      controller: widget.controller,
      primary: widget.primary,
      physics: widget.physics,
      shrinkWrap: widget.shrinkWrap,
      padding: widget.padding,
      itemExtent: widget.itemExtent,
      addAutomaticKeepAlives: widget.addAutomaticKeepAlives,
      addRepaintBoundaries: widget.addRepaintBoundaries,
      addSemanticIndexes: widget.addSemanticIndexes,
      cacheExtent: widget.cacheExtent,
      semanticChildCount: widget.semanticChildCount,
      dragStartBehavior: widget.dragStartBehavior,
      itemCount: widget.data.length,
      itemBuilder: _itemBuilder,
    );
  }

  Widget _itemBuilder(BuildContext context, int index) {
    return TwoLevelWidget(widget.groupChildViewCreate, widget.sectionViewCreate, widget.data[index]);
  }
}

使用部分

import 'package:flutter_fold_list/group_list/base_bean.dart';

///数据
class GroupBean extends BaseBean {
  String title;
  List<ChildBean> childBeans = [];

  @override
  int getChildSize() => childBeans.length;
}

class ChildBean {
  int childIndex;
  String childTitle;
}

import 'dart:core';

import 'package:flutter/material.dart';
import 'package:flutter_fold_list/group_bean.dart';

import 'group_list/group_list_view.dart';

///实例界面
class GroupListPage extends StatefulWidget {
  @override
  State<StatefulWidget> createState() => _GroupListPageState();
}

class _GroupListPageState extends State<GroupListPage> {
  List<GroupBean> _parentBeans = [];

  @override
  void initState() {
    super.initState();
    initData();
  }

  void initData() {
    for (int i = 0; i < 10; i++) {
      GroupBean parentData = GroupBean();
      parentData.index = i;
      parentData.title = "title$i";
      List<ChildBean> childBeans = [];
      for (int j = 0; j < 10; j++) {
        ChildBean childBean = ChildBean();
        childBean.childIndex = j;
        childBean.childTitle = "childTitl$j";
        childBeans.add(childBean);
      }
      parentData.childBeans = childBeans;
      _parentBeans.add(parentData);
    }
  }

  @override
  Widget build(BuildContext context) {
    return new Scaffold(
      backgroundColor: Colors.blue,
      appBar: AppBar(
        centerTitle: true,
        title: Text("二级折叠List"),
      ),
      body: GroupListView<GroupBean>(
        //总数据
        data: _parentBeans,
        //标题列表 - 1
        sectionViewCreate: (section) {
          return GestureDetector(
            child: Padding(
              padding: const EdgeInsets.symmetric(horizontal: 15, vertical: 8),
              child: Text(
                _parentBeans[section].title,
                style: TextStyle(fontSize: 18, fontWeight: FontWeight.w600, color: Colors.red),
              ),
            ),
            onTap: () {
              _parentBeans[section].isOpen = !_parentBeans[section].isOpen;
              setState(() {});
            },
          );
        },
        //标题 对应 列表的个数 - 2
        countOfItemInSection: (int parentIndex) {
          return _parentBeans[parentIndex].childBeans.length;
        },
        //列表中的item - 2
        groupChildViewCreate: (parentIndex, childIndex) {
          return Text(
            _parentBeans[parentIndex].childBeans[childIndex].childTitle,
            style: TextStyle(color: Colors.white, fontSize: 18),
          );
        },
      ),
    );
  }
}

参考:
https://www.jianshu.com/p/336a2ce21dfc

相关文章

  • 18.flutter-两级折叠List

    插件部分 使用部分 参考:https://www.jianshu.com/p/336a2ce21dfc[https...

  • Flutter 两级折叠列表

  • R合并不等长list的elements为dataframe

    0、示例 列表数据 1、Rbind行合并list,折叠elements 元素为一列 2、Cbind,列合并list...

  • iOS之三级列表

    两级折叠列表的链接项目中有遇到做三级列表的功能出来,找了找demo,然后自己做了下,完善了些相关的UI界面,发出来...

  • 无标题文章.md

    >测试引用 测试两级标题 测试引用blockquote 测试两级标题: ##两级标题 测试两级标题 测试引用blo...

  • 读书如抽丝-书单

    Github-EasyBooks Books List 1.如何有效阅读一本书2.未来简史3.北京折叠4.科学怪人...

  • Xcode 折叠快捷键

    局部折叠(折叠一个函数) 全局折叠(折叠当前文件下的全部函数) 折叠注释块

  • Xcode快捷键

    折叠代码块: 局部折叠(折叠一个函数)Command+Option+Left/Right 全局折叠(折叠全部函数)...

  • XCode快捷键

    折叠 局部折叠(折叠一个函数) Command+Option+Left/Right 全局折叠(折叠当前文件下的...

  • 【认知折叠】

    认知折叠究竟是指什么?是指复杂性折叠吗或者折叠再折叠吗?前端系统感受不到,将复杂性打包折叠或者折叠再折叠到后端仅仅...

网友评论

      本文标题:18.flutter-两级折叠List

      本文链接:https://www.haomeiwen.com/subject/xtiqgrtx.html