【问题标题】:how to change layout in Flutter如何在 Flutter 中更改布局
【发布时间】:2020-08-16 08:30:13
【问题描述】:

我一直在尝试设计我的 ExpansionTile 的布局,就像下面的设计一样,但我不知道如何更改布局。关于如何更改边框半径、更改背景颜色以及彼此之间有什么建议?

我尝试在每个容器中添加 boxDecoration,但该样式仅适用于外部,而不适用于每个扩展 Tile。

import 'package:flutter/material.dart';

class MyReoderWidget extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return ReorderItems(topTen: ['j']);
  }
}
class DataHolder {
  List<String> parentKeys;

  Map<String, List<String>> childMap;

  DataHolder._privateConstructor();

  static final DataHolder _dataHolder = DataHolder._privateConstructor();

  static DataHolder get instance => _dataHolder;

  factory DataHolder.initialize({@required parentKeys}) {
    _dataHolder.parentKeys = parentKeys;
    _dataHolder.childMap = {};
    for (String key in parentKeys) {
      _dataHolder.childMap.putIfAbsent(

    }
    return _dataHolder;
  }
}

class ReorderItems extends StatefulWidget {
  final List<String> topTen;
  ReorderItems({this.topTen});
  @override
  _ReorderItemsState createState() => _ReorderItemsState();
}

class _ReorderItemsState extends State<ReorderItems> {
  @override
  void initState() {
    super.initState();
    // initialize the children for the Expansion tile
    // This initialization can be replaced with any logic like network fetch or something else.
    DataHolder.initialize(parentKeys: widget.topTen);
  }

  @override
  Widget build(BuildContext context) {
    return PrimaryScrollController(
      key: ValueKey(widget.topTen.toString()),
      controller: ScrollController(),
      child: Container(
        decoration: BoxDecoration(),
        child: ReorderableListView(
          onReorder: onReorder,
          children: getListItem(),
        ),
      ),
    );
  }

  List<ExpansionTile> getListItem() => DataHolder.instance.parentKeys
      .asMap()
      .map((index, item) => MapEntry(index, buildTenableListTile(item, index)))
      .values
      .toList();

  ExpansionTile buildTenableListTile(String mapKey, int index) => ExpansionTile(
        key: ValueKey(mapKey),
        title: Text(mapKey),
        leading: Icon(Icons.list),
        children: [
          Container(
            decoration: BoxDecoration(
              borderRadius: BorderRadius.all(Radius.circular(20))
            ),
            key: ValueKey('$mapKey$index'),
            height: 200,
            child: Container(
              padding: EdgeInsets.only(left: 30.0),
              child: ReorderList(
                parentMapKey: mapKey,
              ),
            ),
          ),
        ],
      );

  void onReorder(int oldIndex, int newIndex) {
    if (newIndex > oldIndex) {
      newIndex -= 1;
    }
    setState(() {
      String game = widget.topTen[oldIndex];
      DataHolder.instance.parentKeys.removeAt(oldIndex);
      DataHolder.instance.parentKeys.insert(newIndex, game);
    });
  }
}

class ReorderList extends StatefulWidget {
  final String parentMapKey;
  ReorderList({this.parentMapKey});
  @override
  _ReorderListState createState() => _ReorderListState();
}

class _ReorderListState extends State<ReorderList> {
  @override
  Widget build(BuildContext context) {
    return PrimaryScrollController(
      controller: ScrollController(),
      child: ReorderableListView(
        // scrollController: ScrollController(),
        onReorder: onReorder,
        children: DataHolder.instance.childMap[widget.parentMapKey]
            .map(
              (String child) => Container(
                child: ListTile(
                  key: ValueKey(child),
                  leading: Icon(Icons.list),
                  title: Text(child),
                ),
              ),
            )
            .toList(),
      ),
    );
  }

  void onReorder(int oldIndex, int newIndex) {
    if (newIndex > oldIndex) {
      newIndex -= 1;
    }
    List<String> children = DataHolder.instance.childMap[widget.parentMapKey];
    String game = children[oldIndex];
    children.removeAt(oldIndex);
    children.insert(newIndex, game);
    DataHolder.instance.childMap[widget.parentMapKey] = children;
    // Need to set state to rebuild the children.
    setState(() {});
  }
}

【问题讨论】:

    标签: flutter flutter-layout


    【解决方案1】:

    您可以使用自定义的可扩展容器来做到这一点。

    import 'package:flutter/material.dart';
    
    void main() => runApp(MyApp());
    
    class MyApp extends StatelessWidget {
      @override
      Widget build(BuildContext context) {
        return MaterialApp(
          title: 'Flutter Calendar',
          theme: ThemeData(
            primarySwatch: Colors.grey,
          ),
          debugShowCheckedModeBanner: false,
          home: Material(
            child: MyReoderWidget(),
          ),
        );
      }
    }
    
    class CustomModel {
      String title;
      bool isExpanded;
      List<String> subItems;
    
      CustomModel({this.title, this.subItems, this.isExpanded = false});
    }
    
    class MyReoderWidget extends StatefulWidget {
      @override
      _MyReoderWidgetState createState() => _MyReoderWidgetState();
    }
    
    class _MyReoderWidgetState extends State<MyReoderWidget> {
      List<CustomModel> listItems;
    
      @override
      void initState() {
        super.initState();
        listItems = List<CustomModel>();
        listItems.add(CustomModel(
            title: "App Name 1", subItems: ["Card Name 1", "Card Name 2"]));
        listItems.add(CustomModel(
            title: "App Name 2", subItems: ["Card Name 3", "Card Name 4"]));
      }
    
      @override
      Widget build(BuildContext context) {
        return Scaffold(
          backgroundColor: Colors.black,
          body: ListView(
              children: listItems
                  .map((model) => new Padding(
                        padding: EdgeInsets.only(
                          bottom: 10,
                        ),
                        child: ExpandableCardContainer(
                          isExpanded: model.isExpanded,
                          collapsedChild: createHeaderCard(model),
                          expandedChild: Column(
                            children: <Widget>[
                              Padding(
                                padding: EdgeInsets.only(
                                  bottom: 10,
                                ),
                                child: createHeaderCard(model),
                              )
                            ]..addAll(model.subItems
                                .map((e) => createChildCard(e))
                                .toList()),
                          ),
                        ),
                      ))
                  .toList()),
        );
      }
    
      Widget createHeaderCard(CustomModel model) {
        return Container(
          child: Row(
            children: <Widget>[
              Icon(
                Icons.more_vert,
                color: Colors.white,
              ),
              Expanded(
                child: Text(
                  model.title,
                  style: TextStyle(color: Colors.white),
                ),
              ),
              GestureDetector(
                onTap: () {
                  setState(() {
                    model.isExpanded = !model.isExpanded;
                  });
                },
                child: Icon(
                  model.isExpanded
                      ? Icons.keyboard_arrow_up
                      : Icons.keyboard_arrow_down,
                  color: Colors.white,
                ),
              )
            ],
          ),
          decoration: BoxDecoration(
            borderRadius: BorderRadius.circular(10),
            color: Color(0xFF132435),
          ),
          height: 50,
        );
      }
    
      Widget createChildCard(String subItems) {
        return Container(
          margin: EdgeInsets.only(left: 30, bottom: 10),
          child: Row(
            mainAxisAlignment: MainAxisAlignment.center,
            children: <Widget>[
              Icon(
                Icons.more_vert,
                color: Colors.white,
              ),
              Expanded(
                child: Text(
                  subItems,
                  style: TextStyle(color: Colors.white),
                ),
              ),
            ],
          ),
          decoration: BoxDecoration(
            borderRadius: BorderRadius.circular(10),
            color: Color(0xFF132435),
          ),
          height: 50,
        );
      }
    }
    
    class ExpandableCardContainer extends StatefulWidget {
      final bool isExpanded;
      final Widget collapsedChild;
      final Widget expandedChild;
    
      const ExpandableCardContainer(
          {Key key, this.isExpanded, this.collapsedChild, this.expandedChild})
          : super(key: key);
    
      @override
      _ExpandableCardContainerState createState() =>
          _ExpandableCardContainerState();
    }
    
    class _ExpandableCardContainerState extends State<ExpandableCardContainer> {
      @override
      Widget build(BuildContext context) {
        return new AnimatedContainer(
          duration: new Duration(milliseconds: 200),
          curve: Curves.easeInOut,
          child: widget.isExpanded ? widget.expandedChild : widget.collapsedChild,
        );
      }
    }
    
    

    【讨论】:

    • 您好,非常感谢您的回答,它看起来与设计一模一样,但在原始代码中,父项和子项是可重新排序的。请你帮我解决这个问题。谢谢
    • 如果你觉得它有帮助,你可以标记和支持它:) 对于可重新排序的东西,我建议你使用状态管理库,如 BLOC 或提供程序,并基于索引作为键重建它。您可以查看this
    • 好的,我会这样做,我是 Flutter 的新手,所以您是说我可以通过继续处理您的代码并按照您提供的示例链接实现上述设计吗?我坚持了几天,所以如果你能指导我,我会非常感激。谢谢
    • 这里使用 GestureDetector 对用户不是很友好。如果使用 InkWell 为总行添加点击事件会更好。
    • @aaasenomad 你可以使用我分享的代码,通过我分享的例子实现可拖动项目的功能。
    猜你喜欢
    • 1970-01-01
    • 2018-11-06
    • 2017-07-30
    • 2019-03-17
    • 1970-01-01
    • 2014-06-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多