タイルが次のようになっているListViewを作成しようとしています:
しかし、私はここでいくつかの問題に直面しています。つまり、アイテムのレイアウトは
@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())
),
],
),
),
],
)
],
),
),
),
);
}
上の画像でわかるように、レイアウト階層は次のとおりです。
行->画像、列->(行->(タイトル、評価))、説明、テキスト、テキスト
創刊号
最初の問題は、タイトル、評価行内で評価を右に揃えることができないことです。そのため、タイトルを左揃えにし、評価を右揃えにします。このために、両方のウィジェットにフレックスレーティングを付けようとしましたが、そうするとすぐに両方が消えます。私が考えることができる唯一の方法は、タイトルに幅を与えることですが、それは非常にハッキーな方法であり、ほとんどのデバイスで壊れます。
第2号
説明をカードの範囲内に収めたい。ただし、説明用のコンテナに特定の幅を定義しない限り、画面の範囲内に制限することはできません。さまざまなフレックス値を使用して、Expanded、Flex、Flexibleに入れてみましたが、うまくいきませんでした。 TextウィジェットのsoftWrapプロパティを使おうとしましたが、うまくいきませんでした。これらのウィジェットのいずれかでテキストをラップするとすぐに消えます。上記のコードでは、テキストをコンテナにラップし、幅を設定しました。これは機能しますが、繰り返しになりますが、非常にハッキーで、デバイスによって外観が異なり、さらにいくつかのデバイスで機能しなくなります。
これらの問題に関するどんな助けも素晴らしいでしょう。
試行錯誤の末、ようやく欲しいものが手に入りました。
私のレイアウトは次のようになります。
@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)
),
],
),
),
],
),
),
],
),
),
);
}
私がしなければならなかったのは、私の最上位行の2番目の子を拡張ウィジェットにすることでした。コードでわかるように、(画像の後の)列をExpanded内に配置します。
以前に発生していた問題は、行の境界が無限であるため、行の列内でテキストを展開しても違いがないことでした。ただし、列全体を展開すると、画面の幅に制限されていました。それがなされるべきことです。
これがあなたの両方の問題の解決策です。
1)mainAxisAlighment.spaceBetweenを割り当てる必要があります。
そして、あなたは行ってもいいでしょう。
以下は、両方の問題を解決しているサンプルコードです。
new Column(
children: <Widget>[
new Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
new Container(
margin: const EdgeInsets.only(
top: 12.0, bottom: 10.0, left: 10.0),
child: new Text(
"Avengers: Infinity war",
style: new TextStyle(
fontSize: 18.0,
color: Colors.black,
fontWeight: FontWeight.bold,
),
),
),
new Container(
margin: const EdgeInsets.all(10.0),
child: new Text(
"8.6",
style: new TextStyle(
fontSize: 16.0,
fontWeight: FontWeight.bold,
color: Colors.grey[600]),
),
)
],
),
new Container(
margin: const EdgeInsets.only(left: 10.0, right: 10.0),
child: new Text(
"Iron Man, Thor, the Hulk and the rest of the Avengers unite to battle their most powerful enemy yet -- the evil Thanos. On a mission to collect all six Infinity Stones, Thanos plans to use the artifacts to inflict his twisted will on reality.",
softWrap: true,
maxLines: 3,
overflow: TextOverflow.Ellipsis,
),
)
],
)