1

I'm a beginner in Flutter, and now I try to understand how I can set for layouts of widget compression priority. What I want for example:

I have Horizontal Stack like Row, it has inside:

Some space like SizedBox, then some Text. And I want to reduce space before the text when the text is overflowing them self space.

enter image description here

os ios it resolving by compression priority in layout constraints, but how I can do the same on flutter?

my current code

          Row(
            mainAxisSize: MainAxisSize.min,
            children: <Widget>[
              SizedBox(width: titleWidth),
              Expanded(child: subline),
            ],
          )

where titleWidth is width space, should be applied when subline widget smaller than rest accessible size pinkSpace. subline is a widget. in the example, it is a Text.

but the code works only like on the card with 'But instead this ...' it doesn't reduce space before text widget.

EvGeniy Ilyin
  • 1,817
  • 1
  • 21
  • 38

3 Answers3

0

I don't see your code but you can use card widget, may it work

Zekai Demir
  • 143
  • 1
  • 10
0

Spacing widgets

Flutter have lots of widgets to help with spacing - inside widgets like Row or Column that take in a list of children.

F.ex:

  • Spacer - A widget that fills the space between the other children widgets.
  • Flexible - Wraps a widget and allows you to define a flex value to affect how much space this widget should take, compared to the other widgets in the children list.
  • Expanded - If you wrap a widget in this you make a widget fill up the remaining space.
  • ConstrainedBox - Allows setting minWidth, maxWidth, minHeight, maxHeight for the child widget.

Code example

Given your requirement:

  1. Have a indent for single line text
  2. Don't have a indent for multiline text

SizedBox is a no-go

SizedBox won't work with multiline text, since multiline Text in a Row has to be wrapped in Flexible (Flutter - multiline label inside row), and the SizedBox would always occupy whatever width you set it to - no combination of Spacer, Flexible, or Expanded seems to work here.

Alternative solution

One option is to specify a Row with mainAxisAlignment set to MainAxisAlignment.end and use a BoxConstraint with a MediaQuery for the screen width subtracted with the minWidth we want for the text container.

  • This is effectively the reverse of the SizedBox attempt.
class IndentedText extends StatelessWidget {
  const IndentedText({Key? key, required this.text, this.textMinWidth = 150}) : super(key: key);

  final String text;
  final double textMinWidth;

  @override
  Widget build(BuildContext context) {
    return Row(
      mainAxisAlignment: MainAxisAlignment.end,
      mainAxisSize: MainAxisSize.max,
      children: [
        Flexible(
          child: ConstrainedBox(
            constraints: BoxConstraints(minWidth: MediaQuery.of(context).size.width - textMinWidth),
            child: Text(text),
          ),
        ),
      ],
    );
  }
}

Then the usage of the widget

class SpacingExample extends StatelessWidget {
  const SpacingExample({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Column(
      mainAxisAlignment: MainAxisAlignment.center,
      children: [
        Card(
          child: Column(
            children: const [
              IndentedText(text: "text"),
              IndentedText(
                text:
                    "A vehicle is a object people use to get around more easily, etc etc make the text longer and multiline.",
              )
            ],
          ),
        ),
      ],
    );
  }
}

How it looks:

  • Note: For more complex use-cases when you subtract the minWidth - you might need to also subtract the size of other widgets if the layout if it have multiple Columns f.ex., and possibly the size of padding.
Tor-Martin Holen
  • 1,359
  • 1
  • 13
  • 19
  • but i need space before the text if the text doesn't overflow themself – EvGeniy Ilyin Dec 21 '21 at 22:59
  • Edited answer with one solution, a bit rough, but it works – Tor-Martin Holen Dec 22 '21 at 00:38
  • Maybe i was not clear, please see my screenshot. i look for behaving like on screenshot except the card with the text 'but instead this...'. on this card I showed current behavior. – EvGeniy Ilyin Dec 22 '21 at 01:37
  • Ahh, so you want it left-aligned to the vehicle icon when it fits and didn't want it multiline, but rather you wanted the ellipsis overflow if it expands outside the entire row? If so try setting the `Text` widget's properties: `maxLines: 1` and `overflow: TextOverflow.ellipsis` in the IndentedText widget I made. – Tor-Martin Holen Dec 22 '21 at 02:15
  • it is already done, my question is - how to reduce left space in the case when Text overflowing – EvGeniy Ilyin Dec 22 '21 at 03:24
0

try this code, I hopefully about this

  @override
  Widget build(BuildContext context) {
    return Column(
      mainAxisAlignment: MainAxisAlignment.start,
      children: [
        Expanded(
           child: Row(
        mainAxisAlignment: MainAxisAlignment.start,
        mainAxisSize: MainAxisSize.min,
        children: <Widget>[
          SizedBox(width: titleWidth),
          Expanded(child:Card( child: subline)),
        ],
      )
        
    );
  }
}
Zekai Demir
  • 143
  • 1
  • 10