もっぺんプログラミング(´・ω・`)

もっぺん頑張って副業プログラマを目指してます。

Flutter動画やってみよ(Foodアプリ)5/5

YoutubeのFlutter UI作成動画トライの続きです。

前回はこちら。

食べ物の横スクロール一覧を足していきます。

小見出しを付ける

カテゴリの下に、小見出しをつけます。

      SizedBox(height: 10, ),
    ],
  ),
),
FadeAnimation(1, Padding(
  padding: EdgeInsets.all(20),
  child: Text('Free Delivery', style: TextStyle(color: Colors.grey[700], fontSize: 20, fontWeight: FontWeight.bold))
))

この動画では、Widget間の余白を作るのに、Paddingの他にもSizedBoxが頻繁に使われていますね。
どういう使い分けなんだろう。

f:id:momoizo:20200516143602p:plain
小見出し追加

小見出しが追加されましたが、センタリングされています。 左寄せに変更します。

body: SafeArea(
  child: Column(
    crossAxisAlignment: CrossAxisAlignment.start,

f:id:momoizo:20200516145336p:plain

食べ物画像を表示する

画像の表示エリアを追加します。

FadeAnimation(1, Padding(
  padding: EdgeInsets.all(20),
  child: Text('Free Delivery', style: TextStyle(color: Colors.grey[700], fontSize: 20, fontWeight: FontWeight.bold))
)),
Expanded(
  child: Padding(
    padding: EdgeInsets.symmetric(horizontal: 20.0),
    child: ListView(
      scrollDirection: Axis.horizontal,
      children: <Widget>[
        FadeAnimation(2, makeItem(image: 'assets/images/one.jpg')), 
      ],
    )
  )
),
SizedBox(
  height: 30,
)

今後、複数のアイテムを並べることを想定して、画像表示エリアを生成する makeItem 関数を用意します。
関数は以下です。

  Widget makeItem({image}) {
    return AspectRatio(
      aspectRatio: 1 / 1.4,
      child: GestureDetector(
        child: Container(
          color: Colors.red,
        )
      )
    );
  }

f:id:momoizo:20200516150820p:plain

赤いエリアが表示されました。 ここに画像をはめ込んでいきます。

赤いエリアは、左右の画面の境界線にスワイプすると自然に戻ってきます。 (動きは、Youtubeの 22:00 頃を見てね)

これは、GestureDetector Widgetのおかげかな?

makeItem 関数を書き換えて、画像をはめ込みます。

  Widget makeItem({image}) {
    return AspectRatio(
      aspectRatio: 1 / 1.4,
      child: GestureDetector(
        child: Container(
          decoration: BoxDecoration (
            image: DecorationImage(
              image: AssetImage(image),
              fit: BoxFit.cover,
            )

引数に指定される画像は、アセットのパスなので AssetImage で読み込んでいます。

f:id:momoizo:20200516154235p:plain

美味しそうなピザの画像が出ました!
次に画像に、価格などの文字を重ねるため、黒いグラデーションをかけます。

画像に文字を重ねる

画像に文字を重ねる箇所に、うっすら黒いグラデーションをかけます。

child: Container(
  decoration: BoxDecoration (
    image: DecorationImage(
      image: AssetImage(image),
      fit: BoxFit.cover,
    )
  ),
  child: Container(
    decoration: BoxDecoration(
      gradient: LinearGradient(
        begin: Alignment.bottomCenter,
        stops: [.2, .9],
        colors:[
          Colors.black.withOpacity(.9),
          Colors.black.withOpacity(.3),
        ]
      )
    ),
    child: Padding(
      padding: EdgeInsets.all(20.0),
      child: Column(
        children: <Widget>[
          Align(
            alignment: Alignment.topRight,
            child: Icon(Icons.favorite, color: Colors.white, ),
          )
        ],
      )
    )
  )

画像を配置したコンテナに、グラデーション用のコンテナを追加します。 ついでに、お気に入りアイコンも右上に追加します。

f:id:momoizo:20200516161436p:plain

動画では画面サイズピッタリなのに 僕のは、はみ出してしまってる・・・なぜだ・・・

基本の表示が出来たので、画像を3枚に増やします。

child: ListView(
  scrollDirection: Axis.horizontal,
  children: <Widget>[
    FadeAnimation(1.4, makeItem(image: 'assets/images/one.jpg')), 
    FadeAnimation(1.5, makeItem(image: 'assets/images/two.jpg')), 
    FadeAnimation(1.6, makeItem(image: 'assets/images/three.jpg')), 
  ],

f:id:momoizo:20200517111157p:plain

画像の間隔が詰まりすぎているので、余白を付けます。

  Widget makeItem({image}) {
    return AspectRatio(
      aspectRatio: 1 / 1.5, // ← 1.4 を 1.5 に。
      child: GestureDetector(
        child: Container(
          margin: EdgeInsets.only(right: 20), // margin 設定を追加

Container の右側に margin をつけました。 合わせて、aspectRatio の設定も変更しています。 これで、1画面に収まるようになりました。

f:id:momoizo:20200517112654p:plain

最後に、価格と商品名を追加します。

child: Column(
  crossAxisAlignment: CrossAxisAlignment.start, // ← 左寄せ
  mainAxisAlignment: MainAxisAlignment.spaceBetween, // ← 文字を下側に
  children: <Widget>[
    Align(
      alignment: Alignment.topRight,
      child: Icon(Icons.favorite, color: Colors.white, ),
    ),
    Column(
      crossAxisAlignment: CrossAxisAlignment.start, // ← 左寄せ
      children: <Widget>[ // ←テキスト追加
        Text("\$ 15.00", style: TextStyle(color: Colors.white, fontSize: 40, fontWeight: FontWeight.bold)),
        SizedBox(height: 10,), ← 行間は、SizedBoxで調整
        Text("Vegetarian Pizza", style: TextStyle(color: Colors.white, fontSize: 20)),
      ],
    )

f:id:momoizo:20200517115354p:plain

それっぽい感じに出来ました!

最後に、起動ページをStartupに戻して動作確認すれば終了です。

void main() => runApp(
  MaterialApp(
    debugShowCheckedModeBanner: false,
    theme: ThemeData(fontFamily: 'Roboto'),
    home: StarterPage(), // ← もとのStarterPage から始まるように戻します。
  )
);