본문 바로가기
스파르타/Flutter

[Flutter] 클론코딩(Shazam) - ( week 2 )

by bakcoding_sparta 2023. 4. 18.

Shazam을 클론코딩 해본다.

본래 사이트는 다음 링크에서 확인할 수 있다.

Shazam

난이도 <왼쪽 : ⭐️⭐️⭐️ 중앙 : ⭐️ 오른쪽 : ⭐️⭐️>

 

만들어야 할 페이지는 총 3개

중앙부터 시작해서 다른 페이지들도 만들어본다.

 

1. 첫 번째 페이지

Background

상태바부터 하단까지 파란색이 점점 어두워지는 배경이다.

이 부분부터 만들어본다.

import 'package:flutter/services.dart';

void main() {
  SystemChrome.setSystemUIOverlayStyle(SystemUiOverlayStyle(
    statusBarColor: Colors.blue, // 배경색
    statusBarIconBrightness: Brightness.light, // 아이콘 색상
  ));
  runApp(MyApp());
}

상태바를 제어하기 위해서 SystemChrome.setSystemUIOverlayStyle 함수를 사용한다.

함수를 사용하기위해서 패키지를 임포트 해주고 해당 함수의 매개변수를 통해 색상을 변경해 준다.

이제 앱바와 바디의 색상도 모두 변경해 주도록 한다. 여기서 MaterialApp의 theme 속성을 통해 변경해 본다.

class MyApp extends StatelessWidget {
  const MyApp({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      debugShowCheckedModeBanner: false,
      theme: ThemeData(
        primaryColor: Colors.blue,
        scaffoldBackgroundColor: Colors.blue,
        //backgroundColor: Colors.white,
      ),
      home: Scaffold(
        appBar: AppBar(
          elevation: 0,
        ),
      ),
    );
  }
}

앱바의 그림자를 제거해 주기 위해 elevation 값은 0으로 해준다.

그리고 페이지의 배경은 단색이 아니라 그러데이션이다. 그러데이션은 body부터 시작하면 될 것 같다.

body의 decroration 속성에서 BoxDecoration을 통해서 그러데이션을 넣어본다.

 

body: Container(
          decoration: BoxDecoration(
            gradient: LinearGradient(
              begin: Alignment.topCenter,
              end: Alignment.bottomCenter,
              colors: [
                Colors.blue,
                const Color.fromARGB(255, 53, 156, 240),
                Color.fromARGB(255, 20, 96, 163),
                const Color.fromARGB(255, 18, 76, 143),
                const Color.fromARGB(255, 5, 45, 104),
              ],
            ),
          ),

층이 보이긴 하지만 우선 넘어가도록 한다. 더 자연스럽게 처리하는 방법은 나중에 찾아보고 수정을 해야 할 듯하다.

 

Appbar

앱바는 세 가지의 위젯으로 구성되어 있는 걸로 보인다. 

라이브러리 페이지를 나타내는 내비게이션 그리고 차트가 있다. 각 페이지를 눌렀을 때 페이지가 전환되어야 하는 것 같다.

일단 페이지 전환은 배제하고 보이는 부분만 만들기로 한다.

 

appBar: AppBar(
          centerTitle: true,
          elevation: 0,
          leading: Row(
            children: [
              Padding(
                padding:
                    const EdgeInsets.symmetric(vertical: 8.0, horizontal: 5.0),
                child: GestureDetector(
                  onTap: () {},
                  child: Column(
                    children: [
                      Icon(
                        Icons.person,
                        color: Colors.white,
                      ),
                      Text(
                        "Library",
                        style: TextStyle(color: Colors.white),
                      ),
                    ],
                  ),
                ),
              ),
            ],
          ),
          title: Row(
            mainAxisAlignment: MainAxisAlignment.center,
            children: [
              Icon(
                Icons.circle_outlined,
                size: 10,
              ),
              SizedBox(
                width: 5,
              ),
              Icon(
                Icons.circle_outlined,
                size: 10,
              ),
              SizedBox(
                width: 5,
              ),
              Icon(
                Icons.circle_outlined,
                size: 10,
              ),
            ],
          ),
          actions: [
            Padding(
              padding:
                  const EdgeInsets.symmetric(vertical: 8.0, horizontal: 8.0),
              child: GestureDetector(
                onTap: () {},
                child: Column(
                  children: [
                    Icon(
                      Icons.show_chart,
                      color: Colors.white,
                    ),
                    Text(
                      "Chart",
                      style: TextStyle(color: Colors.white),
                    ),
                  ],
                ),
              ),
            ),
          ],
        ),

leading과 action에 IconButton을 사용해서 하려다 보니 아래에 텍스트를 넣을 때 오버플로우가 발생해서 해결하려다 보니 그냥 Icon과 Text를 쓰고 버튼은 GestureDetector로 처리해야 될 것 같다.

타이틀 위치에는 Icon을 넣었는데 예시의 기능으로 만들기 위해서는 저런 방식을 쓰면 안 될 것 같다고 느껴진다.

 

우선 이번 페이지는 그대로 진행해 본다.

body: Stack(
          alignment: AlignmentDirectional.center,
          children: [
            Container(
              decoration: BoxDecoration(
                gradient: LinearGradient(
                  begin: Alignment.topCenter,
                  end: Alignment.bottomCenter,
                  colors: [
                    Colors.blue,
                    const Color.fromARGB(255, 53, 156, 240),
                    Color.fromARGB(255, 20, 96, 163),
                    const Color.fromARGB(255, 18, 76, 143),
                    const Color.fromARGB(255, 5, 45, 104),
                  ],
                ),
              ),
            ),
            Column(
              children: [
                SizedBox(
                  height: 50,
                ),
                Text(
                  "Shazam하려면 탭하세요",
                  style: TextStyle(
                    color: Colors.white,
                    fontSize: 24,
                    fontWeight: FontWeight.bold,
                  ),
                ),
                SizedBox(
                  height: 80,
                ),
                Container(
                  alignment: Alignment.center,
                  width: 200,
                  height: 200,
                  decoration: BoxDecoration(
                    color: Colors.blue[300],
                    shape: BoxShape.circle,
                  ),
                  child: Image.network(
                    "https://i.ibb.co/hxNbZ8p/shazam.png",
                    color: Colors.white,
                    width: 130,
                    height: 130,
                  ),
                ),
                SizedBox(
                  height: 50,
                ),
                Container(
                  width: 50,
                  height: 50,
                  alignment: Alignment.center,
                  decoration: BoxDecoration(
                      color: Colors.blue[400], shape: BoxShape.circle),
                  child: Icon(
                    Icons.search,
                    color: Colors.white,
                    size: 30,
                  ),
                ),
              ],
            )
          ],
        ),

그러데이션으로 만든 위젯 위에 다른 위젯들이 배치될 수 있도록 Stack으로 만들어준다.

그리고 내부에 이미지와 아이콘을 배치한다.