Flutter 自定义Widget 圆角矩形加三角指示器

一般app设计中都会有气泡提示,这个时候就需要用到切图了,在flutter中不管你信不信 反正对于.9的这块还是很不友好的,使用起来特别麻烦。要是安卓中这或许会很简单。
但即使支持.9 如果气泡样式很多,对于app的包大小占用其实还是有那么一丢丢的影响的。
我采用了是用代码的方式实现了圆角矩形带三角指示器
现看看效果吧
在这里插入图片描述

在这里插入图片描述
上面就是ui给出的效果,其中底部的三角形距离左边的位置还是动态可变,背景颜色还是渐变的。
使用了CustomPaint方式实现一套圆角矩形加指示器的控件,下面是代码实现

ExRoundTriangleWidget

import 'dart:math';

import 'package:flutter/material.dart';

import 'ex_text.dart';

/// 圆角矩形 + 三角提示布局
class ExRoundTriangleWidget extends StatelessWidget {
  /// 子布局
  final String data; // 文案
  final TextStyle textStyle;
  final double roundRadius; // 圆角半径
  final double triangleWidth; // 三角形的宽度
  final double triangleHeight; // 三角形的高度
  final double triangleDistance; // 三角形距离左边的距离
  final bool triangleFromLeft; // 从左边计算距离
  final LinearGradient gradient; // 渐变颜色
  final Color bordColor; // 边框颜色
  final PaintingStyle paintingStyle; // 是填充还是边框
  final double strokeWidth; // 画笔宽度
  final bool isCenter; // 是否居中
  final double horizontal; // 水平间距

  ExRoundTriangleWidget(
      {this.data,
        this.textStyle,
        this.roundRadius,
        this.triangleWidth,
        this.triangleHeight,
        this.triangleDistance,
        this.triangleFromLeft,
        this.gradient,
        this.bordColor,
        this.paintingStyle,
        this.strokeWidth,
        this.isCenter,
        this.horizontal});

  @override
  Widget build(BuildContext context) {
    return CustomPaint(
      painter: ExRoundTrianglePainter(
        roundRadius: roundRadius ?? 12,
        triangleWidth: triangleWidth ?? 12,
        triangleHeight: triangleHeight ?? 12,
        triangleDistance: triangleDistance ?? 8,
        triangleFromLeft: triangleFromLeft ?? true,
        gradient: gradient,
        bordColor: bordColor,
        paintingStyle: paintingStyle,
        strokeWidth: strokeWidth,
        isCenter: isCenter,
      ),
      child: Row(
        mainAxisSize: MainAxisSize.min,
        children: [
          Container(
            height: (roundRadius ?? 12) * 2 + (triangleHeight ?? 12),
            alignment: Alignment.center,
            child: Container(
              padding: EdgeInsets.symmetric(horizontal: horizontal),
              height: (roundRadius ?? 12) * 2,
              alignment: Alignment.center,
              child: ExText(
                data,
                textStyle,
              ),
            ),
          ),
        ],
      ),
    );
  }
}

/// 圆角矩形 带有三角指示器
class ExRoundTrianglePainter extends CustomPainter {
  Paint _paint;
  final double roundRadius; // 圆角半径
  final double triangleWidth; // 三角形的宽度
  final double triangleHeight; // 三角形的高度
  final double triangleDistance; // 三角形距离左边的距离
  final bool triangleFromLeft; // 从左边计算距离
  LinearGradient gradient; // 渐变颜色
  final Color bordColor; // 边框颜色
  final PaintingStyle paintingStyle; // 是填充还是边框
  final double strokeWidth; // 画笔宽度
  final bool isCenter; // 是否居中
  final double horizontal; // 水平间距

  ExRoundTrianglePainter(
      {this.roundRadius = 12,
        this.triangleWidth = 12,
        this.triangleHeight = 12,
        this.triangleDistance = 16,
        this.triangleFromLeft = true,
        this.gradient,
        this.bordColor,
        this.paintingStyle = PaintingStyle.fill,
        this.strokeWidth = 1,
        this.isCenter = false,
        this.horizontal = 12}) {
    _paint = Paint()
      ..strokeCap = StrokeCap.butt
      ..isAntiAlias = true //是否启动抗锯齿
      ..style = paintingStyle ?? PaintingStyle.fill //绘画风格,默认为填充
      ..filterQuality = FilterQuality.high //颜色渲染模式的质量
      ..strokeWidth = strokeWidth ?? 15.0 //画笔的宽度
      ..color = bordColor ?? Colors.transparent; // 边框颜色
  }

  @override
  void paint(Canvas canvas, Size size) {
    final rect = new Rect.fromLTWH(0.0, 0.0, size.width, size.height);
    if (gradient != null) {
      _paint.shader = gradient.createShader(rect);
    }

    Path path = Path();
    // 左半圆
    path.addArc(new Rect.fromLTWH(0, 0, roundRadius * 2, roundRadius * 2), 90.0 * (pi / 180.0), 180.0 * (pi / 180.0));
    path.lineTo(size.width - roundRadius, 0);
    // 右半圆
    path.addArc(new Rect.fromLTWH(size.width - roundRadius * 2, 0, roundRadius * 2, roundRadius * 2),
        270.0 * (pi / 180.0), 180.0 * (pi / 180.0));

    double reallyTriangleStartDistance; // 三角形的x轴的起始距离 根据triangleFromLeft计算 从右到左开始的
    double reallyTriangleCenterDistance; // 三角形的x轴的中见点距离 根据triangleFromLeft计算 从右到左开始的
    double reallyTriangleEndDistance; // 三角形的x轴的结束距离 根据triangleFromLeft计算 从右到左开始的
    if (isCenter ?? false) {
      reallyTriangleStartDistance = size.width / 2 - triangleWidth / 2;
      reallyTriangleCenterDistance = size.width / 2;
      reallyTriangleEndDistance = size.width / 2 + triangleWidth / 2;
    } else {
      if (triangleFromLeft) {
        reallyTriangleStartDistance = roundRadius + triangleDistance + triangleWidth;
        reallyTriangleCenterDistance = reallyTriangleStartDistance - triangleWidth / 2;
        reallyTriangleEndDistance = reallyTriangleCenterDistance - triangleWidth / 2;
      } else {
        reallyTriangleStartDistance = size.width - roundRadius - triangleDistance;
        reallyTriangleCenterDistance = reallyTriangleStartDistance - triangleWidth / 2;
        reallyTriangleEndDistance = reallyTriangleCenterDistance - triangleWidth / 2;
      }
    }

    // 三角形
    path.lineTo(reallyTriangleEndDistance, roundRadius * 2);
    path.lineTo(reallyTriangleCenterDistance, roundRadius * 2 + triangleHeight);
    path.lineTo(reallyTriangleStartDistance, roundRadius * 2);

    path.lineTo(roundRadius, roundRadius * 2);

    canvas.drawPath(path, _paint);
  }

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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值