基于像 Telegram 聊天信使中那样的换行文本的子小部件的复杂对齐

2024-03-03

我的目标是重现 Telegram(以及其他一些聊天应用程序)用于聊天消息气泡的复杂布局。气泡并不复杂,但事实证明,让气泡中的文本与日期很好地对齐却异常复杂:

一个相似的帖子已在这里发布并回复 https://stackoverflow.com/a/53910745,但关键的是它不能正确处理文本换行(下面详述的情况 #1 和 #2),因为 padding-right 保持不变,浪费了大量的屏幕空间,而且看起来很糟糕。 (如果还不清楚,请参见这里:2 https://i.stack.imgur.com/wYzMG.png).

我已经编译了我认为的 3 个“用例”来重现上图中的布局:

Case #1:是迄今为止最复杂的,它似乎是日期小部件的一个小容器,占用了最少的空间,可能是 mainAxisSize 设置为 min 的一行。复杂的部分在于如何允许文本在上方和旁边流动,同时自然换行以避免任何重叠。

Case #2:如果上面的 #1 重叠,由于文本行的字符数量几乎完美(以便不会自然换行),它将转换到下面的情况 #2 中看到的布局,该布局似乎是一个包含两个嵌套的列行。

Case #3:这是迄今为止最容易单独实现的,并且可以通过多种方式完成,最简单的是带有两个文本小部件的单行。我相当确定,如果解决方案能够实现上述#1 和#2,那么这个解决方案应该是免费的。

我尝试过的:将两者堆叠起来,将日期包裹在一个Positioned和类似的东西bottom: 0, right: 15。如果您添加至少 25 的 padding-right,这基本上只能实现情况 #1。

我还尝试过 RichText,它是迄今为止最有前途的,它可以处理所有情况,但远没有 telegram 所做的那么优雅。这样做的主要缺点是我仍然需要使用某种堆栈来放置“已发送和已查看”图标复选标记,因为图标不能包含在 RickText 跨度中......所以我仍然需要一些向右填充 + 底部填充,这样它们就不会重叠。这是该代码和下面的图片:

RichText(
  text: TextSpan(
    text: _message.textContent,
    style: DefaultTextStyle.of(context).style.merge(TextStyle(fontSize: 16)),
    children: <TextSpan>[
      TextSpan(text: ' ' + DateFormat('H:mm a').format(_message.createdDate.toLocal()).toString(),
        style: Theme.of(context).textTheme.caption.merge(
          TextStyle(
            fontSize: 10,
          )
        ),
      ),
    ],
  ),
),

理想情况下,日期将是一个单独的小部件,并且两者将与 spaceBetween 灵活对齐,因此日期始终保持在右下角,如上面的电报图像所示。 哦,我正在使用bubble: ^1.1.9+1实际聊天气泡的小部件。


找到了解决方案,并对其如此简单的感觉感到非常愚蠢,但不能抱怨,因为它完美地工作:

Text(
  _message.textContent + '                ',
  style: DefaultTextStyle.of(context).style.merge(TextStyle(fontSize: 16)),
),

这里的“魔力”是通过在消息末尾添加 30 个左右的空格,您可以为换行文本小部件的底行提供完美的填充量。无需复杂或昂贵的重新绘制或布局逻辑。

确保在空格字符串的末尾放置一个非打印字符,否则 Flutter 将执行某种操作trimRight()默认情况下在您的文本小部件上,它将不起作用。我用了U+202F https://en.wikipedia.org/wiki/Non-breaking_space#Width_variation,如果您从此处复制代码(并且 StackOverflow 不会自动删除这些字符,它应该可以工作)。

将上面的文本小部件放入堆栈中,并将日期/图标放置在右下角,如下所示:

Positioned(
  width: 60,
  height: 9,
  right: 0,
  bottom: 0,
  child: Row(
    mainAxisSize: MainAxisSize.min,
    mainAxisAlignment: MainAxisAlignment.end,
    children: <Widget>[
      Text(
        DateFormat('H:mm a').format(_message.createdDate.toLocal()).toString(),
        style: Theme.of(context).textTheme.caption.merge(TextStyle(fontSize: 10)),
        textAlign: TextAlign.right,
      ),
      Padding(
        padding: const EdgeInsets.only(left: 4.0),
        child: Icon(Icons.done_all, size: 13),
      )
    ],
  ),
),
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

基于像 Telegram 聊天信使中那样的换行文本的子小部件的复杂对齐 的相关文章

随机推荐