如何在Flutter中实现聊天气泡状的小部件

时间:2019-06-03 03:32:47

标签: flutter flutter-layout

我想设计一个聊天气泡形状的小部件,其中将一个角固定在其中,并且其高度应适应文本的线条?现在,我使用带有一些borderRadius的ClipRRect小部件。但是我想固定一个角落。有什么建议么 ? Chat bubble shape

更新

我知道可以使用堆栈来完成此操作,但是我正在寻找更好的解决方案,因为我必须在单个视图中多次使用它,并且使用多个堆栈可能会影响性能。 (如果我错了,请在这里纠正我)

4 个答案:

答案 0 :(得分:3)

对于希望通过图书馆完成此工作的人。您可以从pub.dev中添加bubble: ^1.1.9+1(最新的)软件包,并用Bubble包装您的消息。

Bubble(
style: right ? styleMe : styleSomebody,
//Your mesasge content child here...
)

这里right是布尔值,指示气泡在右侧还是左侧,为此编写逻辑,然后在小部件内添加样式属性styleMestyleSomebody,如下所示。根据您的主题更改样式。

double pixelRatio = MediaQuery.of(context).devicePixelRatio;
double px = 1 / pixelRatio;

 BubbleStyle styleSomebody = BubbleStyle(
      nip: BubbleNip.leftTop,
      color: Colors.white,
      elevation: 1 * px,
      margin: BubbleEdges.only(top: 8.0, right: 50.0),
      alignment: Alignment.topLeft,
    );

    BubbleStyle styleMe = BubbleStyle(
      nip: BubbleNip.rightTop,
      color: Colors.grey,
      elevation: 1 * px,
      margin: BubbleEdges.only(top: 8.0, left: 50.0),
      alignment: Alignment.topRight,
    );

答案 1 :(得分:0)

对不起,我无法向您显示代码,但是我可以提出一个想法,如果正确实现它可能会起作用。假设您用ClipRect制作的小部件称为MyChatBubbleRect。现在,制作另一个使用CustomPainter绘制三角形的小部件,我们将其命名为MyChatBubbleTriangle,当然用与聊天气泡相同的颜色填充它,但是最初可以使用其他颜色进行调试。现在我们有了两个小部件,我们可以将它们彼此堆叠在一起,并在MyChatBubbleTriangle上使用Positioned小部件。像这样:

Stack(
  children : [
     MyChatBubbleRect(), // Maybe decrease the width a bit
     Positioned(
        top: 0,
        right: 0,
        child: MyChatBubbleTriangle()
     )
  ]
)

这只是我想您可以追求的想法。抱歉,无法提供正确的源代码。

答案 2 :(得分:0)

聊天身体

DecoratedBox(
    decoration: BoxDecoration(
    color: Colors.blue,
    borderRadius: BorderRadius.circular(8.0),
   ),
   child: Text("your message goes here"),
);

制作自定义三角形

class ChatBubbleTriangle extends CustomPainter {
  @override
  void paint(Canvas canvas, Size size) {
    var paint = Paint()..color = Colors.blue;

    var path = Path();
    path.lineTo(-10, 0);
    path.lineTo(0, 10);
    path.lineTo(10, 0);
    canvas.drawPath(path, paint);
  }

  @override
  bool shouldRepaint(CustomPainter oldDelegate) {
    return true;
  }
}

使用@Shababb Karim在其答案中指出的ChatBubbleTriangle小部件将Positioned() chrome.tabs.query({active:true,windowType:"normal", currentWindow: true},function(d){document.getElementById("Current-tab-id").innerHTML = d[0].id;}) chrome.tabs.query({currentWindow: true}, function(tabs) { tabs.forEach(function(tab) { console.log(tab.id); var CurrentTabId = document.getElementById('Current-tab-id').innerHTML; console.log(CurrentTabId); if(CurrentTabId == tab.id) { } else { chrome.tabs.remove(tab.id, function callback(){}) } }); });包裹在一起

答案 3 :(得分:0)

您好,我也正在寻找一个聊天气泡状的小部件,最后我做了一个。 我已经在自定义Painter中完成了此操作,但我并不擅长。 enter image description here

import 'package:flutter/material.dart';

class ChatBubble extends CustomPainter {
  final Color color;
  final Alignment alignment;

  ChatBubble({
    @required this.color,
    this.alignment,
  });

  var _radius = 10.0;
  var _x = 10.0;




  @override
  void paint(Canvas canvas, Size size) {
    if (alignment == Alignment.topRight) {
      canvas.drawRRect(
          RRect.fromLTRBAndCorners(
            0,
            0,
            size.width - 8,
            size.height,
            bottomLeft: Radius.circular(_radius),
            topRight: Radius.circular(_radius),
            topLeft: Radius.circular(_radius),
          ),
          Paint()
            ..color = this.color
            ..style = PaintingStyle.fill);
      var path = new Path();
      path.moveTo(size.width - _x, size.height - 20);
      path.lineTo(size.width - _x, size.height);
      path.lineTo(size.width, size.height);
      canvas.clipPath(path);
      canvas.drawRRect(
          RRect.fromLTRBAndCorners(
            size.width - _x,
            0.0,
            size.width,
            size.height,
            topRight: Radius.circular(_radius),
          ),
          Paint()
            ..color = this.color
            ..style = PaintingStyle.fill);
    } else {
      canvas.drawRRect(
          RRect.fromLTRBAndCorners(
            _x,
            0,
            size.width,
            size.height,
            bottomRight: Radius.circular(_radius),
            topRight: Radius.circular(_radius),
            topLeft: Radius.circular(_radius),
          ),
          Paint()
            ..color = this.color
            ..style = PaintingStyle.fill);
      var path = new Path();
      path.moveTo(0, size.height);
      path.lineTo(_x, size.height);
      path.lineTo(_x, size.height-20);
      canvas.clipPath(path);
      canvas.drawRRect(
          RRect.fromLTRBAndCorners(
            0,
            0.0,
            _x,
            size.height,
            topRight: Radius.circular(_radius),
          ),
          Paint()
            ..color = this.color
            ..style = PaintingStyle.fill);
    }
  }

  @override
  bool shouldRepaint(CustomPainter oldDelegate) {
    return true;
  }
}

复制并粘贴上方代码并粘贴到您的项目中

Align(
      alignment: alignment, //Change this to Alignment.topRight or Alignment.topLeft
      child: CustomPaint(
        painter: ChatBubble(color: Colors.blue, alignment: alignment),
        child: Container(
          margin: EdgeInsets.all(10),
          child: Stack(
            children: <Widget>[
              TextView("Hello World"),
            ],
          ),
        ),
      ),
    )

将此代码粘贴到必须显示chatBubble Widget的位置。 而且我还将此代码上传到了bitbucket ChatBubble Widget中,如果您有任何贡献,请免费提供。