Flutter上的简单可扩展列将不会具有Title>也可以扩展 [英] Simple expandable column on Flutter wont have Title > expandable too

查看:29
本文介绍了Flutter上的简单可扩展列将不会具有Title>也可以扩展的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试制作一个可扩展列.也就是说,它有2个子项:子项和在扩展小部件时出现的扩展子项.

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.

在下面的图片中,您会看到子级(蓝色)和展开的子级(红色),仅当 Expand>按钮被单击.

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

一切正常,但我做不到,我无法使用 Expand> 按钮来像这样工作:展开> (未展开),展开(空格)< (展开).

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))),
        ])

显而易见的解决方案是使此 Row 具有2个 Expanded 子级而不是2个 Container ,但是如果这样做,一切都会刹车,因为它位于水平滚动的 ListView 内部,因此它会尝试永久扩展.

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.

Dartpad中的整个代码:

https://dartpad.dev/dccfb8c0efa98f5da64eca625ccf1487

如果您用我提到的 Expanded()替换 Container(),则布局将无法呈现.

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

我已经考虑了很长时间了,但是 ExpandableListTitle 可能无法知道其父级的大小,因为其父级的大小取决于子级:已扩展但未扩展.

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:不能更改 ListView ,我确实需要在这些可扩展小部件之间水平滚动.

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

推荐答案

您传递的函数错误.请立即检查代码.

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),
                ),
              ),
            ),
          ],
        ),
      ),
    );
  }
}

这篇关于Flutter上的简单可扩展列将不会具有Title&gt;也可以扩展的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆