围绕文本包装容器以用于聊天气泡

Posted

技术标签:

【中文标题】围绕文本包装容器以用于聊天气泡【英文标题】:Wrapping container around text for chat buble 【发布时间】:2019-08-05 10:40:19 【问题描述】:

我正在尝试创建聊天气泡并让它们环绕文本而不扩展到屏幕的另一端。我已经看到了有关如何执行此操作的其他线程,并尝试实现它,但没有一个有效。以下是我看到并尝试实施建议修复的线程:

Flutter- wrapping text

Container text wrap

Wrap text in container without using a fixed width in Flutter

目前,当我的容器中有背景时会发生这种情况:

我的代码:

Widget build(BuildContext context) 
return new SizeTransition(
    sizeFactor: new CurvedAnimation(
        parent: animationController.view,
        curve: Curves.easeOut),
    axisAlignment: 0.0, 
    child: new Container(
        decoration: BoxDecoration(
          border: Border.all(
            color: (text[0]=='r') ? lightVioletBlue :mintgreen,
            width: 2.0,
            style: BorderStyle.solid,
          ),
          borderRadius:  BorderRadius.all(Radius.circular(20)),
          color: (text[0] == 'r') ? lightVioletBlue:mintgreen,
        ),
        margin: const EdgeInsets.symmetric(vertical: 10.0),
        child: new Row(           
          mainAxisSize: MainAxisSize.min,            
          children: <Widget>[
            new Container(
              margin: const EdgeInsets.only(right: 16.0),
              child: (text[0] == 'r') //If first letter is an r, then it indicates it's a reply.
                  ? new CircleAvatar(child: new Text(_otherName[0]))
                  : null
            ),
            new Expanded(
              child: new Column(
                  crossAxisAlignment: (text[0] == 'r') //If first letter is an r, then it indicates it's a reply.
                      ? CrossAxisAlignment.start
                      : CrossAxisAlignment.end,
                  children: <Widget>[
                    new Text((text[0] == 'r') ? _otherName : _name, //If first letter is an r, then it indicates it's a reply.
                        style: (text[0] == 'r') ? TextStyle(color: Colors.white) : Theme.of(context).textTheme.subhead),
                    new Container(
                      margin: const EdgeInsets.only(top: 5.0),
                      child: (text[0] == 'r') //If first letter is an r, then it indicates it's a reply.
                          ? new Text(text.substring(1), style: TextStyle(color: Colors.white))
                          : new Text(text),
                    ),
                  ],
                ),                 
            ),
            new Container(
                margin: const EdgeInsets.only(left: 16.0),
                child: (text[0] == 'r') //If first letter is an r, then it indicates it's a reply.
                    ? null
                    : new CircleAvatar(child: new Text(_name[0]))),
            ],
          ),
        ) //new
    );   

我尝试在父容器上添加约束,但这需要我创建一个固定大小(至少根据我自己对颤振的理解),并且容器仍然从左侧开始。因此,来自“Ken”的消息会出现在容器的右侧,但容器会出现在屏幕中间。

【问题讨论】:

应该是,简而言之,Row(Expanded(Text(''))), Container(Text('Ken')))。即在气泡容器之前使用 Expanded emty Text。 什么意思?我尝试将 Expanded 添加到 Expanded 内的文本部分,并删除了扩展。尽管这短暂地奏效了,但一旦我从父容器中删除了约束,一切都崩溃了。 不,您的 Expanded 在气泡容器内,我的意思是在气泡容器外有一个 Expanded EMPTY Text。 在气泡容器之外是指我的行小部件吗? 再添加一个行小部件 【参考方案1】:

您可以将整个消息气泡包装在 Row 中,并将 Spacer() 添加为另一个孩子:

Row(
  children: <Widget>[ messageBubble, Spacer() ]
),

将它应用到您的代码中,我们会得到这样的结果(我还优化了一些其他代码):

Widget build(BuildContext context) 
  bool isReply = (text[0] == r);
  String name = isReply ? _otherName : name;

  Widget profilePicture = Container(
    padding: const EdgeInsets.symmetric(horizontal: 16),
    child: CircleAvatar(child: Text(name[0]))
  );

  Widget messageText = Column(
    crossAxisAlignment: isReply ? CrossAxisAlignment.start : CrossAxisAlignment.end,
    children: <Widget>[
      Text(name,
        style: isReply
          ? TextStyle(color: Colors.white)
          : Theme.of(context).textTheme.subhead
      ),
      SizedBox(height: 5),
      isReply ? Text(text.substring(1), style: TextStyle(color: Colors.white))
        : Text(text),
    ],
  );

  Widget messageBubble = SizeTransition(
    sizeFactor: CurvedAnimation(
      parent: animationController.view,
      curve: Curves.easeOut
    ),
    axisAlignment: 0, 
    child: Container(
      decoration: BoxDecoration(
        border: Border.all(
          color: isReply ? lightVioletBlue : mintgreen,
          width: 2,
          style: BorderStyle.solid,
        ),
        borderRadius: BorderRadius.circular(20),
        color: isReply ? lightVioletBlue : mintgreen,
      ),
      margin: const EdgeInsets.symmetric(vertical: 10),
      child: Row(
        mainAxisSize: MainAxisSize.min,            
        children: isReply
          ? <Widget>[ profilePicture, messageText ]
          : <Widget>[ messageText, profilePicture ],
      ),
    ),
  );

  return Row(
    children: isReply
      ? <Widget>[ messageBubble, Spacer(), ]
      : <Widget>[ Spacer(), messageBubble ]
  );

另请注意,您不应将消息文本用作回复的区分因素(如果消息以小写 r 开头...?)

【讨论】:

谢谢!是的,我知道我不应该将消息文本用作区分因素。这只是一个临时解决方案,直到我完全实现了这个应用程序的后端。不过谢谢你的帮助,我把它整理好了!

以上是关于围绕文本包装容器以用于聊天气泡的主要内容,如果未能解决你的问题,请参考以下文章

聊天界面之气泡文本cell使用Autolayout

调整放置区域的大小以破坏气泡

iOS绘制聊天气泡

请教仿微信聊天气泡效果 在ios中是怎么实现的

如何通过反应原生天才聊天设置气泡中显示的图像尺寸?

Swift 聊天气泡图片拉伸