强制容器内的小部件将自身限制为一行

时间:2018-08-02 09:57:28

标签: flutter flutter-layout

我对Flutter相对较新,并且遇到布局问题,我认为这很容易做到。我试图将MarkdownBody(其中包含一些HTML文本)呈现为ListTile的标题。如果标题太长,它将溢出。如果我可以使用Text小部件而不是MarkdownBody,则解决方案将非常简单:使用maxLines: 1overflow: TextOverflow.ellipsis。但是,由于标题包含HTML,因此我正在使用MarkdownBody,所以这就是创建标题的方式:

   return new Container(
      height: 25.0,
      child: new Row(
        crossAxisAlignment: CrossAxisAlignment.start,
        mainAxisAlignment: MainAxisAlignment.start,
        children: <Widget>[
          new Expanded(
            child: new MarkdownBody(
              data: converted,
              styleSheet: MarkdownStyleSheet(
                p: textStyle,
                strong: TextStyle(fontWeight: FontWeight.bold),
              ),
            ),
          )
        ],
      ),
    );

那是它的样子:

enter image description here

该搜索结果中的每一行都是ListTile内的Container包裹,其标题和副标题的创建如上所示。我要尝试的是如果文本太长,请确保标题和副标题都被截断。我尝试将MarkdownBody包装在各种布局小部件内;例如ContainerSizedBoxRowExpanded,但无法解决溢出问题。

我该如何实现?

2 个答案:

答案 0 :(得分:1)

您将必须修改markdown库,尤其是this method

  @override
  void visitText(md.Text text) {
    if (_blocks.last.tag == null) // Don't allow text directly under the root.
      return;

    _addParentInlineIfNeeded(_blocks.last.tag);

    final TextSpan span = _blocks.last.tag == 'pre'
      ? delegate.formatText(styleSheet, text.text)
      : new TextSpan(
          maxLines: 1,
          overflow: TextOverflow.ellipsis,
          style: _inlines.last.style,
          text: text.text,
          recognizer: _linkHandlers.isNotEmpty ? _linkHandlers.last : null,
        );

    _inlines.last.children.add(new RichText(text: span));
}

或者,您可以创建自己的小型HTML解析器,该解析器由TextSpan(基本上是带有格式的文本)组成,然后使用RichText小部件进行呈现。

答案 1 :(得分:1)

理想的解决方案是克隆原始程序包并在其中添加一个额外的小部件,以便您可以提供overflow / maxLines属性,并在overflow时中断/扩展解析逻辑和/或maxLines设置为限制要建立的子代。

在假设降价的长度对于传入数据而言最小的情况下,您可以只在自己的项目中扩展MarkdownWidget并像这样破解它(省去编写自己的解析器或必须克隆另一个项目):

import 'dart:io';

import 'package:flutter/widgets.dart';
import 'package:flutter_markdown/flutter_markdown.dart';

class SingleLineMarkdownBody extends MarkdownWidget {
  final TextOverflow overflow;
  final int maxLines;

  const SingleLineMarkdownBody(
      {Key key,
      String data,
      MarkdownStyleSheet styleSheet,
      SyntaxHighlighter syntaxHighlighter,
      MarkdownTapLinkCallback onTapLink,
      Directory imageDirectory,
      this.overflow,
      this.maxLines})
      : super(
          key: key,
          data: data,
          styleSheet: styleSheet,
          syntaxHighlighter: syntaxHighlighter,
          onTapLink: onTapLink,
          imageDirectory: imageDirectory,
        );

  @override
  Widget build(BuildContext context, List<Widget> children) {
    var richText = _findWidgetOfType<RichText>(children.first);
    if (richText != null) {
      return RichText(
        text: richText.text,
        textAlign: richText.textAlign,
        textDirection: richText.textDirection,
        softWrap: richText.softWrap,
        overflow: this.overflow,
        textScaleFactor: richText.textScaleFactor,
        maxLines: this.maxLines,
        locale: richText.locale);
    }

    return children.first;
  }

  T _findWidgetOfType<T>(Widget widget) {
    if (widget is T) {
      return widget as T;
    }

    if (widget is MultiChildRenderObjectWidget) {
      MultiChildRenderObjectWidget multiChild = widget;
      for (var child in multiChild.children) {
        return _findWidgetOfType<T>(child);
      }
    } else if (widget is SingleChildRenderObjectWidget) {
      SingleChildRenderObjectWidget singleChild = widget;
      return _findWidgetOfType<T>(singleChild.child);
    }

    return null;
  }
}