问题
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