How to Add Text Border or Text Stroke in Flutter


Hello, and welcome

I am Joseph and I will be writing on how to add text stroke in flutter.

As at the time of this writing, there was an issue raised on Github by PieterAelse and as a game developer, I also needed to use this feature.



After searching, I found this comment by Aleh on Stackoverflow.

I made a Dart package and published it on Dart pub
You can also find the package on Github

Here is the source code as at the time of this writing:
import 'package:flutter/widgets.dart';

/// Adds stroke to text widget
/// {@tool sample}
/// We can apply a very thin and subtle stroke to a [Text]
/// ```dart
/// BorderedText(
///   strokeWidth: 1.0,
///   child: Text(
///     'Bordered Text',
///     style: TextStyle(
///       decoration: TextDecoration.none,
///       decorationStyle: TextDecorationStyle.wavy,
///       decorationColor: Colors.red,
///     ),
///   ),
/// )
/// ```
/// {@end-tool}
class BorderedText extends StatelessWidget {
  BorderedText({
    this.strokeCap = StrokeCap.round,
    this.strokeJoin = StrokeJoin.round,
    this.strokeWidth = 6.0,
    this.strokeColor = const Color.fromRGBO(53, 0, 71, 1),
    @required this.child,
  }) : assert(child != null);

  /// the stroke cap style
  final StrokeCap strokeCap;

  /// the stroke joint style
  final StrokeJoin strokeJoin;

  /// the stroke width
  final double strokeWidth;

  /// the stroke color
  final Color strokeColor;

  /// the `Text` widget to apply stroke on
  final Text child;

  @override
  Widget build(BuildContext context) {
    TextStyle style;
    if (child.style != null) {
      style = child.style.copyWith(
        foreground: Paint()
          ..style = PaintingStyle.stroke
          ..strokeCap = strokeCap
          ..strokeJoin = strokeJoin
          ..strokeWidth = strokeWidth
          ..color = strokeColor,
        color: null,
      );
    } else {
      style = TextStyle(
        foreground: Paint()
          ..style = PaintingStyle.stroke
          ..strokeCap = strokeCap
          ..strokeJoin = strokeJoin
          ..strokeWidth = strokeWidth
          ..color = strokeColor,
      );
    }
    return Stack(
      alignment: Alignment.center,
      textDirection: TextDirection.ltr,
      children: [
        Text(
          child.data,
          style: style,
          maxLines: child.maxLines,
          overflow: child.overflow,
          semanticsLabel: child.semanticsLabel,
          softWrap: child.softWrap,
          strutStyle: child.strutStyle,
          textAlign: child.textAlign,
          textDirection: child.textDirection,
          textScaleFactor: child.textScaleFactor,
          textWidthBasis: child.textWidthBasis,
        ),
        child,
      ],
    );
  }
}

So, what do we have here, a Stack with two children, the first item being:
...
        Text(
          child.data,
          style: style,
          maxLines: child.maxLines,
          overflow: child.overflow,
          semanticsLabel: child.semanticsLabel,
          softWrap: child.softWrap,
          strutStyle: child.strutStyle,
          textAlign: child.textAlign,
          textDirection: child.textDirection,
          textScaleFactor: child.textScaleFactor,
          textWidthBasis: child.textWidthBasis,
        ),
...
The above creates a copy of the Text widget, puts it behind the original text and replaces the color with stroke using all the stroke styles supplied.
With this setup, we need not bother about other styles attached to the original Text widget, everything is copied :).

Using shadows as a temporary hack, I got this:


compared to using the package above which gives:


I hope this helps...

Comments

Post a Comment

We Love Comments