リバース・エンジニアリング

Flultterとテックブログと時々iOS

45.【AppleMusicクローン】セクション2 のウィジェットを共通化する

Apple Music のクローンアプリを開発していて気づいたことがある。 前回はセクション2 のレイアウトを実装していて今回はセクション3 のレイアウトを実装するわけですが、

セクション2

f:id:qed805:20200416000033p:plain:w375
section 2

セクション3

f:id:qed805:20200416000118p:plain:w375
section 3

割とデザインが似ているわけである(笑)。

そして、次のセクション4 なのですが、

セクション 4

f:id:qed805:20200416000235p:plain:w375
section 4

画像サイズだけでなくテキストの位置もセクション2 と同じでありました。

セクション3からは「使い回す」事を意識してウィジェットを組み立てることにしました。 さらにセクション2は前回のようなindex単位のページングスクロールはなく普通のスクロールでした。

ということで、セクション3のレイアウトはセクション2のレイアウトをそのまま使い回せます。 違いは画像サイズと画像の下にはテキストが一つしかないことです。

ソースコードについて

それを意識してサクッとセクション3 のレイアウトを作っていきます。 セクション3なのでthird_section_item.dartとファイル名を命名しています。

third_section_item.dart

import 'package:flutter/material.dart';

class ThirdSectionItem extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Container(
      height: 150,
      child: ListView(
        scrollDirection: Axis.horizontal,
        children: <Widget>[
          Container(
            margin: EdgeInsets.only(left: 20),
            child: _contentItem('assets/images/image4.png'),
          ),
          Container(
            margin: EdgeInsets.only(left: 5.0),
            child: _contentItem('assets/images/image5.png'),
          ),
          Container(
            margin: EdgeInsets.only(left: 5.0),
            child: _contentItem('assets/images/image4.png'),
          ),
          Container(
            margin: EdgeInsets.only(left: 5.0),
            child: _contentItem('assets/images/image5.png'),
          ),
          Container(
            margin: EdgeInsets.only(left: 5.0),
            child: _contentItem('assets/images/image4.png'),
          ),
          Container(
            margin: EdgeInsets.only(left: 5.0, right: 20),
            child: _contentItem('assets/images/image5.png'),
          ),
        ],
      ),
    );
  }

  Widget _contentItem(String imageString) {
    return Column(
      crossAxisAlignment: CrossAxisAlignment.start,
      children: <Widget>[
        Image.asset(imageString),
        Text('モチベーション'),
      ],
    );
  }
}

また、セクション3のヘッダー部分はセクション2のヘッダーを使い回せます。 一つだけ違いがあって、「すべて見る」のボタンがないことです。

そこで、前回作成したSecondSectionHeaderItem クラスで「すべて見る」のボタンをフラグで表示・非表示の切り替えができるようになればOKです。 また、このクラスは他のセクションでも使い回せるので「SectionHeaderItem」と命名を変更しました。

section_header_item.dart

import 'package:flutter/material.dart';

class SectionHeaderItem extends StatelessWidget {

  final String title;
  final bool isVisible;

  SectionHeaderItem({@required this.title, @required this.isVisible});

  @override
  Widget build(BuildContext context) {
    return Row(
      mainAxisAlignment: MainAxisAlignment.spaceBetween,
      children: <Widget>[
        Padding(
          padding: EdgeInsets.only(left: 20),
          child: Text(
            title,
            style: TextStyle(
                fontSize: 17, fontWeight: FontWeight.bold),
          ),
        ),
        FlatButton(
          onPressed: () {},
          child: Visibility(
            visible: isVisible,
            child: Text(
              'すべて見る',
              style: TextStyle(fontSize: 10, color: Colors.pink),
            ),
          ),
        )
      ],
    );
  }
}

FlatButtonchildVisibilityウィジェットを乗せてvisibleのフラグ管理でそれを実現させています。 最後にContentSliverListクラスでセクション3 に「アクティビティ & ムード」のヘッダータイトルをつけてあげれば完成します。

content_sliver_list.dart

          if (index == _sectionToInt(Section.Top)) {
            return _buildTopSectionPageView(context, 4);
          } else if (index == _sectionToInt(Section.Relax)) {
            return Column(
              mainAxisAlignment: MainAxisAlignment.start,
              children: <Widget>[
                SectionHeaderItem(title: 'くつろぎのひと時を', isVisible: true),
                SecondSectionItem(),
              ],
            );
          } else if (index == _sectionToInt(Section.ActivityMood)) {
            return Column(
              mainAxisAlignment: MainAxisAlignment.start,
              children: <Widget>[
                SectionHeaderItem(title: 'アクティビティ & ムード', isVisible: false),
                ThirdSectionItem(),
              ],
            );
        }

これでセクション3 のデザインが完成しました。

f:id:qed805:20200416003226p:plain:w375
キャプチャー

それにしてもListViewColumnウィジェットは大変便利だなと思いました。

さらにセクション4と5 はセクション2 と同じデザインです。 セクション2を使い回せばいいということが分かりますね。

なので次回はもしかしたら一気にセクション6 の解説に進むかもしれません。

それでは、バイバイ。