Flutter 以最小宽度对齐列中的特定小部件

Flutter align specific widget in column with min width

我正在我的 flutter 应用程序上实现聊天,我希望我的聊天时间在列的右侧对齐(所有其他小部件应左对齐)。

我的问题是,当我在我的专栏中使用 alignment.bottomRight 时,它会将列宽扩展到 max(我想保留它 min)。

问题:

我想要达到的目标:

我的专栏:

return Bubble(
      margin: BubbleEdges.only(top: 5, bottom: 5),
      elevation: 0.6,
      alignment: Alignment.topLeft,
      nip: BubbleNip.leftTop,
      radius: Radius.circular(10),
      child: Column(
        crossAxisAlignment: CrossAxisAlignment.start,
        children: [
          getUserChatTitle(document['userId']),
          Padding(
            padding: const EdgeInsets.only(top: 3, bottom: 5),
            child: SelectableLinkify(
              onOpen: onOpenLink,
              text: "Text Text Text",
              textAlign:
                  intl.Bidi.detectRtlDirectionality(document['content'])
                      ? TextAlign.right
                      : TextAlign.left,
              textDirection:
                  intl.Bidi.detectRtlDirectionality(document['content'])
                      ? ui.TextDirection.rtl
                      : ui.TextDirection.ltr,
              style: TextStyle(
                fontSize: 16,
                height: 1.35,
                letterSpacing: -0.1,
                fontFamily: 'Arimo',
              ),
            ),
          ),
          Align(
            alignment: Alignment.bottomRight,
            child: Text(
              formatTimestampToString(document['timestamp']),
              textAlign: TextAlign.left,
              style: TextStyle(
                color: Colors.grey,
                fontSize: 12,
              ),
            ),
          ),
        ],
      ),
    );

替换为:

Align(
            alignment: Alignment.bottomRight,
            child: Text(
              formatTimestampToString(document['timestamp']),
              textAlign: TextAlign.right,
              style: TextStyle(
                color: Colors.grey,
                fontSize: 12,
              ),
            ),
          ),

与:

Row(
            mainAxisAlignment: MainAxisAlignment.end,
            children: [Text(
              formatTimestampToString(document['timestamp']),
              textAlign: TextAlign.right,
              style: TextStyle(
            color: Colors.grey,
            fontSize: 12,
          ),
        )],
      ),

这确实没那么容易,因为您希望气泡具有“未定义”的宽度 - 它应该适应实际消息的长度,这在运行时实际放置/绘制小部件之前是未知的。我的建议是使用 Stack - 我也在 ListView.builder 中使用它,这可能是所需的用例。请务必阅读我在代码块中的评论:

ListView.builder(
  itemCount: 5,
  itemBuilder: (context, index) => UnconstrainedBox(
    /// Decide whether a message has been received or written by yourself (left or right side)
    alignment:
        index % 2 == 0 ? Alignment.centerLeft : Alignment.centerRight,
    /// ConstrainedBox to make sure chat bubbles don't go from left to right if they are too big - you can change it or even remove it if it's not what you want
    child: ConstrainedBox(
      constraints: BoxConstraints(
          maxWidth: MediaQuery.of(context).size.width / 1.5),
      child: Bubble(
        margin: BubbleEdges.only(top: 5, bottom: 5),
        elevation: 0.6,
        /// Alignment and nip has to be adjusted here too
        alignment:
            index % 2 == 0 ? Alignment.topLeft : Alignment.topRight,
        nip: index % 2 == 0 ? BubbleNip.leftTop : BubbleNip.rightTop,
        radius: Radius.circular(10),
        child: Stack(
          children: [
            Column(
              crossAxisAlignment: CrossAxisAlignment.start,
              children: [
                Text('TestUser'),
                Padding(
                  padding: const EdgeInsets.only(top: 3, bottom: 5),
                  child: Text(
                    'Text ' * Random().nextInt(50),
                    style: TextStyle(
                      fontSize: 16,
                      height: 1.35,
                      letterSpacing: -0.1,
                    ),
                  ),
                ),
                /// Adjust the space you want between the actual message and the timestamp here, you could also use a Text widget to use the same height as the actual timestamp - as you like
                SizedBox(height: 18.0),
              ],
            ),
            Positioned(
              bottom: 0,
              right: 0,
              child: Text(
                '08.09.2021',
                style: TextStyle(
                  color: Colors.grey,
                  fontSize: 12,
                ),
              ),
            ),
          ],
        ),
      ),
    ),
  ),
),