flutter - 如何更改 Flutter 上的 TextPainter?

标签 flutter dart

是否可以像下图一样更改文本绘制?我需要添加两条线并且不旋转。

click here to view image

Container(
foregroundDecoration: const BadgeDecoration(
   badgeColor: Colors.green,
   badgeSize: 50,
   textSpan: TextSpan(
   text: '42',
   style: TextStyle(color: Colors.black, fontSize: 10),
   ),
   ),
),

装饰

import 'package:flutter/material.dart';
import 'dart:math' as math;

class BadgeDecoration extends Decoration {
  final Color badgeColor;
  final double badgeSize;
  final TextSpan textSpan;

  const BadgeDecoration({@required this.badgeColor, @required this.badgeSize, @required this.textSpan});

  @override
  BoxPainter createBoxPainter([onChanged]) => _BadgePainter(badgeColor, badgeSize, textSpan);
}

class _BadgePainter extends BoxPainter {
  static const double BASELINE_SHIFT = 1;
  static const double CORNER_RADIUS = 4;
  final Color badgeColor;
  final double badgeSize;
  final TextSpan textSpan;

  _BadgePainter(this.badgeColor, this.badgeSize, this.textSpan);

  @override
  void paint(Canvas canvas, Offset offset, ImageConfiguration configuration) {
    canvas.save();
    canvas.translate(offset.dx + configuration.size.width - badgeSize, offset.dy);
    canvas.drawPath(buildBadgePath(), getBadgePaint());
    // draw text
    final hyp = math.sqrt(badgeSize * badgeSize + badgeSize * badgeSize);
    final textPainter = TextPainter(text: textSpan, textDirection: TextDirection.ltr, textAlign: TextAlign.center);
    textPainter.layout(minWidth: hyp, maxWidth: hyp);
    final halfHeight = textPainter.size.height / 2;
    final v = math.sqrt(halfHeight * halfHeight + halfHeight * halfHeight) + BASELINE_SHIFT;
    canvas.translate(v, -v);
    canvas.rotate(0.785398); // 45 degrees
    textPainter.paint(canvas, Offset.zero);
    canvas.restore();
  }

  Paint getBadgePaint() => Paint()
    ..isAntiAlias = true
    ..color = badgeColor;

  Path buildBadgePath() => Path.combine(
      PathOperation.difference,
      Path()..addRRect(RRect.fromLTRBAndCorners(0, 0, badgeSize, badgeSize, topRight: Radius.circular(CORNER_RADIUS))),
      Path()
        ..lineTo(0, badgeSize)
        ..lineTo(badgeSize, badgeSize)
        ..close());
}

最佳答案

您可以复制粘贴运行下面的完整代码
您可以在旋转之前绘制并提供偏移

代码片段

TextSpan span = new TextSpan(style: new TextStyle(color: Colors.black, fontSize: 10), text: "Point");
final textPainter1 = TextPainter(text: span, textDirection: TextDirection.ltr, textAlign: TextAlign.center);
textPainter1.layout(minWidth: hyp, maxWidth: hyp);

textPainter1.paint(canvas, Offset(0.0, 5.0));
textPainter.paint(canvas, Offset(3.0, 17.0));
canvas.translate(v, -v);
canvas.rotate(0.785398);

工作演示

enter image description here

完整代码

import 'package:flutter/material.dart';
import 'dart:math' as math;

class BadgeDecoration extends Decoration {
  final Color badgeColor;
  final double badgeSize;
  final TextSpan textSpan;

  const BadgeDecoration({@required this.badgeColor, @required this.badgeSize, @required this.textSpan});

  @override
  BoxPainter createBoxPainter([onChanged]) => _BadgePainter(badgeColor, badgeSize, textSpan);
}

class _BadgePainter extends BoxPainter {
  static const double BASELINE_SHIFT = 1;
  static const double CORNER_RADIUS = 4;
  final Color badgeColor;
  final double badgeSize;
  final TextSpan textSpan;

  _BadgePainter(this.badgeColor, this.badgeSize, this.textSpan);

  @override
  void paint(Canvas canvas, Offset offset, ImageConfiguration configuration) {
    canvas.save();
    canvas.translate(offset.dx + configuration.size.width - badgeSize, offset.dy);
    canvas.drawPath(buildBadgePath(), getBadgePaint());
    // draw text
    final hyp = math.sqrt(badgeSize * badgeSize + badgeSize * badgeSize);
    final textPainter = TextPainter(text: textSpan, textDirection: TextDirection.ltr, textAlign: TextAlign.center);
    textPainter.layout(minWidth: hyp, maxWidth: hyp);
    final halfHeight = textPainter.size.height / 2;
    final v = math.sqrt(halfHeight * halfHeight + halfHeight * halfHeight) + BASELINE_SHIFT;

    TextSpan span = new TextSpan(style: new TextStyle(color: Colors.black, fontSize: 10), text: "Point");
    final textPainter1 = TextPainter(text: span, textDirection: TextDirection.ltr, textAlign: TextAlign.center);
    textPainter1.layout(minWidth: hyp, maxWidth: hyp);

    textPainter1.paint(canvas, Offset(0.0, 5.0));
    textPainter.paint(canvas, Offset(3.0, 17.0));
    canvas.translate(v, -v);
    canvas.rotate(0.785398);
    canvas.restore();
  }

  Paint getBadgePaint() => Paint()
    ..isAntiAlias = true
    ..color = badgeColor;

  Path buildBadgePath() => Path.combine(
      PathOperation.difference,
      Path()..addRRect(RRect.fromLTRBAndCorners(0, 0, badgeSize, badgeSize, topRight: Radius.circular(CORNER_RADIUS))),
      Path()
        ..lineTo(0, badgeSize)
        ..lineTo(badgeSize, badgeSize)
        ..close());
}

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {  
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(       
        primarySwatch: Colors.blue,       
        visualDensity: VisualDensity.adaptivePlatformDensity,
      ),
      home: MyHomePage(title: 'Flutter Demo Home Page'),
    );
  }
}

class MyHomePage extends StatefulWidget {
  MyHomePage({Key key, this.title}) : super(key: key);

  final String title;

  @override
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  int _counter = 0;

  void _incrementCounter() {
    setState(() {     
      _counter++;
    });
  }

  @override
  Widget build(BuildContext context) {    
    return Scaffold(
      appBar: AppBar(       
        title: Text(widget.title),
      ),
      body: Center(        
        child: Column(          
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            Container(
              foregroundDecoration: const BadgeDecoration(
                badgeColor: Colors.green,
                badgeSize: 50,
                textSpan: TextSpan(
                  text: '42',
                  style: TextStyle(color: Colors.black, fontSize: 10),
                ),
              ),
            ),
          ],
        ),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: _incrementCounter,
        tooltip: 'Increment',
        child: Icon(Icons.add),
      ),
    );
  }
}

关于flutter - 如何更改 Flutter 上的 TextPainter?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62127849/

相关文章:

flutter - 如何在Flutter中显示我的Google日历事件

flutter - 如何修复此可忽略的小部件边框

dart - 有没有人尝试过在 Dart 中使用 Firebase javascript 库?

ios - Flutter - 使用 google_maps_webservice 和 google_maps_flutter 的附近地点

python - 减少 Dart 中包装对象的数量

flutter - 如何在 flutter 中获取当前国家/地区代码

svg - 是否有混合模式来替换黑色并保留其他颜色(即白色)?

firebase - Flutter Firebase Auth : A network error (such as timeout, interrupted connection or unreachable host) 发生

flutter - 应用程序在使用 flutter 构建发布 apk 时停止工作,但在 razorpay 网关打开时在模拟器中工作

java - Dart VM服务客户端