Flutter中的自定义扩展瓷砖

问题描述 投票:0回答:1

我正在学习Flutter,我正尝试像下面的设计一样创建ExpansionTile,但我不确定是否可以更改expandTile的布局和设计。如果有人可以向我提出建议或就如何实现这种设计提供帮助,我们将不胜感激。

enter image description here

这是我所拥有的

enter image description here

这是我的代码

// One entry in the multilevel list displayed by this app.
class Entry {
  Entry(this.title, [this.children = const <Entry>[]]);

  final String title;
  final List<Entry> children;
}

// The entire multilevel list displayed by this app.
final List<Entry> data = <Entry>[
  Entry(
    'Group 1',
    <Entry>[
      Entry('Section B0'),
      Entry('Section B1'),
    ],
  ),
  Entry(
    'Group',
    <Entry>[
      Entry('Name 1'),
      Entry('Name 2'),
    ],
  ),
];

// Displays one Entry. If the entry has children then it's displayed
// with an ExpansionTile.
class EntryItem extends StatelessWidget {
  const EntryItem(this.entry);

  final Entry entry;

  Widget _buildTiles(Entry root) {
    if (root.children.isEmpty) return ListTile(title: Text(root.title));
    return ExpansionTile(
      leading: Icon(Icons.view_column),
      key: PageStorageKey<Entry>(root),
      title: Text(root.title),
      children: root.children.map(_buildTiles).toList(),
    );
  }

  @override
  Widget build(BuildContext context) {
    return _buildTiles(entry);
  }
}
``

flutter flutter-layout flutter-dependencies flutter-animation flutter-test
1个回答
0
投票

您可以在下面复制粘贴运行完整代码您可以使用套件https://pub.dev/packages/flutter_treeview它提供您可以配置的Expansion属性,您可以在下面看到工作示例您使用EntryNode创建List<Map<String, dynamic>>数据代码段

 @override
  void initState() {
    _nodes = [
      Node(
        label: 'documents',
        key: 'docs',
        expanded: docsOpen,
        icon: NodeIcon(
          codePoint:
              docsOpen ? Icons.folder_open.codePoint : Icons.folder.codePoint,
          color: "blue",
        ),
        children: [

...

const List<Map<String, dynamic>> US_STATES = [
  {
    "label": "A",
    "children": [
      {"label": "Alabama", "key": "AL"},
      {"label": "Alaska", "key": "AK"},
      {"label": "American Samoa", "key": "AS"},
      {"label": "Arizona", "key": "AZ"},
      {"label": "Arkansas", "key": "AR"}
    ]   

工作演示

enter image description here

完整代码

import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter_treeview/tree_view.dart';
import 'dart:convert';

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'TreeView Example',
      home: MyHomePage(title: 'TreeView Example'),
    );
  }
}

class MyHomePage extends StatefulWidget {
  MyHomePage({Key key, this.title}) : super(key: key);
  final String title;

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

class _MyHomePageState extends State<MyHomePage> {
  String _selectedNode;
  List<Node> _nodes;
  TreeViewController _treeViewController;
  bool docsOpen = true;
  final Map<ExpanderPosition, Widget> expansionPositionOptions = const {
    ExpanderPosition.start: Text('Start'),
    ExpanderPosition.end: Text('End'),
  };
  final Map<ExpanderType, Widget> expansionTypeOptions = const {
    ExpanderType.caret: Icon(
      Icons.arrow_drop_down,
      size: 28,
    ),
    ExpanderType.arrow: Icon(Icons.arrow_downward),
    ExpanderType.chevron: Icon(Icons.expand_more),
    ExpanderType.plusMinus: Icon(Icons.add),
  };
  final Map<ExpanderModifier, Widget> expansionModifierOptions = const {
    ExpanderModifier.none: ModContainer(ExpanderModifier.none),
    ExpanderModifier.circleFilled: ModContainer(ExpanderModifier.circleFilled),
    ExpanderModifier.circleOutlined:
        ModContainer(ExpanderModifier.circleOutlined),
    ExpanderModifier.squareFilled: ModContainer(ExpanderModifier.squareFilled),
    ExpanderModifier.squareOutlined:
        ModContainer(ExpanderModifier.squareOutlined),
  };
  ExpanderPosition _expanderPosition = ExpanderPosition.start;
  ExpanderType _expanderType = ExpanderType.caret;
  ExpanderModifier _expanderModifier = ExpanderModifier.none;
  bool _allowParentSelect = false;
  bool _supportParentDoubleTap = false;

  @override
  void initState() {
    _nodes = [
      Node(
        label: 'documents',
        key: 'docs',
        expanded: docsOpen,
        icon: NodeIcon(
          codePoint:
              docsOpen ? Icons.folder_open.codePoint : Icons.folder.codePoint,
          color: "blue",
        ),
        children: [
          Node(
              label: 'personal',
              key: 'd3',
              icon: NodeIcon.fromIconData(Icons.input),
              children: [
                Node(
                    label: 'Resume.docx',
                    key: 'pd1',
                    icon: NodeIcon.fromIconData(Icons.insert_drive_file)),
                Node(
                    label: 'Cover Letter.docx',
                    key: 'pd2',
                    icon: NodeIcon.fromIconData(Icons.insert_drive_file)),
              ]),
          Node(
            label: 'Inspection.docx',
            key: 'd1',
//          icon: NodeIcon.fromIconData(Icons.insert_drive_file),
          ),
          Node(
              label: 'Invoice.docx',
              key: 'd2',
              icon: NodeIcon.fromIconData(Icons.insert_drive_file)),
        ],
      ),
      Node(
          label: 'MeetingReport.xls',
          key: 'mrxls',
          icon: NodeIcon.fromIconData(Icons.insert_drive_file)),
      Node(
          label: 'MeetingReport.pdf',
          key: 'mrpdf',
          icon: NodeIcon.fromIconData(Icons.insert_drive_file)),
      Node(
          label: 'Demo.zip',
          key: 'demo',
          icon: NodeIcon.fromIconData(Icons.archive)),
    ];
    _treeViewController = TreeViewController(
      children: _nodes,
      selectedKey: _selectedNode,
    );
    super.initState();
  }

  ListTile _makeExpanderPosition() {
    return ListTile(
      title: Text('Expander Position'),
      dense: true,
      trailing: CupertinoSlidingSegmentedControl(
        children: expansionPositionOptions,
        groupValue: _expanderPosition,
        onValueChanged: (ExpanderPosition newValue) {
          setState(() {
            _expanderPosition = newValue;
          });
        },
      ),
    );
  }

  SwitchListTile _makeAllowParentSelect() {
    return SwitchListTile.adaptive(
      title: Text('Allow Parent Select'),
      dense: true,
      value: _allowParentSelect,
      onChanged: (v) {
        setState(() {
          _allowParentSelect = v;
        });
      },
    );
  }

  SwitchListTile _makeSupportParentDoubleTap() {
    return SwitchListTile.adaptive(
      title: Text('Support Parent Double Tap'),
      dense: true,
      value: _supportParentDoubleTap,
      onChanged: (v) {
        setState(() {
          _supportParentDoubleTap = v;
        });
      },
    );
  }

  ListTile _makeExpanderType() {
    return ListTile(
      title: Text('Expander Style'),
      dense: true,
      trailing: CupertinoSlidingSegmentedControl(
        children: expansionTypeOptions,
        groupValue: _expanderType,
        onValueChanged: (ExpanderType newValue) {
          setState(() {
            _expanderType = newValue;
          });
        },
      ),
    );
  }

  ListTile _makeExpanderModifier() {
    return ListTile(
      title: Text('Expander Modifier'),
      dense: true,
      trailing: CupertinoSlidingSegmentedControl(
        children: expansionModifierOptions,
        groupValue: _expanderModifier,
        onValueChanged: (ExpanderModifier newValue) {
          setState(() {
            _expanderModifier = newValue;
          });
        },
      ),
    );
  }

  @override
  Widget build(BuildContext context) {
    TreeViewTheme _treeViewTheme = TreeViewTheme(
      expanderTheme: ExpanderThemeData(
        type: _expanderType,
        modifier: _expanderModifier,
        position: _expanderPosition,
        color: Colors.grey.shade800,
        size: 20,
      ),
      labelStyle: TextStyle(
        fontSize: 16,
        letterSpacing: 0.3,
      ),
      parentLabelStyle: TextStyle(
        fontSize: 16,
        letterSpacing: 0.1,
        fontWeight: FontWeight.w800,
        color: Colors.blue.shade700,
      ),
      iconTheme: IconThemeData(
        size: 18,
        color: Colors.grey.shade800,
      ),
      colorScheme: Theme.of(context).brightness == Brightness.light
          ? ColorScheme.light(
              primary: Colors.blue.shade50,
              onPrimary: Colors.grey.shade900,
              background: Colors.transparent,
              onBackground: Colors.black,
            )
          : ColorScheme.dark(
              primary: Colors.black26,
              onPrimary: Colors.white,
              background: Colors.transparent,
              onBackground: Colors.white70,
            ),
    );
    return Scaffold(
      appBar: AppBar(
        title: Text(widget.title),
        elevation: 0,
      ),
      body: GestureDetector(
        onTap: () {
          FocusScope.of(context).requestFocus(FocusNode());
        },
        child: Container(
          color: Colors.grey.shade200,
          padding: EdgeInsets.all(20),
          height: double.infinity,
          child: Column(
            children: <Widget>[
              Container(
                height: 300,
                child: Column(
                  children: <Widget>[
                    _makeExpanderPosition(),
                    _makeExpanderType(),
                    _makeExpanderModifier(),
                    _makeAllowParentSelect(),
                    _makeSupportParentDoubleTap(),
                  ],
                ),
              ),
              Expanded(
                child: Container(
                  decoration: BoxDecoration(
                    color: Colors.white,
                    borderRadius: BorderRadius.circular(10),
                  ),
                  padding: EdgeInsets.all(10),
                  child: TreeView(
                    controller: _treeViewController,
                    allowParentSelect: _allowParentSelect,
                    supportParentDoubleTap: _supportParentDoubleTap,
                    onExpansionChanged: (key, expanded) =>
                        _expandNode(key, expanded),
                    onNodeTap: (key) {
                      debugPrint('Selected: $key');
                      setState(() {
                        _selectedNode = key;
                        _treeViewController =
                            _treeViewController.copyWith(selectedKey: key);
                      });
                    },
                    theme: _treeViewTheme,
                  ),
                ),
              ),
              GestureDetector(
                onTap: () {
                  debugPrint('Close Keyboard');
                  FocusScope.of(context).unfocus();
                },
                child: Container(
                  padding: EdgeInsets.only(top: 20),
                  alignment: Alignment.center,
                  child: Text(_treeViewController.getNode(_selectedNode) == null
                      ? ''
                      : _treeViewController.getNode(_selectedNode).label),
                ),
              )
            ],
          ),
        ),
      ),
      bottomNavigationBar: SafeArea(
        top: false,
        child: ButtonBar(
          alignment: MainAxisAlignment.spaceEvenly,
          children: <Widget>[
            CupertinoButton(
              child: Text('Node'),
              onPressed: () {
                setState(() {
                  _treeViewController = _treeViewController.copyWith(
                    children: _nodes,
                  );
                });
              },
            ),
            CupertinoButton(
              child: Text('JSON'),
              onPressed: () {
                setState(() {
                  _treeViewController =
                      _treeViewController.loadJSON(json: US_STATES_JSON);
                });
              },
            ),
            CupertinoButton(
              child: Text('Toggle'),
              onPressed: _treeViewController.selectedNode != null &&
                      _treeViewController.selectedNode.isParent
                  ? () {
                      setState(() {
                        _treeViewController = _treeViewController
                            .withToggleNode(_treeViewController.selectedKey);
                      });
                    }
                  : null,
            ),
            CupertinoButton(
              child: Text('Edit'),
              onPressed: () {
                TextEditingController editingController = TextEditingController(
                    text: _treeViewController.selectedNode.label);
                showCupertinoDialog(
                    context: context,
                    builder: (context) {
                      return CupertinoAlertDialog(
                        title: Text('Edit Label'),
                        content: Container(
                          height: 80,
                          alignment: Alignment.center,
                          padding: EdgeInsets.all(10),
                          child: CupertinoTextField(
                            controller: editingController,
                            autofocus: true,
                          ),
                        ),
                        actions: <Widget>[
                          CupertinoDialogAction(
                            child: Text('Cancel'),
                            isDestructiveAction: true,
                            onPressed: () => Navigator.of(context).pop(),
                          ),
                          CupertinoDialogAction(
                            child: Text('Update'),
                            isDefaultAction: true,
                            onPressed: () {
                              if (editingController.text.isNotEmpty) {
                                setState(() {
                                  Node _node = _treeViewController.selectedNode;
                                  _treeViewController =
                                      _treeViewController.withUpdateNode(
                                          _treeViewController.selectedKey,
                                          _node.copyWith(
                                              label: editingController.text));
                                });
                                debugPrint(editingController.text);
                              }
                              Navigator.of(context).pop();
                            },
                          ),
                        ],
                      );
                    });
              },
            ),
          ],
        ),
      ),
    );
  }

  _expandNode(String key, bool expanded) {
    String msg = '${expanded ? "Expanded" : "Collapsed"}: $key';
    debugPrint(msg);
    Node node = _treeViewController.getNode(key);
    if (node != null) {
      List<Node> updated;
      if (key == 'docs') {
        updated = _treeViewController.updateNode(
          key,
          node.copyWith(
              expanded: expanded,
              icon: NodeIcon(
                codePoint: expanded
                    ? Icons.folder_open.codePoint
                    : Icons.folder.codePoint,
                color: expanded ? "blue600" : "grey700",
              )),
        );
      } else {
        updated = _treeViewController.updateNode(
            key, node.copyWith(expanded: expanded));
      }
      setState(() {
        if (key == 'docs') docsOpen = expanded;
        _treeViewController = _treeViewController.copyWith(children: updated);
      });
    }
  }
}

class ModContainer extends StatelessWidget {
  final ExpanderModifier modifier;

  const ModContainer(this.modifier, {Key key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    double _borderWidth = 0;
    BoxShape _shapeBorder = BoxShape.rectangle;
    Color _backColor = Colors.transparent;
    Color _backAltColor = Colors.grey.shade700;
    switch (modifier) {
      case ExpanderModifier.none:
        break;
      case ExpanderModifier.circleFilled:
        _shapeBorder = BoxShape.circle;
        _backColor = _backAltColor;
        break;
      case ExpanderModifier.circleOutlined:
        _borderWidth = 1;
        _shapeBorder = BoxShape.circle;
        break;
      case ExpanderModifier.squareFilled:
        _backColor = _backAltColor;
        break;
      case ExpanderModifier.squareOutlined:
        _borderWidth = 1;
        break;
    }
    return Container(
      decoration: BoxDecoration(
        shape: _shapeBorder,
        border: _borderWidth == 0
            ? null
            : Border.all(
                width: _borderWidth,
                color: _backAltColor,
              ),
        color: _backColor,
      ),
      width: 15,
      height: 15,
    );
  }
}

const List<Map<String, dynamic>> US_STATES = [
  {
    "label": "A",
    "children": [
      {"label": "Alabama", "key": "AL"},
      {"label": "Alaska", "key": "AK"},
      {"label": "American Samoa", "key": "AS"},
      {"label": "Arizona", "key": "AZ"},
      {"label": "Arkansas", "key": "AR"}
    ]
  },
  {
    "label": "C",
    "children": [
      {"label": "California", "key": "CA"},
      {"label": "Colorado", "key": "CO"},
      {"label": "Connecticut", "key": "CT"},
    ]
  },
  {
    "label": "D",
    "children": [
      {"label": "Delaware", "key": "DE"},
      {"label": "District Of Columbia", "key": "DC"},
    ]
  },
  {
    "label": "F",
    "children": [
      {"label": "Federated States Of Micronesia", "key": "FM"},
      {"label": "Florida", "key": "FL"},
    ]
  },
  {
    "label": "G",
    "children": [
      {"label": "Georgia", "key": "GA"},
      {"label": "Guam", "key": "GU"},
    ]
  },
  {
    "label": "H",
    "children": [
      {"label": "Hawaii", "key": "HI"},
    ]
  },
  {
    "label": "I",
    "children": [
      {"label": "Idaho", "key": "ID"},
      {"label": "Illinois", "key": "IL"},
      {"label": "Indiana", "key": "IN"},
      {"label": "Iowa", "key": "IA"},
    ]
  },
  {
    "label": "K",
    "children": [
      {"label": "Kansas", "key": "KS"},
      {"label": "Kentucky", "key": "KY"},
    ]
  },
  {
    "label": "L",
    "children": [
      {"label": "Louisiana", "key": "LA"},
    ]
  },
  {
    "label": "M",
    "children": [
      {"label": "Maine", "key": "ME"},
      {"label": "Marshall Islands", "key": "MH"},
      {"label": "Maryland", "key": "MD"},
      {"label": "Massachusetts", "key": "MA"},
      {"label": "Michigan", "key": "MI"},
      {"label": "Minnesota", "key": "MN"},
      {"label": "Mississippi", "key": "MS"},
      {"label": "Missouri", "key": "MO"},
      {"label": "Montana", "key": "MT"},
    ]
  },
  {
    "label": "N",
    "children": [
      {"label": "Nebraska", "key": "NE"},
      {"label": "Nevada", "key": "NV"},
      {"label": "New Hampshire", "key": "NH"},
      {"label": "New Jersey", "key": "NJ"},
      {"label": "New Mexico", "key": "NM"},
      {"label": "New York", "key": "NY"},
      {"label": "North Carolina", "key": "NC"},
      {"label": "North Dakota", "key": "ND"},
      {"label": "Northern Mariana Islands", "key": "MP"},
    ]
  },
  {
    "label": "O",
    "children": [
      {"label": "Ohio", "key": "OH"},
      {"label": "Oklahoma", "key": "OK"},
      {"label": "Oregon", "key": "OR"},
    ]
  },
  {
    "label": "P",
    "children": [
      {"label": "Palau", "key": "PW"},
      {"label": "Pennsylvania", "key": "PA"},
      {"label": "Puerto Rico", "key": "PR"},
    ]
  },
  {
    "label": "R",
    "children": [
      {"label": "Rhode Island", "key": "RI"},
    ]
  },
  {
    "label": "S",
    "children": [
      {"label": "South Carolina", "key": "SC"},
      {"label": "South Dakota", "key": "SD"},
    ]
  },
  {
    "label": "T",
    "children": [
      {"label": "Tennessee", "key": "TN"},
      {"label": "Texas", "key": "TX"},
    ]
  },
  {
    "label": "U",
    "children": [
      {"label": "Utah", "key": "UT"},
    ]
  },
  {
    "label": "V",
    "children": [
      {"label": "Vermont", "key": "VT"},
      {"label": "Virgin Islands", "key": "VI"},
      {"label": "Virginia", "key": "VA"},
    ]
  },
  {
    "label": "W",
    "children": [
      {"label": "Washington", "key": "WA"},
      {"label": "West Virginia", "key": "WV"},
      {"label": "Wisconsin", "key": "WI"},
      {"label": "Wyoming", "key": "WY"}
    ]
  },
];

String US_STATES_JSON = jsonEncode(US_STATES);
© www.soinside.com 2019 - 2024. All rights reserved.