diff --git a/examples/lib/stories/rendering/rendering.dart b/examples/lib/stories/rendering/rendering.dart index 8e9f7df1e..0fb17fac9 100644 --- a/examples/lib/stories/rendering/rendering.dart +++ b/examples/lib/stories/rendering/rendering.dart @@ -67,7 +67,15 @@ void addRenderingStories(Dashbook dashbook) { ) ..add( 'Rich Text', - (_) => GameWidget(game: RichTextExample()), + (context) => GameWidget( + game: RichTextExample( + textAlign: context.listProperty( + 'Text align', + TextAlign.left, + TextAlign.values, + ), + ), + ), codeLink: baseLink('rendering/rich_text_example.dart'), info: RichTextExample.description, ); diff --git a/examples/lib/stories/rendering/rich_text_example.dart b/examples/lib/stories/rendering/rich_text_example.dart index d7560f3fb..a6ce405d7 100644 --- a/examples/lib/stories/rendering/rich_text_example.dart +++ b/examples/lib/stories/rendering/rich_text_example.dart @@ -4,6 +4,10 @@ import 'package:flame/text.dart'; import 'package:flutter/painting.dart'; class RichTextExample extends FlameGame { + final TextAlign textAlign; + + RichTextExample({this.textAlign = TextAlign.left}); + static const String description = 'A non-interactive example of how to render rich text in Flame.'; @@ -23,11 +27,15 @@ class RichTextExample extends FlameGame { ), paragraph: BlockStyle( padding: const EdgeInsets.symmetric(vertical: 12, horizontal: 16), + textAlign: textAlign, background: BackgroundStyle( color: const Color(0xFF004D40), borderColor: const Color(0xFFAAAAAA), ), ), + header1: BlockStyle( + textAlign: textAlign, + ), ); final document = DocumentRoot([ HeaderNode.simple('1984', level: 1), diff --git a/packages/flame/lib/src/text/nodes/text_block_node.dart b/packages/flame/lib/src/text/nodes/text_block_node.dart index 007b6eebb..a663c4a70 100644 --- a/packages/flame/lib/src/text/nodes/text_block_node.dart +++ b/packages/flame/lib/src/text/nodes/text_block_node.dart @@ -1,3 +1,5 @@ +import 'dart:ui'; + import 'package:flame/src/text/common/utils.dart'; import 'package:flame/src/text/elements/group_element.dart'; import 'package:flame/text.dart'; @@ -26,6 +28,7 @@ abstract class TextBlockNode extends BlockNode { final lines = []; final horizontalOffset = style.padding.left; var verticalOffset = style.padding.top; + final textAlign = style.textAlign ?? TextAlign.left; while (!layoutBuilder.isDone) { final element = layoutBuilder.layOutNextLine(contentWidth); if (element == null) { @@ -36,7 +39,12 @@ abstract class TextBlockNode extends BlockNode { } else { final metrics = element.metrics; assert(metrics.left == 0 && metrics.baseline == 0); - element.translate(horizontalOffset, verticalOffset + metrics.ascent); + + final dx = horizontalOffset + + (contentWidth - metrics.width) * _relativeOffset(textAlign); + final dy = verticalOffset + metrics.ascent; + element.translate(dx, dy); + lines.add(element); verticalOffset += metrics.height; } @@ -50,4 +58,19 @@ abstract class TextBlockNode extends BlockNode { children: elements, ); } + + double _relativeOffset(TextAlign textAlign) { + return switch (textAlign) { + TextAlign.left => 0, + TextAlign.right => 1, + TextAlign.center => 0.5, + // NOTE: we do not support non-LRT text directions + TextAlign.start => 0, + TextAlign.end => 1, + // Not supported by Flame + TextAlign.justify => throw UnimplementedError( + 'The text rendering pipeline cannot justify text.', + ), + }; + } } diff --git a/packages/flame/lib/src/text/styles/block_style.dart b/packages/flame/lib/src/text/styles/block_style.dart index e30ff4089..abc1e4d3e 100644 --- a/packages/flame/lib/src/text/styles/block_style.dart +++ b/packages/flame/lib/src/text/styles/block_style.dart @@ -11,6 +11,7 @@ class BlockStyle extends FlameTextStyle { EdgeInsets? padding, this.background, this.text, + this.textAlign, }) : _margin = margin, _padding = padding; @@ -18,6 +19,7 @@ class BlockStyle extends FlameTextStyle { final EdgeInsets? _padding; final BackgroundStyle? background; final InlineTextStyle? text; + final TextAlign? textAlign; EdgeInsets get margin => _margin ?? EdgeInsets.zero; EdgeInsets get padding => _padding ?? EdgeInsets.zero; @@ -29,6 +31,7 @@ class BlockStyle extends FlameTextStyle { padding: other._padding ?? _padding, background: other.background ?? background, text: FlameTextStyle.merge(text, other.text), + textAlign: other.textAlign ?? textAlign, ); } }