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

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

48.【AppleMusicクローン】注目トラックのデザインを組み立てる

本日はAppleMusicクローンアプリの「注目トラック」のデザインについて見ていきます。

まずはデザインのレイアウトについておさらいします!

f:id:qed805:20200423132433p:plain:w300
注目トラックのデザイン

最初に見た感想としては、「もう無理だな、諦めるわ」ていうレベルです。iOSアプリでいえば UITableViewCell の標準的なレイアウトに似てるなと思いました。 横スクロールについてindex単位のページング付きのスクロールですのでPageViewを使う必要があります。 こういう場合はSection1 で行ったことを思い出したほうが早いです。

blog.tamappe.com

早速、SeventhSectionItemクラスを作成するためにseventh_section_item.dartファイルを新規作成します。

seventh_section_item.dart

import 'package:apple_music_clone/widgets/sections/seventh_section_column_item.dart';
import 'package:flutter/material.dart';
import 'package:flutter/painting.dart';

class SeventhSectionItem extends StatelessWidget {
  final int itemCount;

  SeventhSectionItem({@required this.itemCount});

  @override
  Widget build(BuildContext context) {
    return Column(
      mainAxisSize: MainAxisSize.min,
      children: <Widget>[
        SizedBox(
          height: 230.0,
          child: PageView.builder(
            itemCount: itemCount,
            controller: PageController(viewportFraction: 0.9),
            itemBuilder: (BuildContext context, int itemIndex) {
              return _buildTopSectionItem();
            },
          ),
        )
      ],
    );
  }

  Widget _buildTopSectionItem() {
    final verticalPadding = const EdgeInsets.symmetric(vertical: 1.0);
    final horizontalPadding = const EdgeInsets.symmetric(horizontal: 5.0);
    return Padding(
      padding: horizontalPadding,
      child: SeventhSectionColumnItem(verticalPadding),
    );
  }
}

このようになりました。 ここまでは問題ありません。 ちなみにこの場合はSeventhSectionColumnItemクラスはまだ作成していませんのでエラーが発生します。

SeventhSectionColumnItemクラスを作成するためseventh_section_column_item.dartを新規作成します。

seventh_section_column_item.dart

import 'package:apple_music_clone/utils/hex_color.dart';
import 'package:flutter/material.dart';

class SeventhSectionColumnItem extends StatelessWidget {
  final verticalPadding;

  SeventhSectionColumnItem(this.verticalPadding);

  @override
  Widget build(BuildContext context) {
    return Column(
      children: <Widget>[
        _oneCell('assets/images/image11.png', 'SOMEBODY TORE MY P', 'tofubeats'),
        _oneCell('assets/images/image12.png', '失恋、ありがとう', 'AKB48'),
        _oneCell('assets/images/image13.png', 'Light The Light', 'RADWIMPS'),
        _oneCell('assets/images/image14.png', 'In Your Eyes', 'ザ・ウィークエンド'),
      ],
    );
  }
}

このようにしています。ここも問題ないはずです。 _oneCell()のメソッドで勝負をかけています。

_oneCell() のメソッドの中身はこのようになります。

class SeventhSectionColumnItem extends StatelessWidget {


  Widget _oneCell(String assetPath, String title, String subTitle) {
    return Container(
      height: 50,
      child: Row(
        children: <Widget>[
          Padding(
            padding: const EdgeInsets.symmetric(vertical: 3.0),
            child: Container(
              decoration: BoxDecoration(
                borderRadius: BorderRadius.all(Radius.circular(5.0)),
              ),
              child: Image.asset(assetPath),
            ),
          ),
          Expanded(
            child: Padding(
              padding: const EdgeInsets.only(left: 10.0),
              child: Column(
                mainAxisAlignment: MainAxisAlignment.start,
                crossAxisAlignment: CrossAxisAlignment.start,
                children: <Widget>[
                  Divider(
                    height: 1.0,
                    color: Colors.black45,
                  ),
                  Row(
                    mainAxisAlignment: MainAxisAlignment.spaceBetween,
                    children: <Widget>[
                      Column(
                        crossAxisAlignment: CrossAxisAlignment.start,
                        children: <Widget>[
                          Padding(
                            padding: const EdgeInsets.only(top: 8.0, bottom: 3.0),
                            child: Text(
                            title,
                              style: TextStyle(
                                  fontSize: 13,
                                  color: Colors.black,
                                  fontWeight: FontWeight.w400
                              ),
                            ),
                          ),
                          Text(
                              subTitle,
                            style: TextStyle(
                              fontSize: 11,
                              color: HexColor('#848484'),
                              fontWeight: FontWeight.w400
                            ),
                          ),
                        ],
                      ),
                      Container(
                        child: Icon(
                          Icons.add,
                          color: Colors.red,
                          size: 30,
                        ),
                      )
                    ],
                  ),
                ],
              ),
            ),
          ),
        ],
      ),
    );
  }
}

順番に説明しますとWidget の順番は

Container

Row

[ (Padding < Image) , (Expanded < Column) ]

Expanded < Column の内訳 [ (Divider) , Row ]

Row < Column

[ Text, Text, (Container < Icon) ]

という構造になっています。

Columnに入っているText 2つが タイトルとサブタイトル、 Container < Icon を 赤のプラス(+)ボタン という風に設計しました。 Container < Icon のIcon は後の FlatButton になります。

こんな感じで複雑そうな「注目トラック」のデザインを実現してみました。 他にもっといいやり方がありましたらTwitter などで教えていただけると助かります。

あとはいつものようにcontent_sliver_list.dartでSection.Attentionを追加してやればOKです。

content_sliver_list.dart

class ContentSliverList extends StatelessWidget {

/// 省略

 else if (index == _sectionToInt(Section.Attention)) {
            return Column(
              mainAxisAlignment: MainAxisAlignment.start,
              children: <Widget>[
                SectionHeaderItem(
                    title: '注目トラック',
                    isVisible: true
                ),
                SeventhSectionItem(
                  itemCount: 20,
                ),
              ],
            );
          }

/// 省略
}

これをビルドすると「注目トラック」のデザインが出来上がります。

f:id:qed805:20200426191220p:plain:w300
注目トラックのデザイン

ここまで来るとAppleMusicクローンアプリの残りのタスクは雑魚だけになります。