Faça um aplicativo de clone do Spotify usando o Flutter

Tempo de leitura: 4 minutes

Neste tutorial, vamos criar um aplicativo Spotify Clone usando o Flutter. para esta parte, focaremos no front end do aplicativo, o que significa que não usaremos a API ou adicionaremos um music player real, mas aprenderemos como criar uma barra de navegação inferior e como navegar entre visualizações diferentes usando a vibração.

Introdução

Antes de começarmos a codificar nosso aplicativo, vamos dar uma olhada no nosso aplicativo

Como você pode ver, nosso aplicativo tem uma barra de navegação inferior e 4 fragmentos. primeiro codificaremos o arquivo principal do nosso aplicativo e criaremos quatro arquivos, um para cada fragmento. Agora vamos começar a codificar.

Código Fonte:

main.dart

import 'package:flutter/material.dart';
import 'package:spotifyclone/PlayListPage.dart';
import 'package:spotifyclone/ProfilePage.dart';
import 'package:spotifyclone/SearchPage.dart';
import 'HomePage.dart';
void main() => runApp(MyApp());

class MyApp extends StatefulWidget {
  @override
  _MyAppState createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {
  int _courentTab = 0;
  final Tabs = [
    HomePage(),
    SearchPage(),
    PlayListPage(),
    ProfilePage(),
  ];
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      debugShowCheckedModeBanner: false,
      home: SafeArea(
        child: Scaffold(
          backgroundColor: Colors.black,
          body: Tabs[_courentTab], //HomePage(),tabs[_courentTab],
          bottomNavigationBar: BottomNavigationBar(
            currentIndex: _courentTab,

            type: BottomNavigationBarType.shifting,
            items:[
              BottomNavigationBarItem(
                icon: Icon(Icons.home,color: Colors.white,),
                title: Text("Home",style: TextStyle(color: Colors.white),),
                backgroundColor: Color.fromARGB(255, 20, 20, 20),
              ),
              BottomNavigationBarItem(
                icon: Icon(Icons.search,color: Colors.white,),
                title: Text("Search",style: TextStyle(color: Colors.white),),
                backgroundColor: Color.fromARGB(255, 20, 20, 20),
              ),
              BottomNavigationBarItem(
                icon: Icon(Icons.library_music,color: Colors.white,),
                title: Text("Music Library",style: TextStyle(color: Colors.white),),
                backgroundColor: Color.fromARGB(255, 20, 20, 20),
              ),
              BottomNavigationBarItem(
                icon: Icon(Icons.person,color: Colors.white,),
                title: Text("Your Account",style: TextStyle(color: Colors.white),),
                backgroundColor: Color.fromARGB(255, 20, 20, 20),

              ),

            ],
            onTap: (index){
              setState(() {
                _courentTab = index;
              });
            },
          ),
        ),
      ),

    );
  }
}

 

HomePage.dart

import 'package:flutter/material.dart';

class HomePage extends StatelessWidget {
  List<String> CoverList =[
    "https://i.pinimg.com/originals/f5/82/47/f58247463e38a536f442bfb816f62c6b.jpg",
    "https://www.designformusic.com/wp-content/uploads/2016/09/electro-synthwave-album-cover-500x500.jpg",
    "https://fiverr-res.cloudinary.com/images/q_auto,f_auto/gigs/102342461/original/68ef1e1fab3c4028d51f7fd7cfa9bad2232e576c/create-a-copyright-free-album-cover.jpg",
    "https://www.designformusic.com/wp-content/uploads/2016/02/volta-music-trailer-music-album-cover-design.jpg",
    "https://www.designformusic.com/wp-content/uploads/2018/07/Digital-World-album-cover-design.jpg",
    "https://www.designformusic.com/wp-content/uploads/2016/02/volta-music-trailer-music-album-cover-design.jpg"
  ];
  Widget AlbumContainer(String CoverUrl,String CoverName, String SingerName){
    return Container(
      child: InkWell(
        onTap: (){},
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.start,
          children: <Widget>[
            ClipRRect(
              borderRadius: BorderRadius.circular(12.0),
              child: Container(
                  height: 140.0,
                  width: 140.0,
                  child: Image.network(CoverUrl)
              ),
            ),
            SizedBox(height: 12.0,),
            Text(
              CoverName,
              style: TextStyle(
                color: Colors.white,
                fontWeight: FontWeight.w800,
                fontSize: 22.0
              ),
            ),
            SizedBox(height: 12.0,),
            Text(
              SingerName,
              style: TextStyle(
                  color: Colors.white,
                  fontWeight: FontWeight.w300,
                  fontSize: 18.0
              ),
            ),
          ],
        ),
      ),
    );
  }

  @override
  Widget build(BuildContext context) {
    return Container(
        child: Padding(
          padding: EdgeInsets.symmetric(vertical: 40.0,horizontal: 25.0),
          child: Column(
            crossAxisAlignment: CrossAxisAlignment.start,
            mainAxisAlignment: MainAxisAlignment.start,
            children: <Widget>[
              Text(
                "Recommended for you",
                style: TextStyle(
                    color: Colors.white,
                  fontSize: 28.0
                ),
              ),
              SizedBox(
                height: 20.0,
              ),
              Expanded(
                child: ListView(
                  scrollDirection: Axis.horizontal,
                  children: <Widget>[
                    AlbumContainer(CoverList[0], "CoverName", "SingerName"),
                    SizedBox(width: 28.0,),
                    AlbumContainer(CoverList[1], "CoverName", "SingerName"),
                    SizedBox(width: 28.0,),
                    AlbumContainer(CoverList[2], "CoverName", "SingerName"),
                    SizedBox(width: 28.0,),
                  ],
                ),
              ),
              Text(
                "New Music",
                style: TextStyle(
                    color: Colors.white,
                    fontSize: 28.0
                ),
              ),
              SizedBox(
                height: 20.0,
              ),
              Expanded(
                child: ListView(
                  scrollDirection: Axis.horizontal,
                  children: <Widget>[
                    AlbumContainer(CoverList[3], "CoverName", "SingerName"),
                    SizedBox(width: 28.0,),
                    AlbumContainer(CoverList[4], "CoverName", "SingerName"),
                    SizedBox(width: 28.0,),
                    AlbumContainer(CoverList[5], "CoverName", "SingerName"),
                    SizedBox(width: 28.0,),
                  ],
                ),
              )
            ],
          ),
        ),
      );

  }
}

 

SearchPage.dart

import 'package:flutter/material.dart';

class SearchPage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Center(
      child: Padding(
        padding: const EdgeInsets.symmetric(vertical: 12.0, horizontal: 15.0),
          child: Column(
            children: <Widget>[
              Center(
                child: Text(
                  "Search",
                  textAlign: TextAlign.center,
                  style: TextStyle(
                    color: Colors.white,
                    fontSize: 48.0,
                  ),
                ),
              ),
              Padding(
                padding: const EdgeInsets.all(18.0),
                child: TextField(
                  textAlign: TextAlign.center,
                  decoration: InputDecoration(
                    fillColor: Colors.white,
                    prefixIcon: Icon(Icons.search,color: Colors.black,size: 28.0,),
                    filled: true,
                    border: InputBorder.none,
                    hintText: "Find your music",
                  ),
                ),
              ),
              Expanded(
                child: GridView.count(
                  primary: false,
                  padding: const EdgeInsets.all(20),
                  crossAxisSpacing: 10,
                  mainAxisSpacing: 10,
                  crossAxisCount: 2,
                  children: <Widget>[
                    ClipRRect(
                      borderRadius: BorderRadius.circular(10.0),
                      child: Container(
                        padding: const EdgeInsets.symmetric(vertical: 12.0,horizontal: 12.0),
                        child: const Text("Pop Music",style: TextStyle(
                          color: Colors.white,
                          fontSize: 28.0
                        ),),
                        color: Colors.deepOrange,
                      ),
                    ),
                    ClipRRect(
                      borderRadius: BorderRadius.circular(10.0),
                      child: Container(
                        padding: const EdgeInsets.symmetric(vertical: 12.0,horizontal: 12.0),
                        child: const Text("Rock",style: TextStyle(
                          color: Colors.white,
                          fontSize: 28.0
                        ),),
                        color: Colors.deepPurple,
                      ),
                    ),
                    ClipRRect(
                      borderRadius: BorderRadius.circular(10.0),
                      child: Container(
                        padding: const EdgeInsets.symmetric(vertical: 12.0,horizontal: 12.0),
                        child: const Text("Hip Hop",style: TextStyle(
                          color: Colors.white,
                          fontSize: 28.0
                        ),),
                        color: Colors.blueAccent,
                      ),
                    ),
                    ClipRRect(
                      borderRadius: BorderRadius.circular(10.0),
                      child: Container(
                        padding: const EdgeInsets.symmetric(vertical: 12.0,horizontal: 12.0),
                        child: const Text("Jazz",style: TextStyle(
                          color: Colors.white,
                          fontSize: 28.0
                        ),),
                        color: Colors.amber,
                      ),
                    ),
                    ClipRRect(
                      borderRadius: BorderRadius.circular(10.0),
                      child: Container(
                        padding: const EdgeInsets.symmetric(vertical: 12.0,horizontal: 12.0),
                        child: const Text("House",style: TextStyle(
                          color: Colors.white,
                          fontSize: 28.0
                        ),),
                        color: Colors.green,
                      ),
                    ),
                    ClipRRect(
                      borderRadius: BorderRadius.circular(10.0),
                      child: Container(
                        padding: const EdgeInsets.symmetric(vertical: 12.0,horizontal: 12.0),
                        child: const Text("Reggae",style: TextStyle(
                          color: Colors.white,
                          fontSize: 28.0
                        ),),
                        color: Colors.red,
                      ),
                    ),

                  ],
                ),
              )

            ],
          ),

      )
    );
  }
}

 

PlayListPage.dart

import 'package:flutter/material.dart';

class PlayListPage extends StatelessWidget {
  List<String> CoverList =[
    "https://i.pinimg.com/originals/f5/82/47/f58247463e38a536f442bfb816f62c6b.jpg",
    "https://www.designformusic.com/wp-content/uploads/2016/09/electro-synthwave-album-cover-500x500.jpg",
    "https://fiverr-res.cloudinary.com/images/q_auto,f_auto/gigs/102342461/original/68ef1e1fab3c4028d51f7fd7cfa9bad2232e576c/create-a-copyright-free-album-cover.jpg",
    "https://www.designformusic.com/wp-content/uploads/2016/02/volta-music-trailer-music-album-cover-design.jpg",
    "https://www.designformusic.com/wp-content/uploads/2018/07/Digital-World-album-cover-design.jpg",
    "https://www.designformusic.com/wp-content/uploads/2016/02/volta-music-trailer-music-album-cover-design.jpg"
  ];

  Widget ListItem(String CoverUrl,String AlbumTitle, String SingerName){
      return Column(
        children: <Widget>[
          InkWell(
            onTap: (){},
            child: Container(
                child: Row(
                  children: <Widget>[
                    ClipRRect(
                      borderRadius: BorderRadius.circular(4.0),
                      child: Container(
                        width: 100.0,
                        height: 100.0,
                        child: Image.network(CoverUrl),
                      ),
                    ),
                    SizedBox(width: 20.0,),
                    Column(
                      crossAxisAlignment: CrossAxisAlignment.start,
                      children: <Widget>[
                        Text(
                          AlbumTitle,
                          style: TextStyle(
                            color: Colors.white,
                            fontSize: 28.0,
                            fontWeight: FontWeight.w800
                          ),
                        ),
                        SizedBox(height: 12.0,),
                        Text(
                          SingerName,
                          style: TextStyle(
                            color: Colors.white,
                            fontSize: 20.0,
                            fontWeight: FontWeight.w300
                          ),
                        )
                      ],
                    )
                  ],
                ),
            ),
          ),
          SizedBox(height: 20.0,)
        ],
      );
  }

  @override
  Widget build(BuildContext context) {
    return Container(
        child: Padding(
          padding: const EdgeInsets.symmetric(horizontal:12.0,vertical: 35.0),
          child: Column(
            crossAxisAlignment: CrossAxisAlignment.start,
            mainAxisAlignment: MainAxisAlignment.start,
            children: <Widget>[
              Text(
                "Your Favorite Music",
                style: TextStyle(
                  color: Colors.white,
                  fontSize: 28.0
                ),
              ),
              SizedBox(height: 20.0,),
              Expanded(
                child: ListView(
                  children: <Widget>[
                    ListItem(CoverList[0], "AlbumTitle", "SingerName"),
                    ListItem(CoverList[1], "AlbumTitle", "SingerName"),
                    ListItem(CoverList[2], "AlbumTitle", "SingerName"),
                    ListItem(CoverList[3], "AlbumTitle", "SingerName"),
                    ListItem(CoverList[4], "AlbumTitle", "SingerName"),
                    ListItem(CoverList[5], "AlbumTitle", "SingerName"),
                  ],
                ),
              )
            ],
          ),
        ),
    );
  }
}

 

ProfilePage.dart

import 'package:flutter/material.dart';

class ProfilePage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Center(
        child: Padding(
          padding: const EdgeInsets.symmetric(vertical: 30.0,horizontal: 22.0),
          child: Column(
            children: <Widget>[
              CircleAvatar(
                radius: 70,
                backgroundImage: NetworkImage("https://images.unsplash.com/photo-1529665253569-6d01c0eaf7b6?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=1276&q=80"),
              ),
              SizedBox(
                height: 20.0,
              ),
              Text(
                "Doctor Code",
                style: TextStyle(
                  color: Colors.white,
                  fontSize: 28.0
                ),
              ),
              SizedBox(
                height: 50.0,
              ),
              Row(
                children: <Widget>[
                  Expanded(
                    child: Column(
                      children: <Widget>[
                        Text("501",style: TextStyle(
                          color: Colors.white,
                          fontSize: 35.0
                        ),),
                        SizedBox(height: 5.0,),
                        Text("Music",style: TextStyle(
                            color: Colors.white,
                            fontSize: 25.0,
                          fontWeight: FontWeight.w300
                        ),),
                      ],
                    ),
                  ),
                  Expanded(
                    child: Column(
                      children: <Widget>[
                        Text("20.1K",style: TextStyle(
                          color: Colors.white,
                          fontSize: 35.0
                        ),),
                        SizedBox(height: 5.0,),
                        Text("Followers",style: TextStyle(
                            color: Colors.white,
                            fontSize: 25.0,
                            fontWeight: FontWeight.w300
                        ),),
                      ],
                    ),
                  ),
                  Expanded(
                    child: Column(
                      children: <Widget>[
                        Text("1.2k",style: TextStyle(
                          color: Colors.white,
                          fontSize: 35.0
                        ),),
                        SizedBox(height: 5.0,),
                        Text("Follow",style: TextStyle(
                            color: Colors.white,
                            fontSize: 25.0,
                          fontWeight: FontWeight.w300
                        ),),
                      ],
                    ),
                  ),
                ],
              ),
              SizedBox(
                height: 30.0,
              ),
              
              Padding(
                padding: EdgeInsets.all(22.0),
                child: RaisedButton(
                  shape: RoundedRectangleBorder(
                    borderRadius: BorderRadius.circular(100.0),
                  ),
                  child: Padding(
                    padding: const EdgeInsets.symmetric(horizontal: 30.0,vertical: 18.0),
                    child: Text("Edit Profile", style: TextStyle(
                      color: Colors.white,
                      fontSize: 22.0
                    ),),
                  ),
                  color: Color(0xFF1DD860),
                  onPressed: (){},
                ),
              )
            ],
          ),
        )
    );
  }
}

 

Espero que este tutorial tenha sido útil, se você gostou, pode colocar no comentário o que você quer para um projeto futuro