Flutter: How to code the following ExpansionPanel

主宰稳场 提交于 2021-01-29 13:26:37

问题


Good day!

I am trying to find a solution for the following design:

Layout Image (Note: LightGrey Lines are just to point out the Layout. They should not be visible later on)

An ExpansionPanel shall contain 2 Columns, where Column A expands over the whole height (which Column B needs) but only uses a certain width. In Column A (left side), I want to draw a start and end point, connected with a line, and text next to those points. In Column B (right side), I want to show detailed information. However the amount of content shown on right side is not always the same. So Column A has to always fill the height, that Column B needs to show all its contents. It will also fill the remaining width that is used by Column A.

How can I code this example?

Many thanks!


回答1:


try this FooPanel class (the key is IntrinsicHeight as a parent of Row widget) - of course replace PanelPainter with your CustomPainter:

class FooPanel extends StatefulWidget {
  @override
  _FooPanelState createState() => _FooPanelState();
}

class _FooPanelState extends State<FooPanel> with SingleTickerProviderStateMixin {
  var expanded = false;
  AnimationController controller;

  @override
  void initState() {
    super.initState();
    controller = AnimationController(
      vsync: this,
      duration: Duration(milliseconds: 1000),
    );
  }

  @override
  Widget build(BuildContext context) {
    return SingleChildScrollView(
      child: ExpansionPanelList(
        expandedHeaderPadding: EdgeInsets.zero,
        expansionCallback: (i, b)  {
          setState(() => expanded = !b);
          if (expanded) {
            controller.forward(from: 0.0);
          }
        },
        children: [
          ExpansionPanel(
            headerBuilder: (ctx, b) => Align(alignment: Alignment.centerLeft , child: Text('London - Paris', textScaleFactor: 2)),
            body: IntrinsicHeight(
              child: Row(
                crossAxisAlignment: CrossAxisAlignment.stretch,
                children: [
                  CustomPaint(
                    size: Size.fromWidth(48),
                    painter: PanelPainter(controller),
                  ),
                  Column(crossAxisAlignment: CrossAxisAlignment.start , children: [
                    Text('London', textScaleFactor: 1.5),
                    ...[ 'a direct route', 'price 100 euro', '3 times a day', 'working days only']
                      .map((s) => Text(' • $s')),
                    Text('Paris', textScaleFactor: 1.5),
                  ],),
                ],
              ),
            ),
            isExpanded: expanded,
          ),
        ],
      ),
    );
  }
}

class PanelPainter extends CustomPainter {
  final AnimationController controller;
  final radius0;
  final radius1;
  final h;

  PanelPainter(this.controller) :
    radius0 = CurveTween(curve: Interval(0.3, 0.5)).animate(controller),
    radius1 = CurveTween(curve: Interval(0.5, 0.7)).animate(controller),
    h = CurveTween(curve: Interval(0.7, 1.0)).animate(controller),
    super(repaint: controller);

  @override
  void paint(Canvas canvas, Size size) {
    // timeDilation = 10;
    var rect = (Offset.zero & size).deflate(14);
    var paint = Paint()
      ..style = PaintingStyle.stroke
      ..strokeWidth = 2
      ..color = Colors.green;
    var p0 = Path()
      ..addOval(Rect.fromCircle(center: rect.topCenter, radius: 8 * radius0.value))
      ..addOval(Rect.fromCircle(center: rect.bottomCenter, radius: 8 * radius1.value));
    var p1 = Path()
      ..addRect(Rect.fromCenter(center: rect.center, width: 4, height: rect.height * h.value));
    var combinedPath = Path.combine(PathOperation.union, p0, p1);
    canvas.drawPath(combinedPath, paint);
  }

  @override
  bool shouldRepaint(covariant CustomPainter oldDelegate) => true;
}


来源:https://stackoverflow.com/questions/64679485/flutter-how-to-code-the-following-expansionpanel

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