Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

TextBoxComponent should have the possiblity to align text within itself #1088

Closed
spydon opened this issue Nov 11, 2021 · 7 comments · Fixed by #1620
Closed

TextBoxComponent should have the possiblity to align text within itself #1088

spydon opened this issue Nov 11, 2021 · 7 comments · Fixed by #1620
Assignees

Comments

@spydon
Copy link
Member

spydon commented Nov 11, 2021

Problem to solve

Right now the text within a TextBoxComponent can only be left aligned.

Proposal

I propose that we add a textAlign field in TextBoxConfig. The type of the field could either be TextAlign or an Anchor.

More information

@st-pasha
Copy link
Contributor

I just looked into TextBoxComponent, and can't figure out why TextBoxConfig is a separate class -- is it just a rudiment of an unfinished refactor? It doesn't seem to be used anywhere else, nor is it ever subclassed.

@spydon
Copy link
Member Author

spydon commented Nov 11, 2021

It is used in TextBoxComponent. It was a long time since it was created, but I think the idea was that you could create multiple TextBoxComponents with the same config.

@LahaLuhem
Copy link

screencap
Need this enhancement asap. No way to align the text to the center directly

@large
Copy link

large commented May 11, 2022

Totally agree! My first try on flame, but that was a flaw straight away.

I combined SpriteButtonComponent with TextBoxComponent and wanted to have centered text.
Everything is fine until you need multiline, see the difference
image

In multiline it does not look good
image

When I get warm in Flame I'll create a PR for fixing this ;)

Pst, here is the class for this drawing

import 'package:flame/components.dart';
import 'package:flame/input.dart';
import 'package:flutter/cupertino.dart';

class TextButton extends SpriteButtonComponent with HasGameRef {
  final String buttonText;

  TextButton(
      {required Vector2 position,
      required Vector2 size,
      required this.buttonText})
      : super(position: position, size: size);

  //Text properties
  late TextBoxComponent _textComponent;
  final regular = TextPaint(
      style: const TextStyle(
    fontSize: 25.0,
  ));

  @override
  Future<void>? onLoad() async {
    //Create two sprites for testing
    button = await Sprite.load('crate.png');
    buttonDown = await Sprite.load('crate2.png');

    //Add text to button
    _textComponent = TextBoxComponent(
        text: buttonText,
        textRenderer: regular, boxConfig: TextBoxConfig(growingBox: true, margins: const EdgeInsets.all(0)))
    ..position = size/2
    ..anchor = Anchor.centerLeft;

    //Align the text to center on x-axis
    _textComponent.x = (size.x - _textComponent.width) / 2;
    add(_textComponent);

    return super.onLoad();
  }
}

@large
Copy link

large commented May 11, 2022

I had a go to solve this little puzzle, and here is a way to get it as expected
Copy the TextBoxComponent to a new file: https://github.com/flame-engine/flame/blob/main/packages/flame/lib/src/components/text_box_component.dart

Rename the class to for instance MyTextBoxComponent:

class MyTextBoxComponent<T extends TextRenderer> extends TextComponent {
//(...)
  //Add this paramter
  final TextAlign textAlign; 
//(....)
  MyTextBoxComponent({
//(...)
    int? priority,
    this.textAlign = TextAlign.left, //Defaults to left alignment
  })  : _boxConfig = boxConfig ?? TextBoxConfig(),
        pixelRatio = pixelRatio ?? window.devicePixelRatio,
        super( .............

Find the _drawLine routine and change it to this:

  void _drawLine(Canvas c, String line, double dy) {
    if(textAlign == TextAlign.left)
      {
        textRenderer.render(c, line, Vector2(_boxConfig.margins.left, dy));
      }
    if(textAlign == TextAlign.center)
      {
        double _lineActualLength = getLineWidth(line, line.length);
        double _lineWidth = ( size.x - _boxConfig.margins.right - _lineActualLength  ) / 2;
        textRenderer.render(c, line, Vector2(_boxConfig.margins.left + _lineWidth, dy));
      }
    if(textAlign == TextAlign.right)
      {
        double _lineActualLength = getLineWidth(line, line.length);
        double _lineWidth = ( size.x - _boxConfig.margins.right - _lineActualLength );
        textRenderer.render(c, line, Vector2(_boxConfig.margins.left + _lineWidth, dy));
      }
  }

Text will now show correctly:
image
image

This solution is "good enough" for me.
My suggestion is to implement all TextAlign features before PR-ing this to flame; https://api.flutter.dev/flutter/dart-ui/TextAlign.html

I do not need TextAlign.start, TextAlign.justify and TextAlign.end for my project.
Also did not see a quick solution to get that working.
If someone does, please share your code to get the quality we all want in flame ;)

@spydon
Copy link
Member Author

spydon commented May 11, 2022

@large nice that you provided a work around, we had kind of forgotten about this issue. I assigned @st-pasha to it now, so it'll probably be fixed in no time!

@st-pasha
Copy link
Contributor

I propose that we add a textAlign field in TextBoxConfig. The type of the field could either be TextAlign or an Anchor.

The Anchor option is really interesting -- it would allow to control both vertical and horizontal alignment with a single parameter. At the same time, it doesn't allow the "justified" option (not sure whether it is needed though).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants