카테고리 없음

2주차 Shazam 클론코딩

songyooho 2023. 9. 2. 01:07
import 'package:flutter/material.dart';

const Color darkBlue = Color.fromARGB(255, 18, 32, 47);

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      debugShowCheckedModeBanner: false,
      home: HomePage(),
    );
  }
}

class HomePage extends StatefulWidget {
  const HomePage({Key? key}) : super(key: key);

  @override
  State<HomePage> createState() => _HomePageState();
}

class _HomePageState extends State<HomePage> {
  @override
  Widget build(BuildContext context) {
    return DefaultTabController(
        initialIndex: 1,
        length: 3,
        child: Scaffold(
          body: Stack(children: [
            TabBarView(
              children: [
                First(),
                Second(),
                Third(),
              ],
            ),
            SafeArea(
                child: Padding(
              padding: const EdgeInsets.symmetric(vertical: 20, horizontal: 16),
              child: Column(
                children: [
                  Container(
                    alignment: Alignment.topCenter,
                    child: TabPage(),
                  )
                ],
              ),
            ))
          ]),
        ));
  }
}

class TabPage extends StatefulWidget {
  const TabPage({super.key});

  @override
  State<TabPage> createState() => _TabPageState();
}

class _TabPageState extends State<TabPage> {
  @override
  Widget build(BuildContext context) {
    return TabPageSelector(
      color: DefaultTabController.of(context)!.index == 1
          ? Colors.blue[300]
          : Colors.grey[400],
      selectedColor: DefaultTabController.of(context)!.index == 1
          ? Colors.white
          : Colors.blue,
      indicatorSize: 8,
    );
  }
}

class First extends StatelessWidget {
  const First({super.key});

  @override
  Widget build(BuildContext context) {
    const songs = [
      {
        'imageUrl': 'https://i.ibb.co/MRSqtP8/autumnnight.jpg',
        'title': '가을밤에 든 생각',
        'artist': '잔나비',
      },
      {
        'imageUrl': 'https://i.ibb.co/MRSqtP8/autumnnight.jpg',
        'title': '가을밤에 든 생각',
        'artist': '잔나비',
      },
      {
        'imageUrl': 'https://i.ibb.co/MRSqtP8/autumnnight.jpg',
        'title': '가을밤에 든 생각',
        'artist': '잔나비',
      },
      {
        'imageUrl': 'https://i.ibb.co/MRSqtP8/autumnnight.jpg',
        'title': '가을밤에 든 생각',
        'artist': '잔나비',
      },
      {
        'imageUrl': 'https://i.ibb.co/MRSqtP8/autumnnight.jpg',
        'title': '가을밤에 든 생각',
        'artist': '잔나비',
      },
      {
        'imageUrl': 'https://i.ibb.co/MRSqtP8/autumnnight.jpg',
        'title': '가을밤에 든 생각',
        'artist': '잔나비',
      },
    ];

    return SafeArea(
        child: Padding(
            padding: const EdgeInsets.symmetric(horizontal: 16),
            child: Column(
              crossAxisAlignment: CrossAxisAlignment.start,
              children: [
                Row(
                  mainAxisAlignment: MainAxisAlignment.spaceBetween,
                  crossAxisAlignment: CrossAxisAlignment.start,
                  children: [
                    Padding(
                      padding: const EdgeInsets.symmetric(vertical: 4),
                      child: Icon(Icons.settings),
                    ),
                    Text(
                      "라이브러리",
                      style: TextStyle(
                        fontSize: 18,
                        fontWeight: FontWeight.bold,
                      ),
                    ),
                    Icon(null),
                  ],
                ),
                SizedBox(height: 8),
                Padding(
                  padding: const EdgeInsets.symmetric(vertical: 8.0),
                  child: Row(
                    children: [
                      ImageIcon(
                        NetworkImage("https://i.ibb.co/hxNbZ8p/shazam.png"),
                        size: 18,
                      ),
                      SizedBox(
                        width: 12,
                      ),
                      Text(
                        "Shazam",
                        style: TextStyle(
                            fontSize: 18, fontWeight: FontWeight.bold),
                      )
                    ],
                  ),
                ),
                Divider(
                  height: 1,
                  color: Colors.grey,
                ),
                Padding(
                    padding: const EdgeInsets.symmetric(vertical: 8),
                    child: Row(
                      children: [
                        Icon(
                          Icons.person,
                          size: 18,
                        ),
                        SizedBox(
                          width: 12,
                        ),
                        Text(
                          "아티스트",
                          style: TextStyle(
                              fontSize: 18, fontWeight: FontWeight.bold),
                        )
                      ],
                    )),
                Divider(
                  height: 1,
                  color: Colors.grey,
                ),
                Padding(
                    padding: const EdgeInsets.symmetric(vertical: 8),
                    child: Row(
                      children: [
                        Icon(
                          Icons.music_note,
                          size: 18,
                        ),
                        SizedBox(
                          width: 12,
                        ),
                        Text(
                          "회원님을 위한 재생목록",
                          style: TextStyle(
                              fontSize: 18, fontWeight: FontWeight.bold),
                        )
                      ],
                    )),
                Divider(
                  height: 1,
                  color: Colors.grey,
                ),
                SizedBox(
                  height: 16,
                ),
                Padding(
                    padding: const EdgeInsets.symmetric(vertical: 8),
                    child: Row(
                      children: [
                        Text(
                          "최근 Shazam",
                          style: TextStyle(
                              fontSize: 18, fontWeight: FontWeight.bold),
                        )
                      ],
                    )),
                SizedBox(
                  height: 8,
                ),
                Expanded(
                    child: GridView.builder(
                        itemCount: songs.length,
                        gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
                            crossAxisCount: 2, childAspectRatio: 3 / 5),
                        itemBuilder: ((context, index) {
                          String img = songs[index]["imageUrl"]!;
                          String artist = songs[index]["artist"]!;
                          String title = songs[index]["title"]!;

                          return Container(
                            margin: EdgeInsets.all(4),
                            decoration: BoxDecoration(
                              borderRadius:
                                  BorderRadius.all(Radius.circular(8)),
                            ),
                            child: Column(children: [
                              Image.network(
                                img,
                                fit: BoxFit.cover,
                                height: 180,
                              ),
                              Expanded(
                                  child: Container(
                                padding: const EdgeInsets.all(8),
                                width: double.infinity,
                                child: Column(
                                  crossAxisAlignment: CrossAxisAlignment.start,
                                  mainAxisAlignment: MainAxisAlignment.start,
                                  children: [
                                    Text(
                                      title,
                                      style: TextStyle(
                                          fontSize: 18,
                                          fontWeight: FontWeight.bold),
                                    ),
                                    Text(
                                      artist,
                                      style: TextStyle(
                                          fontSize: 12, color: Colors.grey),
                                    ),
                                    Spacer(),
                                    Padding(
                                      padding: const EdgeInsets.symmetric(
                                          vertical: 8.0),
                                      child: Image.network(
                                        "https://i.ibb.co/KG9m5QS/applemusic.png",
                                        width: 60,
                                      ),
                                    ),
                                  ],
                                ),
                              ))
                            ]),
                          );
                        })))
              ],
            )));
  }
}

class Second extends StatelessWidget {
  const Second({super.key});

  @override
  Widget build(BuildContext context) {
    double pheight = MediaQuery.of(context).size.height;
    double pwidth = MediaQuery.of(context).size.width;

    return Container(
      decoration: BoxDecoration(
          gradient: LinearGradient(
              colors: [Colors.blue[300]!, Colors.blue[900]!],
              begin: Alignment.topCenter,
              end: Alignment.bottomCenter)),
      child: Column(children: [
        SizedBox(
          height: 20,
        ),
        Padding(
          padding: const EdgeInsets.all(8.0),
          child: Row(
            mainAxisAlignment: MainAxisAlignment.spaceBetween,
            children: [
              Column(
                children: [
                  Icon(
                    Icons.person,
                    color: Colors.white,
                  ),
                  Text(
                    "라이브러리",
                    style: TextStyle(
                        color: Colors.white,
                        fontSize: 12,
                        fontWeight: FontWeight.bold),
                  )
                ],
              ),
              Spacer(),
              Column(
                children: [
                  Icon(
                    Icons.show_chart,
                    color: Colors.white,
                  ),
                  Text(
                    "차트",
                    style: TextStyle(
                        color: Colors.white,
                        fontSize: 12,
                        fontWeight: FontWeight.bold),
                  )
                ],
              ),
            ],
          ),
        ),
        SizedBox(
          height: pheight * 0.1,
        ),
        Padding(
          padding: const EdgeInsets.symmetric(vertical: 30.0),
          child: Text(
            "Shazam하려면 탭하세요",
            style: TextStyle(
                color: Colors.white, fontSize: 24, fontWeight: FontWeight.bold),
          ),
        ),
        Container(
          alignment: Alignment.center,
          height: pheight * 0.3,
          width: pheight * 0.3,
          decoration:
              BoxDecoration(color: Colors.blue[300], shape: BoxShape.circle),
          child: Image.network(
            "https://i.ibb.co/hxNbZ8p/shazam.png",
            color: Colors.white,
            height: pheight * 0.2,
            width: pheight * 0.2,
          ),
        ),
        SizedBox(
          height: pheight * 0.1,
        ),
        Container(
          alignment: Alignment.center,
          height: pwidth * 0.12,
          width: pwidth * 0.12,
          decoration:
              BoxDecoration(color: Colors.blue[300], shape: BoxShape.circle),
          child: Icon(
            Icons.search,
            color: Colors.white,
            size: pwidth * 0.08,
          ),
        )
      ]),
    );
  }
}

class Third extends StatelessWidget {
  const Third({super.key});

  @override
  Widget build(BuildContext context) {
    const chartData = {
      'korea': [
        {
          'imageUrl': 'https://i.ibb.co/xf2HpfG/dynamite.jpg',
          'name': 'Dynamite',
          'artist': 'BTS',
        },
        {
          'imageUrl': 'https://i.ibb.co/xf2HpfG/dynamite.jpg',
          'name': 'Dynamite',
          'artist': 'BTS',
        },
        {
          'imageUrl': 'https://i.ibb.co/xf2HpfG/dynamite.jpg',
          'name': 'Dynamite',
          'artist': 'BTS',
        },
      ],
      'global': [
        {
          'imageUrl': 'https://i.ibb.co/xf2HpfG/dynamite.jpg',
          'name': 'Dynamite',
          'artist': 'BTS',
        },
        {
          'imageUrl': 'https://i.ibb.co/xf2HpfG/dynamite.jpg',
          'name': 'Dynamite',
          'artist': 'BTS',
        },
        {
          'imageUrl': 'https://i.ibb.co/xf2HpfG/dynamite.jpg',
          'name': 'Dynamite',
          'artist': 'BTS',
        },
      ],
      'newyork': [
        {
          'imageUrl': 'https://i.ibb.co/xf2HpfG/dynamite.jpg',
          'name': 'Dynamite',
          'artist': 'BTS',
        },
        {
          'imageUrl': 'https://i.ibb.co/xf2HpfG/dynamite.jpg',
          'name': 'Dynamite',
          'artist': 'BTS',
        },
        {
          'imageUrl': 'https://i.ibb.co/xf2HpfG/dynamite.jpg',
          'name': 'Dynamite',
          'artist': 'BTS',
        },
      ],
    };

    double pheight = MediaQuery.of(context).size.height;
    double pwidth = MediaQuery.of(context).size.width;

    return SafeArea(
        child: Column(
      children: [
        Text(
          "차트",
          style: TextStyle(
              fontSize: 16, fontWeight: FontWeight.bold, color: Colors.black),
        ),
        SizedBox(
          height: 16,
        ),
        Expanded(
            child: ListView(
          children: [
            Container(
              width: double.infinity,
              height: pheight * 0.3,
              alignment: Alignment.center,
              decoration: BoxDecoration(color: Colors.blue[900]),
              child: Column(children: [
                Spacer(),
                Container(
                  decoration: BoxDecoration(
                    color: Colors.white,
                    borderRadius: BorderRadius.all(Radius.circular(8)),
                  ),
                  width: pwidth * 0.7,
                  height: pheight * 0.05,
                  alignment: Alignment.center,
                  child: Text(
                    "국가 및 도시별 차트",
                    style: TextStyle(
                        fontSize: 16,
                        fontWeight: FontWeight.bold,
                        color: Colors.blue[900]),
                  ),
                ),
                Padding(
                  padding: const EdgeInsets.all(8.0),
                  child: Text(
                    "전 세계",
                    style: TextStyle(
                        fontWeight: FontWeight.bold,
                        fontSize: 18,
                        color: Colors.white),
                  ),
                ),
                Spacer()
              ]),
            ),
            Column(
              children: [
                Padding(
                  padding: const EdgeInsets.all(8.0),
                  child: Row(
                    children: [
                      Text(
                        "대한민국 차트",
                        style: TextStyle(fontSize: 16),
                      ),
                      Spacer(),
                      Text(
                        "모두 보기",
                        style: TextStyle(fontSize: 14, color: Colors.blue[300]),
                      ),
                    ],
                  ),
                ),
                Row(
                  children: [
                    Padding(
                      padding: const EdgeInsets.all(8.0),
                      child: Column(
                        crossAxisAlignment: CrossAxisAlignment.start,
                        children: [
                          Image.network(
                            chartData['korea']![0]["imageUrl"]!,
                            width: pwidth * 0.28,
                          ),
                          Text(
                              "${chartData['korea']![0]["name"]!}\n${chartData['korea']![0]["artist"]!}")
                        ],
                      ),
                    ),
                    Padding(
                      padding: const EdgeInsets.all(8.0),
                      child: Column(
                        crossAxisAlignment: CrossAxisAlignment.start,
                        children: [
                          Image.network(
                            chartData['korea']![1]["imageUrl"]!,
                            width: pwidth * 0.28,
                          ),
                          Text(
                              "${chartData['korea']![1]["name"]!}\n${chartData['korea']![1]["artist"]!}")
                        ],
                      ),
                    ),
                    Padding(
                      padding: const EdgeInsets.all(8.0),
                      child: Column(
                        crossAxisAlignment: CrossAxisAlignment.start,
                        children: [
                          Image.network(
                            chartData['korea']![2]["imageUrl"]!,
                            width: pwidth * 0.28,
                          ),
                          Text(
                              "${chartData['korea']![2]["name"]!}\n${chartData['korea']![2]["artist"]!}")
                        ],
                      ),
                    ),
                  ],
                )
              ],
            ),
            Column(
              children: [
                Padding(
                  padding: const EdgeInsets.all(8.0),
                  child: Row(
                    children: [
                      Text(
                        "글로벌 차트",
                        style: TextStyle(fontSize: 16),
                      ),
                      Spacer(),
                      Text(
                        "모두 보기",
                        style: TextStyle(fontSize: 14, color: Colors.blue[300]),
                      ),
                    ],
                  ),
                ),
                Row(
                  children: [
                    Padding(
                      padding: const EdgeInsets.all(8.0),
                      child: Column(
                        crossAxisAlignment: CrossAxisAlignment.start,
                        children: [
                          Image.network(
                            chartData['global']![0]["imageUrl"]!,
                            width: pwidth * 0.28,
                          ),
                          Text(
                              "${chartData['global']![0]["name"]!}\n${chartData['global']![0]["artist"]!}")
                        ],
                      ),
                    ),
                    Padding(
                      padding: const EdgeInsets.all(8.0),
                      child: Column(
                        crossAxisAlignment: CrossAxisAlignment.start,
                        children: [
                          Image.network(
                            chartData['global']![1]["imageUrl"]!,
                            width: pwidth * 0.28,
                          ),
                          Text(
                              "${chartData['global']![1]["name"]!}\n${chartData['global']![1]["artist"]!}")
                        ],
                      ),
                    ),
                    Padding(
                      padding: const EdgeInsets.all(8.0),
                      child: Column(
                        crossAxisAlignment: CrossAxisAlignment.start,
                        children: [
                          Image.network(
                            chartData['global']![2]["imageUrl"]!,
                            width: pwidth * 0.28,
                          ),
                          Text(
                              "${chartData['global']![2]["name"]!}\n${chartData['global']![2]["artist"]!}")
                        ],
                      ),
                    ),
                  ],
                )
              ],
            ),
            Column(
              children: [
                Padding(
                  padding: const EdgeInsets.all(8.0),
                  child: Row(
                    children: [
                      Text(
                        "뉴욕 차트",
                        style: TextStyle(fontSize: 16),
                      ),
                      Spacer(),
                      Text(
                        "모두 보기",
                        style: TextStyle(fontSize: 14, color: Colors.blue[300]),
                      ),
                    ],
                  ),
                ),
                Row(
                  children: [
                    Padding(
                      padding: const EdgeInsets.all(8.0),
                      child: Column(
                        crossAxisAlignment: CrossAxisAlignment.start,
                        children: [
                          Image.network(
                            chartData['newyork']![0]["imageUrl"]!,
                            width: pwidth * 0.28,
                          ),
                          Text(
                              "${chartData['newyork']![0]["name"]!}\n${chartData['newyork']![0]["artist"]!}")
                        ],
                      ),
                    ),
                    Padding(
                      padding: const EdgeInsets.all(8.0),
                      child: Column(
                        crossAxisAlignment: CrossAxisAlignment.start,
                        children: [
                          Image.network(
                            chartData['newyork']![1]["imageUrl"]!,
                            width: pwidth * 0.28,
                          ),
                          Text(
                              "${chartData['newyork']![1]["name"]!}\n${chartData['newyork']![1]["artist"]!}")
                        ],
                      ),
                    ),
                    Padding(
                      padding: const EdgeInsets.all(8.0),
                      child: Column(
                        crossAxisAlignment: CrossAxisAlignment.start,
                        children: [
                          Image.network(
                            chartData['newyork']![2]["imageUrl"]!,
                            width: pwidth * 0.28,
                          ),
                          Text(
                              "${chartData['newyork']![2]["name"]!}\n${chartData['newyork']![2]["artist"]!}")
                        ],
                      ),
                    ),
                  ],
                )
              ],
            ),
          ],
        )),
      ],
    ));
  }
}

1. DefaultTabController

페이지를 넘겨가며 볼 수 있게 해주는 위젯

 

2.SafeArea

휴대기기 기종이나 OS에 따라 필요한 텍스트가 가려지는 경우를 방지하기위해 자동으로 패딩을 주는 위젯.

https://all-dev-kang.tistory.com/entry/%ED%94%8C%EB%9F%AC%ED%84%B0-SafeArea-%EC%97%90-%EB%8C%80%ED%95%B4%EC%84%9C

 

[플러터] SafeArea 에 대해서

들어가며 이번 글에서는 Flutter(이하 플러터)에서 가장 기본이 되는 위젯 "SafeArea"에 대해 살펴보고 사용법에 대해서 알아보도록 하겠습니다. 그런 후에 적용 예시를 통해 어떤 옵션이 있는지 또

all-dev-kang.tistory.com

3.TabPageSelector

1의 DefaultTabController의 현재 페이지를 나타내는 indicator역할

 

4.Spacer()

남은 공간을 최대로 차지해서 밀어주는 위젯

 

5.Divider()

구분선을 그려주는 위젯

 

6.GridView.builder()

그리드 뷰 위젯. 리스트뷰와 사용법은 유사함

 

7.MediaQuery.of(context).size.height, MediaQuery.of(context).size.width

현재 기기 화면 사이즈를 구해주는 코드. 각각 높이와 너비

 

8.BoxDecoration( gradient: ~)

그라데이션 형태로 색을 칠해주는 것

 

9.Expanded()

남는 공간을 최대로 차지할수록 늘려주는것. 예를들어 1000이란 공간에서 컨테이너 두개가 각각 200씩 차지한타면 expanded안에 listview를 넣어줄 경우 listview는 최대 600까지 차지할 수 있도록 공간을 배정해준다. 

https://mike123789-dev.tistory.com/entry/%ED%94%8C%EB%9F%AC%ED%84%B0Column-%EC%95%88%EC%9D%98-ListView

 

[플러터]Column 안에 ListView

Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: Text(widget.title), ), body: Column( children: [ MyListView(), ], ), ); } 그리고 class MyListView extends StatelessWidget { @override Widget build(BuildContext context) { retur

mike123789-dev.tistory.com

또한 Expanded안에 row나 column을 넣는 경우 MainAxis부분만 최대로 늘려준다.