Flutter 设计 Instagram 之类的气球/工具提示小部件 [英] Flutter design Instagram like balloons / tooltip widget

查看:21
本文介绍了Flutter 设计 Instagram 之类的气球/工具提示小部件的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在颤振中我想将此布局设计为小部件

当前实现的代码有这样的结果:

你能帮我解决这个设计的一些问题吗?

因为高度/重量和角应该是可定制的,我应该可以在其中放入一些小部件,例如:

class MessageClipper extends CustomClipper;{MessageClipper({this.borderRadius = 15});最终双边框半径;@覆盖路径 getClip(Size size) {双倍宽度 = size.width;双倍高度 = size.height;双倍高度 = 高度 - 高度/3;双 oneThird = 宽度/3;最终路径 = 路径()..lineTo(0, rheight - borderRadius)..cubicTo(0, rheight - borderRadius, 0, rheight, borderRadius, rheight)..lineTo(oneThird, rheight)..lineTo(width/2-borderRadius, height-borderRadius)..cubicTo(宽度/2 - 边界半径,高度 - 边界半径,宽度/2,高度,宽度/2 + 边界半径,高度 - 边界半径)..lineTo(2 * oneThird, rheight)..lineTo(width-borderRadius, rheight)..cubicTo(width - borderRadius, rheight, width, rheight, width,rheight - 边界半径)..lineTo(宽度, 0)..lineTo(0, 0);返回路径;}@覆盖bool shouldReclip(CustomClipper<Path> oldClipper) =>真的;}

解决方案

正如 pskink 在这个问题中提到的那样:

如果你想改变箭头的曲率,你可以使用TooltipShapeBorderarrowArc属性,如果你设置为0.0 它不会有任何曲率,如果您将其设置为 1.0,它将具有最大曲率.

要了解 quadraticBezierTo 的工作原理以及如何制作其他形状,请查看以下链接:Flutter 中的路径:视觉指南

in flutter i would like to design this layout as widget

and current implemented code has this result:

could you help me to fix some problem on this desing?

in that height/weight and corners should be customizable and i should can put some widget into that, for example:

class MessageClipper extends CustomClipper<Path> {
  MessageClipper({this.borderRadius = 15});
  final double borderRadius;
  @override
  Path getClip(Size size) {
    double width = size.width;
    double height = size.height;
    double rheight = height - height / 3;
    double oneThird = width / 3;

    final path = Path()
      ..lineTo(0, rheight - borderRadius)
      ..cubicTo(0, rheight - borderRadius, 0, rheight, borderRadius, rheight)
      ..lineTo(oneThird, rheight)
      ..lineTo(width/2-borderRadius, height-borderRadius)
      ..cubicTo(width / 2 - borderRadius, height - borderRadius, width / 2,
          height, width / 2 + borderRadius, height - borderRadius )
      ..lineTo(2 * oneThird, rheight)
      ..lineTo(width-borderRadius, rheight)
      ..cubicTo(width - borderRadius, rheight, width, rheight, width,
          rheight - borderRadius)
      ..lineTo(width, 0)
      ..lineTo(0, 0);
    return path;
  }

  @override
  bool shouldReclip(CustomClipper<Path> oldClipper) => true;
}

解决方案

Edit: As pskink metioned in this question: Flutter - ClipPath, this would be the correct way to achieve what you want:

class TooltipShapeBorder extends ShapeBorder {
  final double arrowWidth;
  final double arrowHeight;
  final double arrowArc;
  final double radius;

  TooltipShapeBorder({
    this.radius = 16.0,
    this.arrowWidth = 20.0,
    this.arrowHeight = 10.0,
    this.arrowArc = 0.0,
  }) : assert(arrowArc <= 1.0 && arrowArc >= 0.0);

  @override
  EdgeInsetsGeometry get dimensions => EdgeInsets.only(bottom: arrowHeight);

  @override
  Path getInnerPath(Rect rect, {TextDirection textDirection}) => null;

  @override
  Path getOuterPath(Rect rect, {TextDirection textDirection}) {
    rect = Rect.fromPoints(rect.topLeft, rect.bottomRight - Offset(0, arrowHeight));
    double x = arrowWidth, y = arrowHeight, r = 1 - arrowArc;
    return Path()
      ..addRRect(RRect.fromRectAndRadius(rect, Radius.circular(radius)))
      ..moveTo(rect.bottomCenter.dx + x / 2, rect.bottomCenter.dy)
      ..relativeLineTo(-x / 2 * r, y * r)
      ..relativeQuadraticBezierTo(-x / 2 * (1 - r), y * (1 - r), -x * (1 - r), 0)
      ..relativeLineTo(-x / 2 * r, -y * r);
  }

  @override
  void paint(Canvas canvas, Rect rect, {TextDirection textDirection}) {}

  @override
  ShapeBorder scale(double t) => this;
}

This is how to use it:

@override
Widget build(BuildContext context) {
  return Scaffold(
    appBar: AppBar(
      title: Text('Instagram Like Balloon Tooltip'),
    ),
    body: Center(
      child: Container(
        decoration: ShapeDecoration(
          color: Colors.red,
          shape: TooltipShapeBorder(arrowArc: 0.5),
          shadows: [
            BoxShadow(
                color: Colors.black26, blurRadius: 4.0, offset: Offset(2, 2))
          ],
        ),
        child: Padding(
          padding: EdgeInsets.all(16.0),
          child: Text('Text 22', style: TextStyle(color: Colors.white)),
        ),
      ),
    ),
  );
}

And this would be the result:

If you want to change the curvature of the arrow, you can use the arrowArc propery of the TooltipShapeBorder, if you set it to 0.0 it won't have any curvature and if you set it to 1.0 it will have the maximum curvature.

To see how quadraticBezierTo works and how to make other shapes check this link: Paths in Flutter: A Visual Guide

这篇关于Flutter 设计 Instagram 之类的气球/工具提示小部件的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆