Faça um aplicativo de clone do Spotify usando o Flutter
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