【问题标题】:Flutter expansion tile remove trailing颤振扩展瓦片去除尾随
【发布时间】:2021-01-15 19:19:38
【问题描述】:

我有一个 exoansiontile,我希望它像一个盒子,一切都居中,问题是如果我添加一个太长的文本,我会得到溢出错误,我认为这是由尾随引起的膨胀瓦。这是一张图片: https://gyazo.com/c29329106dc5dcb162b71b5f41951b67

代码如下:

ExpansionTile(

    trailing: Text(''),
    leading: Container(
        margin: new EdgeInsets.only(left: 0, top: 10.0, right: 0.0, bottom: 0.0),
        child: Image.asset(
            'images/food.png'
        )),
    title: Row(
        children: < Widget > [


            Padding(
                padding: const EdgeInsets.only(right: 0, left: 10, top: 15, bottom: 15),
                    child: Column(textDirection: TextDirection.ltr, crossAxisAlignment: CrossAxisAlignment.start, children: < Widget > [



                        Container(
                            margin: new EdgeInsets.only(left: 0.0, top: 7.0, right: 0.0, bottom: 3.0),
                            child: Text(
                                'Food System', textAlign: TextAlign.left,
                                style: TextStyle(
                                    color: Colors.white,
                                    fontSize: 25,
                                ),
                            )),
                        Text(
                            'Customize the food system', textAlign: TextAlign.left,
                            style: TextStyle(

                                color: Colors.white,
                                fontSize: 15,
                            ),
                        )

                    ])),

        ], ),
    children: < Widget > [



        Container(
            width: 300,
            margin: new EdgeInsets.only(left: 10.0, top: 0.0, right: 10.0, bottom: 10.0),
            color: Colors.transparent,
            child: new Container(


                padding: new EdgeInsets.all(20),
                child: Column(crossAxisAlignment: CrossAxisAlignment.start, children: < Widget > [
                    Container(
                        margin: new EdgeInsets.only(left: 15.0, top: .0, right: 20.0, bottom: 5.0),
                        child: Text('Storage', style: TextStyle(color: Colors.white, fontSize: 20, fontWeight: FontWeight.bold)), ),
                    Center(child: Column(children: < Widget > [
                        Container(
                            child: Column(children: < Widget > [
                                Text('2.4 KG left        -        7 Days', style: TextStyle(color: Colors.white, fontSize: 20)),
                                Text('200 G / Meal  - 600 G / Day', style: TextStyle(color: Colors.white, fontSize: 20)),
                            ], ),
                            margin: new EdgeInsets.only(left: 0, top: 0, right: 0, bottom: 10.0),
                        )

                    ], )),
                    Container(
                        margin: new EdgeInsets.only(left: 18.0, top: .0, right: 20.0, bottom: 5.0),
                        child: Text('Meal times', style: TextStyle(color: Colors.white, fontSize: 20, fontWeight: FontWeight.bold)), ),
                    Center(child: Column(children: < Widget > [

                        Text('1.   Breakfast   -   8:30 AM', style: TextStyle(color: Colors.white, fontSize: 20)),
                        Text('2.   Lunch         -   2:00 PM', style: TextStyle(color: Colors.white, fontSize: 20)),
                        Text('3.   Dinner        -   9:15  PM', style: TextStyle(color: Colors.white, fontSize: 20)),
                    ], ))
                ], ), )
        ),




        Container(
            height: 50.0,
            width: 300,

            margin: new EdgeInsets.only(left: 10.0, top: 10.0, right: 10.0, bottom: 10.0),
            color: Colors.transparent,
            child: new Container(
                decoration: new BoxDecoration(
                    color: Colors.blue,
                    gradient: LinearGradient(
                        begin: Alignment.topRight,
                        end: Alignment.bottomLeft,
                        colors: [Color(0xff37b9ff), Color(0xff5d3afd)]),
                    borderRadius: new BorderRadius.only(
                        topLeft: const Radius.circular(40.0),
                            topRight: const Radius.circular(40.0),
                                bottomLeft: const Radius.circular(40.0),
                                    bottomRight: const Radius.circular(40.0),

                    )
                ),
                child: Center(child:

                    Text('Edit', style: TextStyle(color: Colors.white, fontSize: 15))

                    , )
            )
        ),
    ]

【问题讨论】:

    标签: flutter flutter-layout flutter-animation


    【解决方案1】:

    请创建一个空文件并将此代码复制到该文件中... 我修改了颤振扩展瓷砖的一部分。 我删除了尾随...

    // Copyright 2014 The Flutter Authors. All rights reserved.
    // Use of this source code is governed by a BSD-style license that can be
    // found in the LICENSE file.
    
    // @dart = 2.8
    
    import 'package:flutter/material.dart';
    import 'package:flutter/widgets.dart';
    
    //import 'colors.dart';
    //import 'icons.dart';
    //import 'list_tile.dart';
    //import 'theme.dart';
    //import 'theme_data.dart';
    
    const Duration _kExpand = Duration(milliseconds: 200);
    
    /// A single-line [ListTile] with a trailing button that expands or collapses
    /// the tile to reveal or hide the [children].
    ///
    /// This widget is typically used with [ListView] to create an
    /// "expand / collapse" list entry. When used with scrolling widgets like
    /// [ListView], a unique [PageStorageKey] must be specified to enable the
    /// [MyExpansionTile] to save and restore its expanded state when it is scrolled
    /// in and out of view.
    ///
    /// See also:
    ///
    ///  * [ListTile], useful for creating expansion tile [children] when the
    ///    expansion tile represents a sublist.
    ///  * The "Expand/collapse" section of
    ///    <https://material.io/guidelines/components/lists-controls.html>.
    class MyExpansionTile extends StatefulWidget {
      /// Creates a single-line [ListTile] with a trailing button that expands or collapses
      /// the tile to reveal or hide the [children]. The [initiallyExpanded] property must
      /// be non-null.
      const MyExpansionTile({
        Key key,
        this.leading,
        @required this.title,
        this.subtitle,
        this.backgroundColor,
        this.onExpansionChanged,
        this.children = const <Widget>[],
        /*this.trailing,*/
        this.initiallyExpanded = false,
        this.maintainState = false,
        this.tilePadding,
        this.expandedCrossAxisAlignment,
        this.expandedAlignment,
        this.childrenPadding,
      }) : assert(initiallyExpanded != null),
           assert(maintainState != null),
           assert(
           expandedCrossAxisAlignment != CrossAxisAlignment.baseline,
           'CrossAxisAlignment.baseline is not supported since the expanded children '
               'are aligned in a column, not a row. Try to use another constant.',
           ),
           super(key: key);
    
      /// A widget to display before the title.
      ///
      /// Typically a [CircleAvatar] widget.
      final Widget leading;
    
      /// The primary content of the list item.
      ///
      /// Typically a [Text] widget.
      final Widget title;
    
      /// Additional content displayed below the title.
      ///
      /// Typically a [Text] widget.
      final Widget subtitle;
    
      /// Called when the tile expands or collapses.
      ///
      /// When the tile starts expanding, this function is called with the value
      /// true. When the tile starts collapsing, this function is called with
      /// the value false.
      final ValueChanged<bool> onExpansionChanged;
    
      /// The widgets that are displayed when the tile expands.
      ///
      /// Typically [ListTile] widgets.
      final List<Widget> children;
    
      /// The color to display behind the sublist when expanded.
      final Color backgroundColor;
    
    //  /// A widget to display instead of a rotating arrow icon.
    //  final Widget trailing;
    
      /// Specifies if the list tile is initially expanded (true) or collapsed (false, the default).
      final bool initiallyExpanded;
    
      /// Specifies whether the state of the children is maintained when the tile expands and collapses.
      ///
      /// When true, the children are kept in the tree while the tile is collapsed.
      /// When false (default), the children are removed from the tree when the tile is
      /// collapsed and recreated upon expansion.
      final bool maintainState;
    
      /// Specifies padding for the [ListTile].
      ///
      /// Analogous to [ListTile.contentPadding], this property defines the insets for
      /// the [leading], [title], [subtitle] and [trailing] widgets. It does not inset
      /// the expanded [children] widgets.
      ///
      /// When the value is null, the tile's padding is `EdgeInsets.symmetric(horizontal: 16.0)`.
      final EdgeInsetsGeometry tilePadding;
    
      /// Specifies the alignment of [children], which are arranged in a column when
      /// the tile is expanded.
      ///
      /// The internals of the expanded tile make use of a [Column] widget for
      /// [children], and [Align] widget to align the column. The `expandedAlignment`
      /// parameter is passed directly into the [Align].
      ///
      /// Modifying this property controls the alignment of the column within the
      /// expanded tile, not the alignment of [children] widgets within the column.
      /// To align each child within [children], see [expandedCrossAxisAlignment].
      ///
      /// The width of the column is the width of the widest child widget in [children].
      ///
      /// When the value is null, the value of `expandedAlignment` is [Alignment.center].
      final Alignment expandedAlignment;
    
      /// Specifies the alignment of each child within [children] when the tile is expanded.
      ///
      /// The internals of the expanded tile make use of a [Column] widget for
      /// [children], and the `crossAxisAlignment` parameter is passed directly into the [Column].
      ///
      /// Modifying this property controls the cross axis alignment of each child
      /// within its [Column]. Note that the width of the [Column] that houses
      /// [children] will be the same as the widest child widget in [children]. It is
      /// not necessarily the width of [Column] is equal to the width of expanded tile.
      ///
      /// To align the [Column] along the expanded tile, use the [expandedAlignment] property
      /// instead.
      ///
      /// When the value is null, the value of `expandedCrossAxisAlignment` is [CrossAxisAlignment.center].
      final CrossAxisAlignment expandedCrossAxisAlignment;
    
      /// Specifies padding for [children].
      ///
      /// When the value is null, the value of `childrenPadding` is [EdgeInsets.zero].
      final EdgeInsetsGeometry childrenPadding;
    
      @override
      _MyExpansionTileState createState() => _MyExpansionTileState();
    }
    
    class _MyExpansionTileState extends State<MyExpansionTile> with SingleTickerProviderStateMixin {
      static final Animatable<double> _easeOutTween = CurveTween(curve: Curves.easeOut);
      static final Animatable<double> _easeInTween = CurveTween(curve: Curves.easeIn);
      static final Animatable<double> _halfTween = Tween<double>(begin: 0.0, end: 0.5);
    
      final ColorTween _borderColorTween = ColorTween();
      final ColorTween _headerColorTween = ColorTween();
      final ColorTween _iconColorTween = ColorTween();
      final ColorTween _backgroundColorTween = ColorTween();
    
      AnimationController _controller;
      Animation<double> _iconTurns;
      Animation<double> _heightFactor;
      Animation<Color> _borderColor;
      Animation<Color> _headerColor;
      Animation<Color> _iconColor;
      Animation<Color> _backgroundColor;
    
      bool _isExpanded = false;
    
      @override
      void initState() {
        super.initState();
        _controller = AnimationController(duration: _kExpand, vsync: this);
        _heightFactor = _controller.drive(_easeInTween);
        _iconTurns = _controller.drive(_halfTween.chain(_easeInTween));
        _borderColor = _controller.drive(_borderColorTween.chain(_easeOutTween));
        _headerColor = _controller.drive(_headerColorTween.chain(_easeInTween));
        _iconColor = _controller.drive(_iconColorTween.chain(_easeInTween));
        _backgroundColor = _controller.drive(_backgroundColorTween.chain(_easeOutTween));
    
        _isExpanded = PageStorage.of(context)?.readState(context) as bool ?? widget.initiallyExpanded;
        if (_isExpanded)
          _controller.value = 1.0;
      }
    
      @override
      void dispose() {
        _controller.dispose();
        super.dispose();
      }
    
      void _handleTap() {
        setState(() {
          _isExpanded = !_isExpanded;
          if (_isExpanded) {
            _controller.forward();
          } else {
            _controller.reverse().then<void>((void value) {
              if (!mounted)
                return;
              setState(() {
                // Rebuild without widget.children.
              });
            });
          }
          PageStorage.of(context)?.writeState(context, _isExpanded);
        });
        if (widget.onExpansionChanged != null)
          widget.onExpansionChanged(_isExpanded);
      }
    
      Widget _buildChildren(BuildContext context, Widget child) {
        final Color borderSideColor = _borderColor.value ?? Colors.transparent;
    
        return Container(
          decoration: BoxDecoration(
            color: _backgroundColor.value ?? Colors.transparent,
            border: Border(
              top: BorderSide(color: borderSideColor),
              bottom: BorderSide(color: borderSideColor),
            ),
          ),
          child: Column(
            mainAxisSize: MainAxisSize.min,
            children: <Widget>[
              ListTileTheme.merge(
                iconColor: _iconColor.value,
                textColor: _headerColor.value,
                child: ListTile(
                  onTap: _handleTap,
                  contentPadding: widget.tilePadding,
                  leading: widget.leading,
                  title: widget.title,
                  subtitle: widget.subtitle,
                  /*trailing: widget.trailing ?? RotationTransition(
                    turns: _iconTurns,
                    child: const Icon(Icons.expand_more),
                  ),*/
                ),
              ),
              ClipRect(
                child: Align(
                  alignment: widget.expandedAlignment ?? Alignment.center,
                  heightFactor: _heightFactor.value,
                  child: child,
                ),
              ),
            ],
          ),
        );
      }
    
      @override
      void didChangeDependencies() {
        final ThemeData theme = Theme.of(context);
        _borderColorTween.end = theme.dividerColor;
        _headerColorTween
          ..begin = theme.textTheme.subtitle1.color
          ..end = theme.accentColor;
        _iconColorTween
          ..begin = theme.unselectedWidgetColor
          ..end = theme.accentColor;
        _backgroundColorTween.end = widget.backgroundColor;
        super.didChangeDependencies();
      }
    
      @override
      Widget build(BuildContext context) {
        final bool closed = !_isExpanded && _controller.isDismissed;
        final bool shouldRemoveChildren = closed && !widget.maintainState;
    
        final Widget result = Offstage(
          child: TickerMode(
            child: Padding(
              padding: widget.childrenPadding ?? EdgeInsets.zero,
              child: Column(
                crossAxisAlignment: widget.expandedCrossAxisAlignment ?? CrossAxisAlignment.center,
                children: widget.children,
              ),
            ),
            enabled: !closed,
          ),
          offstage: closed
        );
    
        return AnimatedBuilder(
          animation: _controller.view,
          builder: _buildChildren,
          child: shouldRemoveChildren ? null : result,
        );
      }
    }
     
    

    【讨论】:

    • 错误:默认情况下,当使用健全的 null 安全性时,库不能选择退出 null 安全性
    • 请看这个答案...并按照第二种方式stackoverflow.com/a/64124471/6813907
    【解决方案2】:

    我尝试了建议的解决方案,但我发现自己没有必要覆盖任何内容或使用其他库。怎么样?

    你可以试试这段代码:

    trailing: (shouldBeEmpty)
          ? const SizedBox()
          : Icon(
              selected
                ? Icons.keyboard_arrow_up
                : Icons.keyboard_arrow_down,
              color: Colors.red,
            ),
    

    我添加了一个附加条件,但基本上如果您想隐藏尾随,请将 SizedBox() 或任何 non-visible 小部件作为尾随。

    【讨论】:

      【解决方案3】:
              controlAffinity: ListTileControlAffinity.leading,
              leading: SizedBox.shrink(),
      

      这几乎可以消除尾随,对我来说已经足够了

      【讨论】:

      • 这适用于前导,但不适用于尾随。
      • 这会删除尾随并最小化前导。但我最终使用了来自 pub.dev 的第三方包,其中有很多而且大多数都可以让您毫无问题地删除尾随和前导。
      猜你喜欢
      • 2021-06-02
      • 2023-01-03
      • 1970-01-01
      • 2021-05-16
      • 2021-11-20
      • 1970-01-01
      • 2021-10-15
      • 1970-01-01
      相关资源
      最近更新 更多