Flutter - 检测内容溢出并剪辑它

Posted

技术标签:

【中文标题】Flutter - 检测内容溢出并剪辑它【英文标题】:Flutter - Detect content overflow and clip it 【发布时间】:2019-08-01 04:15:09 【问题描述】:

我正在尝试使用 ClipRect 并在其中使用 Column,但它似乎效果不佳。

我想要实现的是剪辑列的内容并在溢出时显示一条文本消息(如果列的内容无法在可用空间内显示)。

你有什么建议可以让我实现它吗?

import 'package:flutter/material.dart';

void main() => runApp(ContentOverflowDetectionApp());

class ContentOverflowDetectionApp extends StatelessWidget 
  @override
  Widget build(BuildContext context) 
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: Text("Overflow detection"),
        ),
        body: Stack(
          fit: StackFit.expand,
          children: [
            ClipRect(
              child: Column(
                children: [
                  Container(
                    width: 300,
                    height: 400,
                    color: Colors.green[200],
                    child: Text('first widget'),
                  ),
                  Container(
                    width: 350,
                    height: 350,
                    color: Colors.yellow[200],
                    child: Text('overflowed widget'),
                  ),
                ],
              ),
            ),
            Positioned(
              child: Align(
                alignment: FractionalOffset.bottomCenter,
                child: Text("SHOW THIS TEXT ONLY IF CONTENT HAS OVERFLOWED."),
              ),
            ),
          ],
        ),
      ),
    );
  

【问题讨论】:

您可以使用“SingleChildScrollView”而不是“列” 恐怕我不需要滚动。此外,如果示例中的“Column”考虑到它支持子而不是子列,那么我不太明白如何使用“SingleChildScrollView”代替。 【参考方案1】:

您不应该使用ClipRect 来实现您的目标。请尝试将值为Clip.antiAliasclipBehavior 参数添加到您的Stack 小部件。

import 'package:flutter/material.dart';

void main() => runApp(ContentOverflowDetectionApp());

class ContentOverflowDetectionApp extends StatelessWidget 
  @override
  Widget build(BuildContext context) 
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: Text("Overflow detection"),
        ),
        body: Stack(
          fit: StackFit.expand,
          clipBehavior: Clip.antiAlias,
          children: [
            Positioned(
              top: 0,
              child: Column(
                children: [
                  Container(
                    width: 300,
                    height: 400,
                    color: Colors.green[200],
                    child: Text('first widget'),
                  ),
                  Container(
                    width: 350,
                    height: 350,
                    color: Colors.yellow[200],
                    child: Text('overflowed widget'),
                  ),
                ],
              ),
            ),
            Positioned(
              child: Align(
                alignment: FractionalOffset.bottomCenter,
                child: Text("SHOW THIS TEXT ONLY IF CONTENT HAS OVERFLOWED."),
              ),
            ),
          ],
        ),
      ),
    );
  

这个解决方案只是修复了一个剪辑。

How to get height of a Widget? 给出了如何检查小部件高度并添加带有溢出消息的文本的答案

【讨论】:

实际上,不是 clipBehaviour 而是 Positioned 小部件在这里起到了作用【参考方案2】:

对于那些想要一个“高度限制器”(一个限制其孩子高度的小部件,如果孩子想要太高,请显示一些提示)的人,这是我的代码 sn-p 你可以复制 -并粘贴:

class HeightLimiter extends StatefulWidget 
  final Widget child;
  final double maxHeight;
  final double fadeEffectHeight;

  const HeightLimiter(Key key, this.maxHeight, this.child, this.fadeEffectHeight = 72) : super(key: key);

  @override
  _HeightLimiterState createState() => _HeightLimiterState();


class _HeightLimiterState extends State<HeightLimiter> 
  var _size = Size.zero;

  @override
  Widget build(BuildContext context) 
    return ConstrainedBox(
      constraints: BoxConstraints(
        maxHeight: widget.maxHeight,
      ),
      child: Stack(
        clipBehavior: Clip.hardEdge,
        children: [
          Positioned(
            top: 0,
            left: 0,
            right: 0,
            child: MeasureSize(
              onChange: (size) => setState(() => _size = size),
              child: widget.child,
            ),
          ),
          if (_size.height >= widget.maxHeight)
            Positioned(
              bottom: 0,
              left: 0,
              width: _size.width,
              child: _buildOverflowIndicator(),
            ),
        ],
      ),
    );
  

  Widget _buildOverflowIndicator() 
    return Container(
      height: widget.fadeEffectHeight,
      decoration: BoxDecoration(
        gradient: LinearGradient(
          begin: Alignment.bottomCenter,
          end: Alignment.topCenter,
          colors: [
            Colors.white.withAlpha(200),
            Colors.white.withAlpha(0),
          ],
          tileMode: TileMode.clamp,
        ),
      ),
    );
  

MeasureSize 只是来自https://***.com/a/60868972/4619958。

当子级太高时,结果如下所示(绿色子级溢出蓝色父级);当孩子足够矮时,没有什么特别的表现。

感谢@Aleksandr 和@Dpedrinha 的回答!

【讨论】:

以上是关于Flutter - 检测内容溢出并剪辑它的主要内容,如果未能解决你的问题,请参考以下文章

我需要剪辑或隐藏溢出它的内容,但仅限于一侧

VSCode Flutter 未检测到像素 3

使用 WrapWithOverflow 时如何使 TextBlock 呈现溢出的文本? (没有剪辑)

Flutte VS RN

Flutter 中的文本溢出的示例

文本溢出:省略号和 flex