Tutorial Membuat Aplikasi Sejarah Pahlawan Indonesia dengan Flutter |
Sebelumnya saya sudah pernah membuat tutorial yang sama, namun menggunakan Native ya, bisa kalian lihat tutorialnya DISINI. Untuk di versi Flutter ini, kita harus import library atau assets ke dalam pubspec.yaml ya. Cara import library di Flutter bisa kalian baca DISINI.
Tetapi jika kalian ingin tahu cara mengaplikasikannya, silahkan lanjut baca artikel ini sampai selesai. Jika kamu ingin mencoba tutorial aplikasi ini dengan versi video, berikut saya berikan Videonya:
Jangan lupa subscribe Channel Youtube saya juga ya Azhar Rivaldi, karena disana ada banyak tutorial-tutorial untuk membuat aplikasi lainnya.
Oke langsung saja tanpa basa-basi lagi kita langsung ke langkah-langkahnya ya.
Pertama kalian ubah isi class main.dart menjadi seperti ini:
void main() { runApp(const MyApp()); } class MyApp extends StatelessWidget { const MyApp({super.key}); @override Widget build(BuildContext context) { return MaterialApp( title: 'Sejarah Pahlawan Indonesia', debugShowCheckedModeBanner: false, theme: ThemeData( primaryColor: Colors.white, ), home: const Home(), ); } }Berikutnya kalian buat class model model_main.dart :
class ModelMain { String? nama; String? nama2; String? kategori; String? asal; String? lahir; String? usia; String? gugur; String? lokasimakam; String? history; String? img; ModelMain(this.nama, this.nama2, this.kategori, this.asal, this.lahir, this.usia, this.gugur, this.lokasimakam, this.history, this.img); ModelMain.fromJson(MapBerikutnya kalian buat class home home_page.dart :json) { nama = json['nama']; nama2 = json['nama2']; kategori = json['kategori']; asal = json['asal']; lahir = json['lahir']; usia = json['usia']; gugur = json['gugur']; lokasimakam = json['lokasimakam']; history = json['history']; img = json['img']; } }
void main() { runApp(const Home()); } class Home extends StatelessWidget { const Home({super.key}); @override Widget build(BuildContext context) { return const MaterialApp( debugShowCheckedModeBanner: false, home: HomePage(), ); } } class HomePage extends StatefulWidget { const HomePage({super.key}); @override StateLangkah terakhir kalian buat class dengan nama detail_page.dart. Untuk isinya seperti ini:createState() { return _HomeState(); } } class _HomeState extends State { Future > readJsonData() async { final jsonData = await root_bundle.rootBundle .loadString('assets/pahlawan_nasional.json'); final listData = json.decode(jsonData) as List
; return listData.map((e) => ModelMain.fromJson(e)).toList(); } TextEditingController searchController = TextEditingController(); String? filterData; ScrollController scrollController = ScrollController(); bool showFab = false; @override initState() { searchController.addListener(() { setState(() { filterData = searchController.text; }); }); scrollController.addListener(() { if (scrollController.offset > 10) { showFab = true; setState(() {}); } else { showFab = false; setState(() {}); } }); super.initState(); } @override void dispose() { searchController.dispose(); scrollController.dispose(); super.dispose(); } @override Widget build(BuildContext context) { return Scaffold( backgroundColor: Colors.white, appBar: AppBar( title: const Center( child: Text('Sejarah Pahlawan', style: TextStyle( color: Colors.green, fontWeight: FontWeight.bold, fontSize: 30)), ), backgroundColor: Colors.white, elevation: 0, ), floatingActionButton: AnimatedOpacity( duration: const Duration(milliseconds: 1000), opacity: showFab ? 1.0 : 0.0, child: FloatingActionButton( onPressed: () { scrollController.animateTo(0, duration: const Duration(milliseconds: 500), curve: Curves.fastOutSlowIn); }, backgroundColor: Colors.green, child: const Icon(Icons.arrow_upward), ), ), body: Column( children: [ Padding( padding: const EdgeInsets.all(8), child: TextField( controller: searchController, decoration: InputDecoration( hintText: 'Cari nama pahlawan', suffixIcon: searchController.text.isEmpty ? null : IconButton( onPressed: searchController.clear, icon: const Icon( Icons.clear, color: Colors.red, ), ), contentPadding: const EdgeInsets.fromLTRB(20, 14, 20, 14), border: OutlineInputBorder( borderRadius: BorderRadius.circular(20)), focusedBorder: OutlineInputBorder( borderRadius: BorderRadius.circular(20), borderSide: const BorderSide(color: Colors.green, width: 2), )), ), ), Expanded( child: FutureBuilder( future: readJsonData(), builder: (context, data) { if (data.hasError) { return Center(child: Text("${data.error}")); } else if (data.hasData) { var items = data.data as List ; return ListView.builder( controller: scrollController, shrinkWrap: true, itemCount: items == null ? 0 : items.length, itemBuilder: (context, index) { return filterData == null || filterData == "" ? GestureDetector( onTap: () { String nama = items[index].nama.toString(); String nama2 = items[index].nama2.toString(); String kategori = items[index].kategori.toString(); String asal = items[index].asal.toString(); String usia = items[index].usia.toString(); String lahir = items[index].lahir.toString(); String gugur = items[index].gugur.toString(); String lokasimakam = items[index].lokasimakam.toString(); String history = items[index].history.toString(); String img = items[index].img.toString(); Navigator.push( context, MaterialPageRoute( builder: (context) => DetailPahlawan( nama: nama, nama2: nama2, kategori: kategori, asal: asal, usia: usia, lahir: lahir, gugur: gugur, lokasimakam: lokasimakam, history: history, img: img))); }, child: Card( shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(10)), elevation: 5, margin: const EdgeInsets.all(10), color: Colors.white, child: Padding( padding: const EdgeInsets.all(8), child: Row( children: [ Container( margin: const EdgeInsets.only(right: 14), width: 70, height: 70, decoration: BoxDecoration( shape: BoxShape.circle, image: DecorationImage( fit: BoxFit.cover, image: NetworkImage( items[index].img.toString(), ), ), ), ), Flexible( child: Column( crossAxisAlignment: CrossAxisAlignment.start, mainAxisAlignment: MainAxisAlignment.center, children: [ Text( items[index].nama.toString(), style: const TextStyle( color: Colors.black, fontSize: 18), maxLines: 2, ), const SizedBox(height: 10), Text( items[index].nama2.toString(), style: const TextStyle( color: Colors.black, fontSize: 14), maxLines: 2, ), ], ), ) ], ), ), ), ) : '${items[index].nama}' .toLowerCase() .contains(filterData!.toLowerCase()) ? GestureDetector( onTap: () {}, child: Card( shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(10)), elevation: 4, margin: const EdgeInsets.all(10), color: Colors.white, child: Padding( padding: const EdgeInsets.all(8), child: Row( children: [ Container( margin: const EdgeInsets.only( right: 14), width: 70, height: 70, decoration: BoxDecoration( shape: BoxShape.circle, image: DecorationImage( fit: BoxFit.cover, image: NetworkImage( items[index].img.toString(), ), ), ), ), Flexible( child: Column( crossAxisAlignment: CrossAxisAlignment.start, mainAxisAlignment: MainAxisAlignment.center, children: [ Text( items[index] .nama .toString(), style: const TextStyle( color: Colors.black, fontSize: 18), maxLines: 2, ), const SizedBox(height: 10), Container( padding: const EdgeInsets.all(4), decoration: BoxDecoration( borderRadius: BorderRadius .circular(10), color: Colors.green), child: Text( items[index] .kategori .toString(), style: const TextStyle( color: Colors.white, fontSize: 10), maxLines: 2, ), ), ], ), ) ], ), ), ), ) : Container(); }); } else { return const Center( child: CircularProgressIndicator(), ); } }, ), ), ], ), ); } }
class DetailPahlawan extends StatefulWidget { final String nama, nama2, kategori, asal, usia, lahir, gugur, lokasimakam, history, img; const DetailPahlawan( {Key? key, required this.nama, required this.nama2, required this.kategori, required this.asal, required this.usia, required this.lahir, required this.gugur, required this.lokasimakam, required this.history, required this.img}) : super(key: key); @override _DetailPahlawanState createState() => _DetailPahlawanState(nama, nama2, kategori, asal, usia, lahir, gugur, lokasimakam, history, img); } class _DetailPahlawanState extends StateJika kalian mengikuti langkah-langkah diatas dengan baik, pasti aplikasi yang kalian buat akan berjalan sebagaimana mestinya. Untuk Link Source Code bisa kalian unduh DISINI. Namun jika mengalami Error, silahkan berikan komentar dan kita diskusikan bersama atau bisa ditonton sampai habis video tutorialnya.{ String nama, nama2, kategori, asal, usia, lahir, gugur, lokasimakam, history, img; _DetailPahlawanState(this.nama, this.nama2, this.kategori, this.asal, this.usia, this.lahir, this.gugur, this.lokasimakam, this.history, this.img); @override Widget build(BuildContext context) { return Scaffold( backgroundColor: Colors.white, body: Stack( children: [ Container( width: MediaQuery.of(context).size.width, height: 296, decoration: BoxDecoration( image: DecorationImage( image: NetworkImage(img), fit: BoxFit.cover), ), ), Align( alignment: Alignment.topLeft, child: InkWell( onTap: () => Navigator.pop(context), child: SafeArea( child: Container( width: 50, height: 50, margin: const EdgeInsets.only(left: 20, top: 10), decoration: const BoxDecoration( color: Colors.white, shape: BoxShape.circle, ), child: const Padding( padding: EdgeInsets.only(left: 8), child: Icon(Icons.arrow_back_ios), ), ), ), ), ), Container( width: MediaQuery.of(context).size.width, margin: const EdgeInsets.only(top: 250), padding: const EdgeInsets.symmetric(horizontal: 20), decoration: const BoxDecoration( color: Colors.white, borderRadius: BorderRadius.only( topLeft: Radius.circular(28), topRight: Radius.circular(28), ), ), child: SingleChildScrollView( child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ const SizedBox( height: 20, ), const Text( "Biodata Pahlawan :", style: TextStyle(color: Colors.black, fontSize: 20, fontWeight: FontWeight.bold), ), const SizedBox( height: 20, ), Text( "Nama : $nama", style: const TextStyle(fontSize: 14, color: Colors.black), ), const SizedBox( height: 8, ), Text( "Nama Lengkap : $nama2", style: const TextStyle(fontSize: 14, color: Colors.black), ), const SizedBox( height: 8, ), Text( "Lahir : $lahir", style: const TextStyle(fontSize: 14, color: Colors.black), ), const SizedBox( height: 8, ), Text( "Wafat : $gugur", style: const TextStyle(fontSize: 14, color: Colors.black), ), const SizedBox( height: 8, ), Text( "Lokasi Makam : $lokasimakam", style: const TextStyle(fontSize: 14, color: Colors.black), ), const SizedBox( height: 8, ), Text( "Riwayat : $history", style: const TextStyle(fontSize: 14, color: Colors.black), ), const SizedBox( height: 8, ), ], ), ), ) ], ), ); } }
Support Blog Rivaldi 48 agar terus bisa membagikan artikel-artikel yang bermanfaat dengan cara klik link Sociabuzz dibawah ini :https://sociabuzz.com/azharrvldi_/donate (bisa pakai GoPay, OVO, DANA, Bank Transfer)
Demikian informasi yang saya bagikan untuk kalian. Jangan lupa bagikan artikel ini ke teman-teman kalian agar ikut membaca Tutorial Membuat Aplikasi Sejarah Pahlawan Indonesia dengan Flutter ini. Subscribe juga blog Rivaldi 48 ini agar kalian mendapatkan notifikasi saat Admin update artikel terbaru. Semoga kalian lebih nyaman dan mudah dalam mengakses Blog Rivaldi 48 dimanapun kalian berada. Terima Kasih. Follow Instagram Admin @azhardvls_
0 Comments
Post a Comment
Silahkan tinggalkan komentar jika Anda punya saran, kritik, atau pertanyaan seputar topik pembahasan. Gunakan bahasa yang bijak dan santun. Terima Kasih.