Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Flutter - Alignment and Wrapping issues

I'm trying to build a ListView, where the tiles look like this: enter image description here

However, I'm facing some issues here. So the item layout is

@override
Widget build(BuildContext context) {
  return new GestureDetector(
    onTap: _onTap,
    child: new Card(
      elevation: 1.0,
      color: Colors.white,
      margin: const EdgeInsets.symmetric(vertical: 8.0, horizontal: 15.0),
      child: new Container(
        child: new Row(
          mainAxisAlignment: MainAxisAlignment.start,
          crossAxisAlignment: CrossAxisAlignment.start,
          children: <Widget>[
            new Container(
              margin: const EdgeInsets.only(right: 15.0),
              width: 100.0,
              height: 130.0,
              padding: const EdgeInsets.symmetric(
                  vertical: 10.0, horizontal: 5.0),
              decoration: new BoxDecoration(
                  shape: BoxShape.rectangle,
                  image: new DecorationImage(
                      fit: BoxFit.cover,
                      image: new NetworkImage(
                          "https://image.tmdb.org/t/p/w500" +
                              widget.movie.posterPath
                      )
                  )
              ),
            ),
            new Column(
              mainAxisAlignment: MainAxisAlignment.spaceBetween,
              mainAxisSize: MainAxisSize.min,
              crossAxisAlignment: CrossAxisAlignment.start,
              children: <Widget>[
                new Row(
                  crossAxisAlignment: CrossAxisAlignment.center,
                  children: <Widget>[
                    new Expanded(
                      flex: 0,
                      child: new Container(
                        margin: const EdgeInsets.only(
                            top: 12.0, bottom: 10.0),
                        child: new Text(widget.movie.title,
                          style: new TextStyle(
                            fontSize: 18.0,
                            color: Colors.black,
                            fontWeight: FontWeight.bold,
                          ),
                        ),
                      ),
                    ),
                    new Expanded(
                      flex: 0,
                      child: new Text(
                        widget.movie.voteAverage.toString(),
                        style: new TextStyle(
                            fontSize: 16.0,
                            fontWeight: FontWeight.bold,
                            color: Colors.grey[600]
                        ),
                      ),
                    ),
                  ],
                ),
                new Container(
                  child: new Text(widget.movie.overview,
                    softWrap: true,
                    overflow: TextOverflow.ellipsis,
                    maxLines: 3,
                  ),
                ),
                new Container(
                  margin: const EdgeInsets.only(top: 5.0),
                  child: new Row(
                    children: <Widget>[
                      new Text("Released"),
                      new Container(
                          margin: const EdgeInsets.only(left: 5.0),
                          child: new Text(widget.movie.releaseDate)
                      ),
                    ],
                  ),
                ),
                new Container(
                  margin: const EdgeInsets.only(top: 5.0),
                  child: new Row(
                    children: <Widget>[
                      new Text("Rating"),
                      new Container(
                          margin: const EdgeInsets.only(left: 5.0),
                          child: new Text(widget.movie.voteAverage.toString())
                      ),
                    ],
                  ),
                ),
              ],
            )
          ],
        ),
      ),
    ),
  );
}

The layout hierarchy, as you can see in the image above, is

Row -> Image, Column -> (Row -> (Title, Rating)), Description, Text, Text

  1. First Issue

    The first issue is that I'm unable to align the Rating to the right within the Title, Rating row. So I want the title to be left aligned, and rating to be right aligned. For this, I tried to give a flex rating to both widgets, but as soon as I do that, both disappear. The only way I can think of is to give the Title a width, but that's a very hacky way and will break on most devices.

  2. Second Issue

    I want the Description to fit within the bounds of the Card. However, unless I define a specific width to the Container for Description, I'm unable to constrain it within the bounds of the screen. I tried encasing it within an Expanded, Flex and Flexible with various flex values, but no luck. I tried to use the softWrap property of Text widget, but again no luck. As soon as I wrap the Text in any of those widgets, it disappears. In the above code I've wrapped the Text in a Container, and set a width to it. This works, but again, it's very hacky, and will look different on different device, plus will break on a few.

Any help on these issues would be great.

like image 583
Rachit Avatar asked May 11 '18 03:05

Rachit


1 Answers

After a lot of trial and error, I finally managed to get what I wanted.

My layout is like this:

@override
  Widget build(BuildContext context) {
    return new GestureDetector(
      onTap: _onTap,
      child: new Card(
        elevation: 1.0,
        color: Colors.white,
        margin: const EdgeInsets.symmetric(vertical: 8.0, horizontal: 14.0),
        child: new Row(
          crossAxisAlignment: CrossAxisAlignment.start,
          children: <Widget>[
            new Container(
              margin: const EdgeInsets.only(right: 15.0),
              width: 100.0,
              height: 150.0,
              child: new Image.network(
                  "https://image.tmdb.org/t/p/w500" +
                      widget.movie.posterPath),
            ),
            new Expanded(
              child: new Column(
                crossAxisAlignment: CrossAxisAlignment.start,
                children: <Widget>[
                  new Row(
                    children: <Widget>[
                      new Expanded(
                        child: new Container(
                          margin: const EdgeInsets.only(
                              top: 12.0, bottom: 10.0),
                          child: new Text(widget.movie.title,
                            style: new TextStyle(
                              fontSize: 18.0,
                              color: Colors.black,
                              fontWeight: FontWeight.bold,
                            ),
                          ),
                        ),
                      ),
                      new Container(
                        margin: const EdgeInsets.only(right: 10.0),
                        child: new Text(
                          widget.movie.voteAverage.toString(),
                          style: new TextStyle(
                              fontSize: 16.0,
                              fontWeight: FontWeight.bold,
                              color: Colors.grey[600]
                          ),
                        ),
                      ),
                    ],
                  ),
                  new Container(
                    margin: const EdgeInsets.only(right: 10.0),
                    child: new Text(widget.movie.overview,
                      style: new TextStyle(
                        fontSize: 16.0,
                      ),
                      maxLines: 3,
                      overflow: TextOverflow.ellipsis,
                    ),
                  ),
                  new Container(
                    margin: const EdgeInsets.only(top: 10.0),
                    child: new Row(
                      children: <Widget>[
                        new Text("RELEASED",
                          style: new TextStyle(
                            color: Colors.grey[500],
                            fontSize: 11.0,
                          ),
                        ),
                        new Container(
                            margin: const EdgeInsets.only(left: 5.0),
                            child: new Text(widget.movie.releaseDate)
                        ),
                      ],
                    ),
                  ),
                ],
              ),
            ),
          ],
        ),
      ),
    );
  }

What I had to do was make the second child of my top level row an Expanded widget. So as you can see in the code, I put my column (after the image) within an Expanded.

The problem that was happening before was that Row has infinite bounds, so making my text expanded within a row's column was not making any difference to it. However, when I put the entire column into an expanded, it was bound by the screen width. That is what needs to be done.

The final output, with the above code, looks like this. enter image description here

like image 71
Rachit Avatar answered Sep 19 '22 20:09

Rachit