You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Flutter中实现Curved Text(弧形文本)效果

Flutter实现弧形文本的方案

方法一:使用第三方包快速实现

可以直接用flutter_curved_text包快速搭建弧形文本,步骤如下:

  1. 在pubspec.yaml中添加依赖:
dependencies:
  flutter_curved_text: ^0.3.0
  1. 简单使用示例:
import 'package:flutter/material.dart';
import 'package:flutter_curved_text/flutter_curved_text.dart';

class CurvedTextDemo extends StatelessWidget {
  const CurvedTextDemo({super.key});

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Center(
        child: CurvedText(
          text: "这是一段弧形文本示例",
          style: const TextStyle(
            fontSize: 20,
            fontWeight: FontWeight.bold,
            color: Colors.blue,
          ),
          radius: 150,
          startAngle: -120,
          endAngle: 120,
          direction: CurvedTextDirection.clockwise,
        ),
      ),
    );
  }
}

方法二:自定义CustomPaint实现(更灵活)

如果需要更精细的控制,可以通过CustomPaint手动绘制弧形文本,核心思路是将每个字符单独旋转并定位到圆弧上:

import 'package:flutter/material.dart';

class CustomCurvedText extends StatelessWidget {
  final String text;
  final TextStyle style;
  final double radius;
  final double startAngle; // 弧度值,比如-π/2对应90度向上

  const CustomCurvedText({
    super.key,
    required this.text,
    required this.style,
    required this.radius,
    this.startAngle = -0.5 * 3.1415926,
  });

  @override
  Widget build(BuildContext context) {
    return CustomPaint(
      painter: _CurvedTextPainter(
        text: text,
        textStyle: style,
        radius: radius,
        startAngle: startAngle,
      ),
      size: Size(radius * 2, radius * 2),
    );
  }
}

class _CurvedTextPainter extends CustomPainter {
  final String text;
  final TextStyle textStyle;
  final double radius;
  final double startAngle;

  _CurvedTextPainter({
    required this.text,
    required this.textStyle,
    required this.radius,
    required this.startAngle,
  });

  @override
  void paint(Canvas canvas, Size size) {
    final textSpan = TextSpan(text: text, style: textStyle);
    final textPainter = TextPainter(
      text: textSpan,
      textDirection: TextDirection.ltr,
    );
    textPainter.layout();

    // 计算每个字符的宽度总和,分配角度
    double totalWidth = 0;
    for (int i = 0; i < text.length; i++) {
      final charSpan = TextSpan(text: text[i], style: textStyle);
      final charPainter = TextPainter(
        text: charSpan,
        textDirection: TextDirection.ltr,
      );
      charPainter.layout();
      totalWidth += charPainter.width;
    }

    // 总弧度(字符总宽度对应圆弧的弧度)
    final totalAngle = totalWidth / radius;
    final center = Offset(size.width / 2, size.height / 2);

    double currentAngle = startAngle;
    double currentX = center.dx + radius * cos(currentAngle);
    double currentY = center.dy + radius * sin(currentAngle);

    for (int i = 0; i < text.length; i++) {
      final char = text[i];
      final charSpan = TextSpan(text: char, style: textStyle);
      final charPainter = TextPainter(
        text: charSpan,
        textDirection: TextDirection.ltr,
      );
      charPainter.layout();

      // 计算字符的旋转角度(垂直于圆弧切线)
      final charAngle = currentAngle + 0.5 * 3.1415926;

      canvas.save();
      // 平移到字符位置,旋转后绘制
      canvas.translate(currentX, currentY);
      canvas.rotate(charAngle);
      charPainter.paint(canvas, Offset(-charPainter.width / 2, -charPainter.height / 2));
      canvas.restore();

      // 更新下一个字符的角度和位置
      final charWidth = charPainter.width;
      final angleStep = charWidth / radius;
      currentAngle += angleStep;
      currentX = center.dx + radius * cos(currentAngle);
      currentY = center.dy + radius * sin(currentAngle);
    }
  }

  @override
  bool shouldRepaint(covariant _CurvedTextPainter oldDelegate) {
    return text != oldDelegate.text ||
        textStyle != oldDelegate.textStyle ||
        radius != oldDelegate.radius ||
        startAngle != oldDelegate.startAngle;
  }
}

使用自定义组件的示例:

class CustomCurvedTextDemo extends StatelessWidget {
  const CustomCurvedTextDemo({super.key});

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Center(
        child: CustomCurvedText(
          text: "自定义绘制的弧形文本",
          style: const TextStyle(
            fontSize: 18,
            color: Colors.red,
            fontWeight: FontWeight.w600,
          ),
          radius: 120,
          startAngle: -0.6 * 3.1415926,
        ),
      ),
    );
  }
}

以上两种方法都能实现你需要的弧形文本效果,第三方包适合快速开发,自定义绘制则能满足更多个性化需求。

内容的提问来源于stack exchange,提问作者Muhammad Zeeshan

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.08 13:34:53