Simple expandable column on Flutter wont have Title > expandable too

混江龙づ霸主 提交于 2021-01-27 22:51:52

问题


I'm trying to make an Expandable Column. That is, it has 2 children: the child and the expanded child that appears when the widget is expanded.

In the picture below, you see the child (blue) and expanded child (red) which should only appear when the Expand > button is clicked.

Everything is working, but no mater what I do, I cannot get the Expand > button to work like this: Expand > when not expanded, and Expand (lots of spaces) < when expanded.

This is the code of the Expand button:

      Row(
          mainAxisAlignment: MainAxisAlignment.start,
          children: [
            //Expanded() would be the solution here, but it breaks cause it's inside ListView
            Container(
              child: Container(
                margin: const EdgeInsets.only(left: 12, top: 15),
                child: Text(this.title,
                    style: TextStyle(
                        fontSize: 20,
                        fontWeight: FontWeight.w700,
                        fontFamily: 'Roboto',
                        color: Colors.white)),
              )),
            //Expanded() would be the solution here, but it breaks cause it's inside ListView
            Container(
              child: Container(
                  margin: const EdgeInsets.only(right: 7, top: 15),
                  child: expanded != null && expanded
                      ? Icon(Icons.arrow_back_ios_outlined,
                      color: Colors.grey)
                      : Icon(Icons.arrow_forward_ios,
                      color: Colors.grey))),
        ])

The obvious solution would be to make this Row have 2 Expanded children instead of 2 Container, but if you do that everything brakes because it's inside a ListView scrollable horizontally, so it tries to expand forever.

Entire code in Dartpad:

https://dartpad.dev/dccfb8c0efa98f5da64eca625ccf1487

If you substitute Container() by Expanded() as I mentioned, the layout wont render.

I've been thinking for a long time on how to fix this, but the ExpandableListTitle can't possibly know the size of its parent since the size of its parent depends on the size of the children: expanded and not expanded.

PS: The ListView cannot be changed by a Row, I really need to scroll between these expandable widgets horizontally.


回答1:


You were passing the function wrong. Please check the code now.

import 'package:flutter/material.dart';

final Color darkBlue = const Color.fromARGB(255, 18, 32, 47);

const double COLUMN_WIDTH = 150;
const double COLUMN_WIDTH_EXPANDED = COLUMN_WIDTH;
const double COLUMN_WIDTH_TOTAL_EXPANDED = COLUMN_WIDTH + COLUMN_WIDTH_EXPANDED;

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      theme: ThemeData.dark().copyWith(scaffoldBackgroundColor: darkBlue),
      debugShowCheckedModeBanner: false,
      home: Scaffold(
        body: Center(
            child: Container(
                height: 300,
                child: ListView(scrollDirection: Axis.horizontal, children: [
                  ExpandableColumn(
                    title: "Expand",
                    child: Container(width: COLUMN_WIDTH, color: Colors.blue),
                    expandedChild: Container(
                        width: COLUMN_WIDTH_EXPANDED, color: Colors.red),
                    expanded: false,
                  ),
                  ExpandableColumn(
                    title: "Expand",
                    child: Container(width: COLUMN_WIDTH, color: Colors.green),
                    expandedChild: Container(
                        width: COLUMN_WIDTH_EXPANDED, color: Colors.purple),
                    expanded: false,
                  ),
                ]))),
      ),
    );
  }
}

class ExpandableColumn extends StatefulWidget {
  const ExpandableColumn(
      {Key key,
      this.title,
      @required this.child,
      this.expandedChild,
      this.onExpand,
      this.expanded})
      : super(key: key);
  final Widget child;
  final Widget expandedChild;
  final Function onExpand;
  final String title;
  final bool expanded;

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

class ExpandableColumnState extends State<ExpandableColumn>
    with TickerProviderStateMixin {
  bool expIcon = false;
  AnimationController _controller;
  Animation<double> _animation;
  //Animation<double> _animationT;
  Function onExpand;
  bool expanded;
  final Duration duration = const Duration(milliseconds: 200);

  @override
  void dispose() {
    super.dispose();
    _controller.dispose();
  }

  @override
  void initState() {
    super.initState();
    onExpand = widget.onExpand;
    expanded = widget.expanded;
    _controller = AnimationController(
      duration: duration,
      vsync: this,
    );
    _animation = CurvedAnimation(
      parent: _controller,
      curve: Curves.fastOutSlowIn,
    );
  }

  updateExpansion() {
    // if (expanded) {
    //   _controller.forward();
    // } else {
    //   _controller.reverse();
    // }
    !expanded
        ? Future.delayed(duration).then((value) {
            expIcon = !expIcon;
            _controller.reverse();
            setState(() {});
          })
        : _controller
            .forward()
            .then((value) => setState(() => expIcon = !expIcon));
  }

  onPressed() {
    expanded = !expanded;
    updateExpansion();
    setState(() {});
  }

  @override
  Widget build(BuildContext context) {
    return Align(
      alignment: Alignment.topLeft,
      child: Container(
          child: Column(
              //mainAxisAlignment: MainAxisAlignment.start,
              crossAxisAlignment: CrossAxisAlignment.start,
              children: [
            ExpandableListTitle(
              title: widget.title,
              expanded: expanded,
              onPress: onPressed,
              expIcon: expIcon,
              columnWidth: expanded
                  ? (_animation.value * 150 + 150)
                  : expIcon
                      ? (_animation.value * 150 + 150)
                      : COLUMN_WIDTH,
              duration: duration,
              // onPress: () => {
              //   setState(() {
              //     expanded != null ? expanded = !expanded : expanded = true;
              //     updateExpansion();
              //     if (onExpand != null) onExpand(expanded);
              //   })
              // },
            ),
            Expanded(
                child: Container(
              child:
                  Row(crossAxisAlignment: CrossAxisAlignment.start, children: [
                Container(
                  width: COLUMN_WIDTH,
                  child: widget.child,
                ),
                SizeTransition(
                    sizeFactor: _animation,
                    axis: Axis.horizontal,
                    axisAlignment: -1,
                    child: Container(
                        width: COLUMN_WIDTH, child: widget.expandedChild))
              ]),
            ))
          ])),
    );
  }
}

class ExpandableListTitle extends StatefulWidget {
  const ExpandableListTitle({
    Key key,
    this.title,
    this.expanded,
    this.onPress,
    this.expIcon,
    this.columnWidth,
    this.duration,
  }) : super(key: key);
  final String title;
  final bool expanded;
  final Function onPress;
  final bool expIcon;
  final double columnWidth;
  final Duration duration;
  @override
  _ExpandableListTitleState createState() => _ExpandableListTitleState();
}

class _ExpandableListTitleState extends State<ExpandableListTitle>
    with SingleTickerProviderStateMixin {
  bool _alignAnimationEnded = false;
  // bool expanded;
  // Function onPress;
  // String title;
  // @override
  // void initState() {
  //   super.initState();
  //   expanded = widget.expanded;
  //   onPress = widget.onPress;
  //   title = widget.title;
  // }

  @override
  Widget build(BuildContext context) {
    return Container(
      width: widget.columnWidth,
      child: GestureDetector(
        behavior: HitTestBehavior.opaque,
        // onTap: () =>
        //     onPress != null ? onPress() : print('ExpandableListTitle tap'),
        onTap: () {
          _alignAnimationEnded = false;
          widget.onPress();
        },
        child: Row(
          mainAxisAlignment: MainAxisAlignment.start,
          children: [
            Container(
                child: Container(
              margin: const EdgeInsets.only(left: 12, top: 15),
              child: Text(this.widget.title,
                  style: const TextStyle(
                      fontSize: 20,
                      fontWeight: FontWeight.w700,
                      fontFamily: 'Roboto',
                      color: Colors.white)),
            )),
            Expanded(
              flex: 1,
              child: Container(
                margin: const EdgeInsets.only(right: 7, top: 15),
                child: AnimatedAlign(
                  onEnd: () => setState(() => _alignAnimationEnded = true),
                  duration: widget.duration,
                  alignment: widget.expanded && widget.expIcon
                      ? Alignment.centerRight
                      : Alignment.centerLeft,
                  child: widget.expanded
                      ? widget.expIcon && _alignAnimationEnded
                          ? const Icon(Icons.arrow_back_ios_outlined,
                              color: Colors.grey)
                          : const Icon(Icons.arrow_forward_ios,
                              color: Colors.grey)
                      : widget.expIcon
                          ? const Icon(Icons.arrow_back_ios_outlined,
                              color: Colors.grey)
                          : const Icon(Icons.arrow_forward_ios,
                              color: Colors.grey),
                ),
              ),
            ),
          ],
        ),
      ),
    );
  }
}


来源:https://stackoverflow.com/questions/65296595/simple-expandable-column-on-flutter-wont-have-title-expandable-too

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!