- Apa itu flutter ?
Flutter adalah alat UI/User Interface Google untuk membuat aplikasi yang bagus, yang dikompilasi secara native untuk seluler, web, dan desktop dari basis kode tunggal. Sumber : https://flutter.dev/. Dengan menggunakan flutter akan mudah dan cepat dalam membuat aplikasi mobile iOS dan Android.
- Langkah-langkah dalam membuat aplikasi :
– create project -> flutter create ‘nama_aplikasi’ -> ex: ‘landry_app’
– ubah code main.dart didalam folder lib
– buat 3 folder didalam folder lib/ -> pages, models, widgets
– masuk folder lib/pages -> buat file baru :
* login_page
* main_tab_page.dart
* home_page.dart
* pembayaran_page.dart
* finish_dart
* pesanan.dart
* pesanan_detail.dart
* profile_page.dart
* setting_page.dart
– masuk folder lib/models -> buat file baru :
* jenis_laundry.dart
* jenis_pakaian.dart
– masuk folder lib/widgets -> buat file baru :
* validate.dart - Instalasi flutter
Download flutter SDK terbaru di https://flutter.dev/docs/get-started/install/macos
- Persiapkan editor
Download Android Studio atau Visual Studio Code di https://code.visualstudio.com/ - Buat projek baru dengan Terminal
flutter create ‘nama_aplikasi’ → flutter create laundry_app - Editor code pakai Visual Studio Code
- Jalankan aplikasi yang sudah dibuat
select simulator/emulator device → tekan F5 untuk menjalankan aplikasi
- Ubah main.dart di dalam folder lib
Buka lib/main.dart, ubah code didalam file main.dart
import 'package:flutter/material.dart'; import 'package:laundry_app/pages/login_page.dart'; void main() => runApp(MyApp()); class MyApp extends StatelessWidget { @override Widget build(BuildContext context) { return MaterialApp( debugShowCheckedModeBanner: false, title: 'Laundry App', theme: ThemeData( primarySwatch: Colors.cyan, ), home: LoginPage(), ); } }
- Membuat Login
Buka folder lib, buat file folder baru dengan nama “pages”
Buat file baru dengan nama “login_page.dart” di dalam folder pages
import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:laundry_app/pages/main_tab_page.dart'; import 'package:laundry_app/widgets/validate.dart'; class LoginPage extends StatefulWidget { static const routeName = 'login'; const LoginPage({Key key}) : super(key: key); @override _LoginPageState createState() => _LoginPageState(); } class _LoginPageState extends State<LoginPage> { final userController = TextEditingController(); final passController = TextEditingController(); bool isValUsername = false; bool isValPassword = false; bool lockStatus = false; bool isSecure = true; void lockTapped(bool status) { setState(() { if (isSecure) { isSecure = false; } else { isSecure = true; } }); } @override void initState() { super.initState(); userController.addListener(userChange); passController.addListener(passChange); } void userChange() { setState(() { isValUsername = false; }); } void passChange() { setState(() { isValPassword = false; }); } void loginTapped(BuildContext context) { setState(() { if (userController.text.isEmpty) { isValUsername = true; } else if (passController.text.isEmpty) { isValPassword = true; } else { Navigator.of(context).push( CupertinoPageRoute( fullscreenDialog: true, builder: (context) => MainTabPage(), ), ); } }); } @override Widget build(BuildContext context) { return Scaffold( body: contentBody(context), ); } Widget contentBody(BuildContext context) { return SafeArea( child: Padding( padding: const EdgeInsets.only(left: 16.0, right: 16.0), child: Stack( children: <Widget>[ Column( crossAxisAlignment: CrossAxisAlignment.start, children: <Widget>[ SizedBox(height: 30), Icon( Icons.bubble_chart, color: Colors.blueGrey, size: 38, ), SizedBox(height: 30), Text( 'Selamat Datang,', style: TextStyle(fontSize: 24), ), SizedBox(height: 8.0), Text( 'Login untuk masuk aplikasi', style: TextStyle(color: Colors.grey[700]), ), SizedBox(height: 80), TextField( autocorrect: false, controller: userController, decoration: InputDecoration( labelText: 'Email', ), ), if (isValUsername) Validate(message: 'Email tidak boleh kosong'), TextField( obscureText: isSecure, autocorrect: false, controller: passController, decoration: InputDecoration( labelText: 'Password', suffixIcon: IconButton( icon: (isSecure) ? Icon(Icons.visibility) : Icon(Icons.visibility_off), onPressed: () => lockTapped(lockStatus), ), ), ), if (isValPassword) Validate(message: 'Password tidak boleh kosong'), ], ), Positioned( left: 8.0, right: 8.0, bottom: 16.0, child: Container( decoration: BoxDecoration( borderRadius: BorderRadius.circular(8.0), color: Colors.blueGrey, ), child: FlatButton( child: Text( 'Login', style: TextStyle(color: Colors.white), ), onPressed: () => loginTapped(context), ), ), ), ], ), ), ); } }
- Membuat MainTabPage
Buka folder lib/pages, buat file baru “main_tab_page.dart”import 'package:flutter/material.dart'; import 'package:laundry_app/pages/home_page.dart'; import 'package:laundry_app/pages/pesanan_page.dart'; import 'package:laundry_app/pages/profile_page.dart'; class MainTabPage extends StatefulWidget { static const routeName = 'main-tab'; const MainTabPage({Key key}) : super(key: key); @override _MainTabPageState createState() => _MainTabPageState(); } class _MainTabPageState extends State<MainTabPage> { bool isTopBar = true; int _selectedTabIndex = 0; void _onNavBarTapped(int index) { setState(() { _selectedTabIndex = index; if (_selectedTabIndex == 2) { isTopBar = false; } else { isTopBar = true; } }); } @override Widget build(BuildContext context) { final _listPage = [ HomePage(), PesananPage(), ProfilePage(), ]; final _bottomNavBarItems = <BottomNavigationBarItem>[ BottomNavigationBarItem( icon: Icon(Icons.home), title: Text('Beranda'), activeIcon: Icon(Icons.home, color: Colors.black), ), BottomNavigationBarItem( icon: Icon(Icons.track_changes), title: Text('Pesanan'), activeIcon: Icon(Icons.track_changes, color: Colors.black), ), BottomNavigationBarItem( icon: Icon(Icons.person), title: Text('Akun'), activeIcon: Icon(Icons.person, color: Colors.black), ), ]; final _bottomNavBar = BottomNavigationBar( items: _bottomNavBarItems, currentIndex: _selectedTabIndex, selectedItemColor: Colors.black, unselectedItemColor: Colors.grey, onTap: _onNavBarTapped, ); return Scaffold( backgroundColor: Colors.blueGrey, body: SafeArea( top: isTopBar, child: _listPage[_selectedTabIndex], ), bottomNavigationBar: _bottomNavBar, ); } }
- Membuat HomePage
Buka folder lib/pages, buat file baru “home_page.dart”
import 'package:flutter/material.dart'; import 'package:intl/intl.dart'; import 'package:laundry_app/models/jenis_laundry.dart'; import 'package:laundry_app/models/jenis_pakaian.dart'; import 'package:laundry_app/pages/pembayaran_page.dart'; class HomePage extends StatefulWidget { static const routeName = 'home'; const HomePage({Key key}) : super(key: key); @override _HomePageState createState() => _HomePageState(); } class _HomePageState extends State<HomePage> { final formater = NumberFormat('#,##0.00', 'id'); List<JenisLaundry> pilihLaundry; List<JenisPakaian> pilihPakaian; List<JenisLaundry> jenisLaundry = [ JenisLaundry(jenis: 'Cuci Kering', harga: 6000, status: false), JenisLaundry(jenis: 'Cuci Setrika', harga: 4000, status: false), JenisLaundry(jenis: 'Setrika Saja', harga: 3000, status: false), ]; List<JenisPakaian> jenisPakaian = [ JenisPakaian(jenis: 'Celana Panjang', harga: 4500, status: false), JenisPakaian(jenis: 'Celana Pendek', harga: 3500, status: false), JenisPakaian(jenis: 'Jaket', harga: 7500, status: false), JenisPakaian(jenis: 'Baju Kaos', harga: 3000, status: false), JenisPakaian(jenis: 'Baju Anak', harga: 4000, status: false), JenisPakaian(jenis: 'Selimut', harga: 8000, status: false), JenisPakaian(jenis: 'Sprei', harga: 3500, status: false), JenisPakaian(jenis: 'Sarung Bantal', harga: 4000, status: false), JenisPakaian(jenis: 'Bed Cover Kecil', harga: 2500, status: false), JenisPakaian(jenis: 'Bed Cover Besar', harga: 3500, status: false), JenisPakaian(jenis: 'Sepatu', harga: 5000, status: false), JenisPakaian(jenis: 'CD', harga: 2000, status: false), JenisPakaian(jenis: 'BH', harga: 2000, status: false), JenisPakaian(jenis: 'Kemeja', harga: 2500, status: false), ]; @override Widget build(BuildContext context) { return Scaffold( backgroundColor: Colors.grey[350], body: contentBody(context), ); } Widget contentBody(BuildContext context) { return SafeArea( child: Padding( padding: const EdgeInsets.only(left: 8.0, right: 8.0), child: Stack( children: <Widget>[ ListView.builder( itemCount: 1, itemBuilder: (context, idx) { return Column( crossAxisAlignment: CrossAxisAlignment.start, children: <Widget>[ SizedBox(height: 8.0), contentNamaLaundry(), SizedBox(height: 8.0), contentJenisLaundry(), SizedBox(height: 8.0), contentJenisPakaian(), SizedBox(height: 68.0), ], ); }, ), Positioned( left: 8.0, right: 8.0, bottom: 8.0, child: Container( decoration: BoxDecoration( borderRadius: BorderRadius.circular(8.0), color: Colors.blueGrey, ), child: FlatButton( child: Text( 'Pilih Jenis', style: TextStyle(color: Colors.white), ), onPressed: () { Navigator.push( context, MaterialPageRoute( builder: (context) => PembayaranPage( pilihLaundry: pilihLaundry, pilihPakaian: pilihPakaian, ), ), ); }, ), ), ), ], ), ), ); } Widget contentNamaLaundry() { return Container( decoration: BoxDecoration( boxShadow: [ BoxShadow( color: Colors.grey[400], blurRadius: 5.0, spreadRadius: 0.0, offset: Offset(4.0, 8.0), ) ], color: Colors.white, borderRadius: BorderRadius.circular(8.0), ), child: Padding( padding: const EdgeInsets.only(left: 8.0), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: <Widget>[ SizedBox(height: 8.0), Row( crossAxisAlignment: CrossAxisAlignment.start, children: <Widget>[ Icon(Icons.bubble_chart, color: Colors.grey[600]), Padding( padding: const EdgeInsets.only(left: 8.0), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: <Widget>[ Text( 'Clean Laundry', style: TextStyle(fontWeight: FontWeight.bold), ), SizedBox(height: 4.0), Text( 'Bersih seketika dan wangi sepanjang hari', style: TextStyle( fontSize: 11, color: Colors.grey[700], fontStyle: FontStyle.italic, ), ), ], ), ), ], ), SizedBox(height: 8.0), ], ), ), ); } Widget contentJenisPakaian() { return Container( decoration: BoxDecoration( boxShadow: [ BoxShadow( color: Colors.grey[400], blurRadius: 5.0, spreadRadius: 0.0, offset: Offset(4.0, 8.0), ) ], color: Colors.white, borderRadius: BorderRadius.circular(8.0), ), child: Padding( padding: const EdgeInsets.only(left: 8.0), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: <Widget>[ SizedBox(height: 8.0), Text( 'Jenis Pakaian (Potong)', style: TextStyle(fontWeight: FontWeight.bold), ), ListView.builder( physics: const ClampingScrollPhysics(), shrinkWrap: true, itemCount: jenisPakaian.length, itemBuilder: (context, index) { return Row( children: <Widget>[ Checkbox( value: jenisPakaian[index].status, onChanged: (value) { setState(() { jenisPakaian[index].status = value; pilihPakaian = []; for (final jenis in jenisPakaian) { if (jenis.status == true) { pilihPakaian.add( JenisPakaian( jenis: jenis.jenis, harga: jenis.harga, status: jenis.status, ), ); } } }); }, ), Expanded( child: Text(jenisPakaian[index].jenis), ), Padding( padding: const EdgeInsets.only(right: 16.0), child: Text( 'Rp ' + formater.format(jenisPakaian[index].harga), ), ), ], ); }, ), ], ), ), ); } Widget contentJenisLaundry() { return Container( decoration: BoxDecoration( boxShadow: [ BoxShadow( color: Colors.grey[400], blurRadius: 5.0, spreadRadius: 0.0, offset: Offset(4.0, 8.0), ) ], borderRadius: BorderRadius.circular(8.0), color: Colors.white, ), child: Padding( padding: const EdgeInsets.only(left: 8.0), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: <Widget>[ SizedBox(height: 8.0), Text( 'Jenis Laundry (Kiloan)', style: TextStyle(fontWeight: FontWeight.bold), ), ListView.builder( physics: const ClampingScrollPhysics(), shrinkWrap: true, itemCount: jenisLaundry.length, itemBuilder: (context, index) { return Row( children: <Widget>[ Checkbox( value: jenisLaundry[index].status, onChanged: (value) { setState(() { jenisLaundry[index].status = value; pilihLaundry = []; for (final jenis in jenisLaundry) { if (jenis.status) { pilihLaundry.add( JenisLaundry( jenis: jenis.jenis, harga: jenis.harga, status: jenis.status, ), ); } } }); }, ), Expanded( child: Text(jenisLaundry[index].jenis), ), Padding( padding: const EdgeInsets.only(right: 16.0), child: Text( 'Rp ' + formater.format(jenisLaundry[index].harga), ), ), ], ); }, ), ], ), ), ); } }
- Membuat PembayaranPage
Buka folder lib/pages, buat file baru “pembayaran_page.dart”import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:intl/intl.dart'; import 'package:laundry_app/models/jenis_laundry.dart'; import 'package:laundry_app/models/jenis_pakaian.dart'; import 'package:laundry_app/pages/finish_page.dart'; class PembayaranPage extends StatefulWidget { static const routeName = 'konfirmasi'; const PembayaranPage({ Key key, this.pilihLaundry, this.pilihPakaian, }) : super(key: key); final List<JenisLaundry> pilihLaundry; final List<JenisPakaian> pilihPakaian; @override _PembayaranPageState createState() => _PembayaranPageState(); } class _PembayaranPageState extends State<PembayaranPage> { final formater = NumberFormat('#,##0.00', 'id'); @override Widget build(BuildContext context) { return Scaffold( backgroundColor: Colors.grey[350], appBar: AppBar( backgroundColor: Colors.blueGrey, leading: IconButton( icon: Icon(Icons.arrow_back_ios, color: Colors.white), onPressed: () => Navigator.pop(context), ), title: Text( 'Pembayaran', style: TextStyle(color: Colors.white), ), ), body: contentBody(context), ); } Widget contentBody(BuildContext context) { return SafeArea( child: Padding( padding: const EdgeInsets.only(left: 8.0, right: 8.0), child: Stack( children: <Widget>[ ListView.builder( itemCount: 1, itemBuilder: (context, index) { return Column( children: <Widget>[ SizedBox(height: 8.0), contentOperator(), SizedBox(height: 8.0), contentPelanggan(), SizedBox(height: 8.0), contentDetailPesanan(), SizedBox(height: 68.0), ], ); }, ), Positioned( left: 8.0, right: 8.0, bottom: 8.0, child: Container( decoration: BoxDecoration( borderRadius: BorderRadius.circular(8.0), color: Colors.blueGrey, ), child: FlatButton( child: Text( 'Bayar', style: TextStyle(color: Colors.white), ), onPressed: () { Navigator.of(context).push( CupertinoPageRoute( fullscreenDialog: true, builder: (context) => FinishPage(), ), ); }, ), ), ), ], ), ), ); } Widget contentPelanggan() { return Container( margin: EdgeInsets.only(left: 8.0, right: 8.0), decoration: BoxDecoration( boxShadow: [ BoxShadow( color: Colors.grey[400], blurRadius: 5.0, spreadRadius: 0.0, offset: Offset(4.0, 8.0), ) ], color: Colors.white, borderRadius: BorderRadius.circular(8.0), ), child: Row( crossAxisAlignment: CrossAxisAlignment.start, children: <Widget>[ Padding( padding: const EdgeInsets.only(left: 8.0, top: 8.0), child: Icon( Icons.bubble_chart, color: Colors.blueGrey, ), ), Expanded( child: Padding( padding: const EdgeInsets.only( left: 8.0, right: 8.0, top: 8.0, bottom: 8.0, ), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: <Widget>[ Text( 'Pelanggan', style: TextStyle( fontSize: 12, ), ), SizedBox(height: 6.0), Text( 'Muhammad Abdul Salam', style: TextStyle( fontWeight: FontWeight.bold, fontSize: 12, ), ), SizedBox(height: 6.0), Text( 'Telp. 085870927601', style: TextStyle( fontSize: 12, color: Colors.black, ), ), SizedBox(height: 6.0), Text( 'Jl. Fatmawati No. 177, Kedungmundu, Jawa Tengah, Kota Semarang, Tembalang', style: TextStyle( fontSize: 12, color: Colors.grey, ), ), ], ), ), ), ], ), ); } Widget contentOperator() { return Container( margin: EdgeInsets.only(left: 8.0, right: 8.0), decoration: BoxDecoration( boxShadow: [ BoxShadow( color: Colors.grey[400], blurRadius: 5.0, spreadRadius: 0.0, offset: Offset(4.0, 8.0), ) ], color: Colors.white, borderRadius: BorderRadius.circular(8.0), ), child: Row( crossAxisAlignment: CrossAxisAlignment.start, children: <Widget>[ Padding( padding: const EdgeInsets.only(left: 8.0, top: 8.0), child: Icon( Icons.bubble_chart, color: Colors.blueGrey, ), ), Expanded( child: Padding( padding: const EdgeInsets.only( left: 8.0, right: 8.0, top: 8.0, bottom: 8.0, ), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: <Widget>[ Text( 'Operator', style: TextStyle( fontSize: 12, ), ), SizedBox(height: 6.0), Text( 'Mutakin Akbar', style: TextStyle( fontWeight: FontWeight.bold, fontSize: 12, ), ), ], ), ), ), ], ), ); } Widget contentDetailPesanan() { double total = 0.0; if (widget.pilihLaundry != null) { for (final item in widget.pilihLaundry) { total = total + item.harga; } } if (widget.pilihPakaian != null) { for (final item in widget.pilihPakaian) { total = total + item.harga; } } return Container( margin: EdgeInsets.only(left: 8.0, right: 8.0), decoration: BoxDecoration( boxShadow: [ BoxShadow( color: Colors.grey[400], blurRadius: 5.0, spreadRadius: 0.0, offset: Offset(4.0, 8.0), ) ], color: Colors.white, borderRadius: BorderRadius.circular(8.0), ), child: Row( crossAxisAlignment: CrossAxisAlignment.start, children: <Widget>[ Padding( padding: const EdgeInsets.only(left: 8.0, top: 8.0), child: Icon( Icons.bubble_chart, color: Colors.blueGrey, ), ), Expanded( child: Padding( padding: const EdgeInsets.only( left: 8.0, right: 8.0, top: 8.0, bottom: 8.0, ), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: <Widget>[ Text( 'Detail Pesanan', style: TextStyle( fontWeight: FontWeight.bold, fontSize: 12, ), ), SizedBox(height: 8.0), Divider(height: 1, color: Colors.grey[500]), if (widget.pilihLaundry != null) SizedBox(height: 8.0), if (widget.pilihLaundry != null) ListView.builder( shrinkWrap: true, itemCount: widget.pilihLaundry.length, itemBuilder: (context, index) { return Row( children: <Widget>[ Icon(Icons.event_note, size: 16), Expanded( child: Padding( padding: const EdgeInsets.only(left: 8.0), child: Text(widget.pilihLaundry[index].jenis), ), ), Padding( padding: const EdgeInsets.only(left: 8.0), child: Text( 'Rp ' + formater.format( widget.pilihLaundry[index].harga), ), ), ], ); }, ), if (widget.pilihLaundry != null) SizedBox(height: 8.0), if (widget.pilihLaundry != null) Divider(height: 1, color: Colors.grey[500]), SizedBox(height: 8.0), if (widget.pilihPakaian != null) ListView.builder( shrinkWrap: true, itemCount: widget.pilihPakaian.length, itemBuilder: (context, index) { return Row( children: <Widget>[ Icon(Icons.event_note, size: 16), Expanded( child: Padding( padding: const EdgeInsets.only(left: 8.0), child: Text(widget.pilihPakaian[index].jenis), ), ), Padding( padding: const EdgeInsets.only(left: 8.0), child: Text( 'Rp ' + formater.format( widget.pilihPakaian[index].harga), ), ), ], ); }, ), if (widget.pilihPakaian != null) SizedBox(height: 8.0), if (widget.pilihPakaian != null) Divider(height: 1, color: Colors.grey[500]), SizedBox(height: 8.0), Row( children: <Widget>[ Expanded( child: Text( 'Total', style: TextStyle(fontWeight: FontWeight.bold), ), ), Text( 'Rp ' + formater.format(total), style: TextStyle(fontWeight: FontWeight.bold), ), ], ), SizedBox(height: 8.0), Row( children: <Widget>[ Text( 'Bayar', style: TextStyle(fontWeight: FontWeight.bold), ), Expanded( child: Text( '(Cash)', style: TextStyle(fontWeight: FontWeight.bold), ), ), Text( 'Rp ' + formater.format(total), style: TextStyle(fontWeight: FontWeight.bold), ), ], ), ], ), ), ), ], ), ); } }
- Membuat FinishPage
Buka folder lib/pages, buat file baru “finish_page.dart”import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:laundry_app/pages/main_tab_page.dart'; class FinishPage extends StatefulWidget { static const routeName = 'finish'; const FinishPage({Key key}) : super(key: key); @override _FinishPageState createState() => _FinishPageState(); } class _FinishPageState extends State<FinishPage> { @override Widget build(BuildContext context) { return Scaffold( backgroundColor: Colors.grey[350], appBar: AppBar( backgroundColor: Colors.blueGrey, leading: Icon( Icons.arrow_back_ios, color: Colors.transparent, ), title: Text( 'Selesai', style: TextStyle(color: Colors.white), ), ), body: contentBody(context), ); } Widget contentBody(BuildContext context) { return SafeArea( child: Stack( children: <Widget>[ Padding( padding: const EdgeInsets.only(left: 16.0, right: 8.0), child: Column( children: <Widget>[ SizedBox(height: 20), Container( decoration: BoxDecoration( boxShadow: [ BoxShadow( color: Colors.grey[400], blurRadius: 5.0, spreadRadius: 0.0, offset: Offset(4.0, 8.0), ) ], color: Colors.white, borderRadius: BorderRadius.circular(8.0), ), child: Padding( padding: const EdgeInsets.all(8.0), child: Text( '"Pesanan Anda akan segera diproses, silahkan pantau di aplikasi di menu Pesanan"', style: TextStyle(fontSize: 18), textAlign: TextAlign.center, ), ), ), ], ), ), Positioned( left: 8.0, right: 8.0, bottom: 8.0, child: Container( decoration: BoxDecoration( borderRadius: BorderRadius.circular(8.0), color: Colors.blueGrey, ), child: FlatButton( child: Text( 'Selesai', style: TextStyle(color: Colors.white), ), onPressed: () { Navigator.of(context).push( CupertinoPageRoute( fullscreenDialog: true, builder: (context) => MainTabPage(), ), ); }, ), ), ), ], ), ); } }
- Membuat PesananPage
Buka folder lib/pages, buat file baru “pesanan_page.dart”import 'package:flutter/material.dart'; import 'package:laundry_app/pages/pesanan_detail_page.dart'; class PesananPage extends StatefulWidget { static const routeName = 'pesanan'; const PesananPage({Key key}) : super(key: key); @override _PesananPageState createState() => _PesananPageState(); } class _PesananPageState extends State<PesananPage> { @override Widget build(BuildContext context) { return Scaffold( backgroundColor: Colors.grey[350], appBar: AppBar( leading: Icon(Icons.arrow_back_ios, color: Colors.transparent), title: Text('Pesanan', style: TextStyle(color: Colors.white)), backgroundColor: Colors.blueGrey, elevation: 0, ), body: contentBody(), ); } Widget contentBody() { return SafeArea( child: Padding( padding: const EdgeInsets.only(left: 0.0, right: 0.0), child: Column( children: <Widget>[ Expanded( child: ListView.builder( itemCount: 10, itemBuilder: (context, index) { return GestureDetector( child: Padding( padding: const EdgeInsets.only(top: 16.0), child: Container( margin: EdgeInsets.only(left: 8.0, right: 8.0), decoration: BoxDecoration( boxShadow: [ BoxShadow( color: Colors.grey[400], blurRadius: 5.0, spreadRadius: 0.0, offset: Offset(4.0, 8.0), ) ], color: Colors.white, borderRadius: BorderRadius.circular(8.0), ), child: Row( crossAxisAlignment: CrossAxisAlignment.start, children: <Widget>[ imageList(), contentList(), ], ), ), ), onTap: () { Navigator.push( context, MaterialPageRoute( builder: (context) => PesananDetailPage(), ), ); }, ); }, ), ), ], ), ), ); } Widget contentList() { return Expanded( child: Padding( padding: const EdgeInsets.only( left: 8.0, right: 8.0, top: 8.0, bottom: 8.0, ), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: <Widget>[ Text( 'Telah Selesai', style: TextStyle( fontWeight: FontWeight.bold, fontSize: 12, ), ), SizedBox(height: 6.0), Text( '28/01/2020', style: TextStyle(fontSize: 10), ), SizedBox(height: 6.0), Container( decoration: BoxDecoration( color: Colors.grey[300], borderRadius: BorderRadius.circular(8.0), ), child: Padding( padding: const EdgeInsets.all(6.0), child: Row( children: <Widget>[ Column( crossAxisAlignment: CrossAxisAlignment.start, children: <Widget>[ Text( 'Laundry Anda telah selesai. Pelanggan', style: TextStyle( fontSize: 12, color: Colors.black, ), ), SizedBox(height: 6.0), Text( 'Order # 36176625516618', style: TextStyle( fontSize: 10, color: Colors.grey[900], ), ), ], ), ], ), ), ), ], ), ), ); } Widget imageList() { return Padding( padding: const EdgeInsets.only(left: 8.0, top: 8.0), child: Icon( Icons.bubble_chart, color: Colors.blueGrey, ), ); } }
- Membuat PesananDetailPage
Buka folder lib/pages, buat file baru “pesanan_detail_page.dart”import 'package:flutter/material.dart'; class PesananDetailPage extends StatefulWidget { static const routeName = 'pesanan-detail'; const PesananDetailPage({Key key}) : super(key: key); @override _PesananDetailPageState createState() => _PesananDetailPageState(); } class _PesananDetailPageState extends State<PesananDetailPage> { @override Widget build(BuildContext context) { return Scaffold( backgroundColor: Colors.grey[350], appBar: AppBar( backgroundColor: Colors.blueGrey, leading: IconButton( icon: Icon(Icons.arrow_back_ios, color: Colors.white), onPressed: () => Navigator.pop(context), ), title: Text( 'Detail Pesanan', style: TextStyle(color: Colors.white), ), ), body: contentBody(), ); } Widget contentBody() { return SafeArea( child: Padding( padding: const EdgeInsets.only(left: 0, right: 0), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: <Widget>[ Expanded( child: ListView.builder( itemCount: 1, itemBuilder: (context, index) { return Column( children: <Widget>[ SizedBox(height: 8.0), contentOperator(), SizedBox(height: 8.0), contentPelanggan(), SizedBox(height: 8.0), contentProgress(), SizedBox(height: 8.0), contentPesanan(), ], ); }, ), ), ], ), ), ); } Widget contentPesanan() { return Container( margin: EdgeInsets.only(left: 8.0, right: 8.0), decoration: BoxDecoration( boxShadow: [ BoxShadow( color: Colors.grey[400], blurRadius: 5.0, spreadRadius: 0.0, offset: Offset(4.0, 8.0), ) ], color: Colors.white, borderRadius: BorderRadius.circular(8.0), ), child: Row( crossAxisAlignment: CrossAxisAlignment.start, children: <Widget>[ Padding( padding: const EdgeInsets.only(left: 8.0, top: 8.0), child: Icon( Icons.bubble_chart, color: Colors.blueGrey, ), ), Expanded( child: Padding( padding: const EdgeInsets.only( left: 8.0, right: 8.0, top: 8.0, bottom: 8.0, ), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: <Widget>[ Text( 'Pesanan', style: TextStyle( fontSize: 12, ), ), SizedBox(height: 6.0), Text( '# 36176625516618', style: TextStyle( fontWeight: FontWeight.bold, fontSize: 12, ), ), ], ), ), ), ], ), ); } Widget contentProgress() { return Container( margin: EdgeInsets.only(left: 8.0, right: 8.0), decoration: BoxDecoration( boxShadow: [ BoxShadow( color: Colors.grey[400], blurRadius: 5.0, spreadRadius: 0.0, offset: Offset(4.0, 8.0), ) ], color: Colors.white, borderRadius: BorderRadius.circular(8.0), ), child: Row( crossAxisAlignment: CrossAxisAlignment.start, children: <Widget>[ Padding( padding: const EdgeInsets.only(left: 8.0, top: 8.0), child: Icon( Icons.bubble_chart, color: Colors.blueGrey, ), ), Expanded( child: Padding( padding: const EdgeInsets.only( left: 8.0, right: 8.0, top: 8.0, bottom: 8.0, ), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: <Widget>[ Text( 'Telah Selesai', style: TextStyle( fontWeight: FontWeight.bold, fontSize: 12, ), ), SizedBox(height: 6.0), Row( children: <Widget>[ Text( '28 Jan 10:57', style: TextStyle( fontSize: 11, color: Colors.grey[700], ), ), Padding( padding: const EdgeInsets.only(left: 8.0), child: Column( children: <Widget>[ Text( 'Laundry Anda telah selesai.', style: TextStyle( fontSize: 12, color: Colors.black, ), ), ], ), ), ], ), SizedBox(height: 16.0), Text( 'Proses Pengeringan', style: TextStyle( fontWeight: FontWeight.bold, fontSize: 12, ), ), SizedBox(height: 6.0), Row( crossAxisAlignment: CrossAxisAlignment.start, children: <Widget>[ Text( '28 Jan 05:37', style: TextStyle( fontSize: 11, color: Colors.grey[700], ), ), Expanded( child: Padding( padding: const EdgeInsets.only(left: 8.0), child: Column( children: <Widget>[ Text( 'Operator kami sedang melakukan proses pengeringan laundry anda', style: TextStyle( fontSize: 12, color: Colors.black, ), ), ], ), ), ), ], ), SizedBox(height: 16.0), Text( 'Proses Pencucian', style: TextStyle( fontWeight: FontWeight.bold, fontSize: 12, ), ), SizedBox(height: 6.0), Row( crossAxisAlignment: CrossAxisAlignment.start, children: <Widget>[ Text( '27 Jan 12:57', style: TextStyle( fontSize: 11, color: Colors.grey[700], ), ), Expanded( child: Padding( padding: const EdgeInsets.only(left: 8.0), child: Column( children: <Widget>[ Text( 'Operator kami sedang melakukan proses pencucian laundry anda', style: TextStyle( fontSize: 12, color: Colors.black, ), ), ], ), ), ), ], ), ], ), ), ), ], ), ); } Widget contentPelanggan() { return Container( margin: EdgeInsets.only(left: 8.0, right: 8.0), decoration: BoxDecoration( boxShadow: [ BoxShadow( color: Colors.grey[400], blurRadius: 5.0, spreadRadius: 0.0, offset: Offset(4.0, 8.0), ) ], color: Colors.white, borderRadius: BorderRadius.circular(8.0), ), child: Row( crossAxisAlignment: CrossAxisAlignment.start, children: <Widget>[ Padding( padding: const EdgeInsets.only(left: 8.0, top: 8.0), child: Icon( Icons.bubble_chart, color: Colors.blueGrey, ), ), Expanded( child: Padding( padding: const EdgeInsets.only( left: 8.0, right: 8.0, top: 8.0, bottom: 8.0, ), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: <Widget>[ Text( 'Pelanggan', style: TextStyle( fontSize: 12, ), ), SizedBox(height: 6.0), Text( 'Muhammad Abdul Salam', style: TextStyle( fontWeight: FontWeight.bold, fontSize: 12, ), ), SizedBox(height: 6.0), Text( 'Jl. Fatmawati No. 177, Kedungmundu, Jawa Tengah, Kota Semarang, Tembalang', style: TextStyle( fontSize: 12, color: Colors.grey, ), ), ], ), ), ), ], ), ); } Widget contentOperator() { return Container( margin: EdgeInsets.only(left: 8.0, right: 8.0), decoration: BoxDecoration( boxShadow: [ BoxShadow( color: Colors.grey[400], blurRadius: 5.0, spreadRadius: 0.0, offset: Offset(4.0, 8.0), ) ], color: Colors.white, borderRadius: BorderRadius.circular(8.0), ), child: Row( crossAxisAlignment: CrossAxisAlignment.start, children: <Widget>[ Padding( padding: const EdgeInsets.only(left: 8.0, top: 8.0), child: Icon( Icons.bubble_chart, color: Colors.blueGrey, ), ), Expanded( child: Padding( padding: const EdgeInsets.only( left: 8.0, right: 8.0, top: 8.0, bottom: 8.0, ), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: <Widget>[ Text( 'Operator', style: TextStyle( fontSize: 12, ), ), SizedBox(height: 6.0), Text( 'Mutakin Akbar', style: TextStyle( fontWeight: FontWeight.bold, fontSize: 12, ), ), ], ), ), ), ], ), ); } }
- Membuat ProfilePage
Buka folder lib/pages, buat file baru “profile_page.dart”import 'package:flutter/material.dart'; import 'package:laundry_app/pages/setting_page.dart'; class ProfilePage extends StatefulWidget { static const routeName = 'profile'; const ProfilePage({Key key}) : super(key: key); @override _ProfilePageState createState() => _ProfilePageState(); } class _ProfilePageState extends State<ProfilePage> { @override Widget build(BuildContext context) { return Scaffold( backgroundColor: Colors.grey[350], body: contentBody(context), ); } Widget contentBody(BuildContext context) { return Column( children: <Widget>[ Container( decoration: BoxDecoration( color: Colors.blueGrey, ), child: Padding( padding: const EdgeInsets.only( left: 8.0, right: 8.0, top: 8.0, bottom: 8.0, ), child: Column( crossAxisAlignment: CrossAxisAlignment.end, children: <Widget>[ SizedBox(height: 45), IconButton( icon: Icon(Icons.settings, color: Colors.white), onPressed: () { Navigator.push( context, MaterialPageRoute( builder: (context) => SettingPage(), ), ); }, ), Row( crossAxisAlignment: CrossAxisAlignment.start, children: <Widget>[ Icon( Icons.account_circle, color: Colors.white, size: 64, ), Padding( padding: const EdgeInsets.only(left: 8.0), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: <Widget>[ Text( 'Muhammad Abdul Salam', style: TextStyle( color: Colors.white, ), ), SizedBox(height: 4.0), Container( decoration: BoxDecoration( color: Colors.grey[700], borderRadius: BorderRadius.circular(4.0), ), child: Padding( padding: const EdgeInsets.only( left: 4.0, right: 4.0, top: 2.0, bottom: 2.0, ), child: Text( '[email protected]', style: TextStyle( color: Colors.white, ), ), ), ), ], ), ), ], ), ], ), ), ), contentBantuan(), ], ); } Widget contentBantuan() { return Container( decoration: BoxDecoration( color: Colors.white, ), child: Padding( padding: const EdgeInsets.all(4.0), child: Row( children: <Widget>[ Icon( Icons.notifications, size: 16, color: Colors.grey[700], ), Expanded( child: Padding( padding: const EdgeInsets.only(left: 8.0), child: Text( 'Panduan mencuci baju yang baik', style: TextStyle( fontSize: 11, color: Colors.grey[700], fontWeight: FontWeight.bold, ), ), ), ), Text( 'Lihat >', style: TextStyle( fontSize: 11, color: Colors.blueAccent[700], fontWeight: FontWeight.bold, ), ), ], ), ), ); } }
- Membuat SettingPage
Buka folder lib/pages, buat file baru “setting_page.dart”import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:laundry_app/pages/login_page.dart'; class SettingPage extends StatefulWidget { static const routeName = 'setting'; const SettingPage({Key key}) : super(key: key); @override _SettingPageState createState() => _SettingPageState(); } class _SettingPageState extends State<SettingPage> { @override Widget build(BuildContext context) { return Scaffold( backgroundColor: Colors.grey[350], appBar: AppBar( leading: IconButton( icon: Icon(Icons.arrow_back_ios, color: Colors.white), onPressed: () => Navigator.pop(context), ), title: Text('Pengaturan', style: TextStyle(color: Colors.white)), backgroundColor: Colors.blueGrey, elevation: 0, ), body: contentBody(context), ); } Widget contentBody(BuildContext context) { return SafeArea( child: Column( children: <Widget>[ SizedBox(height: 8.0), informasiAkun(), Divider(height: 1), alamatSaya(), Divider(height: 1), pesan(), SizedBox(height: 8.0), perlindunganPrivasi(), Divider(height: 1), kebijakan(), Divider(height: 1), bantuan(), SizedBox(height: 8.0), keluar(context), ], ), ); } Widget keluar(BuildContext context) { return GestureDetector( child: Row( children: <Widget>[ Expanded( child: Container( color: Colors.white, child: Padding( padding: const EdgeInsets.all(12.0), child: Text( 'Keluar', style: TextStyle(color: Colors.red[700]), textAlign: TextAlign.center, ), ), ), ), ], ), onTap: () { Navigator.of(context).push( CupertinoPageRoute( fullscreenDialog: true, builder: (context) => LoginPage(), ), ); }, ); } Widget bantuan() { return Row( children: <Widget>[ Expanded( child: Container( color: Colors.white, child: Padding( padding: const EdgeInsets.all(12.0), child: Text('Bantuan'), ), ), ), ], ); } Widget kebijakan() { return Row( children: <Widget>[ Expanded( child: Container( color: Colors.white, child: Padding( padding: const EdgeInsets.all(12.0), child: Text('Kebijakan'), ), ), ), ], ); } Widget perlindunganPrivasi() { return Row( children: <Widget>[ Expanded( child: Container( color: Colors.white, child: Padding( padding: const EdgeInsets.all(12.0), child: Text('Perlindungan Privasi'), ), ), ), ], ); } Widget pesan() { return Row( children: <Widget>[ Expanded( child: Container( color: Colors.white, child: Padding( padding: const EdgeInsets.all(12.0), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: <Widget>[ Text('Pesan'), SizedBox(height: 4.0), Text( 'Menerima informasi terbaru semua hal yang penting! :)', style: TextStyle( color: Colors.grey[700], fontSize: 11, ), ), ], ), ), ), ), ], ); } Widget alamatSaya() { return Row( children: <Widget>[ Expanded( child: Container( color: Colors.white, child: Padding( padding: const EdgeInsets.all(12.0), child: Text('Alamat Saya'), ), ), ), ], ); } Widget informasiAkun() { return Row( children: <Widget>[ Expanded( child: Container( color: Colors.white, child: Padding( padding: const EdgeInsets.all(12.0), child: Text('Informasi Akun'), ), ), ), ], ); } }
- Buat folder lib/models
Buat file baru di dalam folder models -> jenis_laundry.dartclass JenisLaundry { JenisLaundry({ this.jenis, this.harga, this.status, }); String jenis; double harga; bool status; }
Buat file baru di dalam folder models -> jenis_pakaian.dart
class JenisPakaian { JenisPakaian({ this.jenis, this.harga, this.status, }); String jenis; double harga; bool status; }
- Buat folder lib/widgets
Buat file baru di dalam folder widgets -> validate.dart
import 'package:flutter/material.dart'; class Validate extends StatelessWidget { Validate({@required this.message}); final String message; @override Widget build(BuildContext context) { return Column( children: <Widget>[ SizedBox(height: 4.0), Text( message, style: TextStyle( color: Colors.red, fontWeight: FontWeight.bold, ), ), ], ); } }
- flutter run
Happy Coding 🙂
I’m a result mobile engineer, as well as deep understanding of digital systems.
salam kenal om
salam kenal, terima kasih sudah berkunjung 🙂