Codelab 1

 Pada kelas ini kita akan mengembangkan sebuah aplikasi yang menampilkan tempat-tempat wisata di Bandung. Hasil akhir dari keseluruhan codelab akan seperti berikut:

20210425131945a4abeea012bc2e46e31538884424008b.gif

Dalam codelab pertama ini kita akan membuat sebuah tampilan yang menggabungkan semua widget-widget yang sebelumnya kita pelajari. Tampilannya adalah seperti berikut:

202104251320085fde1442232fc33aa20602bef39b2eb2.png

Sebelum kita membuat tampilan di atas, kita akan bedah terlebih dahulu layout-nya.

Pada layout di atas kita dapat memetakan widget-widget dalam bentuk diagram seperti di bawah ini:

20200615123022ba51f3071b1abe12d3704a7ce5db8b4d.png

  1. Buat project Flutter baru dan berikan nama yang sesuai, misalnya wisatabandung. Hapus kode aplikasi counter yang diberikan ketika project dibuat.
  2. Tuliskan kode dasar yang menampilkan widget MaterialAppseperti berikut:
    1. import 'package:flutter/material.dart';
    2.  
    3. void main() => runApp(const MyApp());
    4.  
    5. class MyApp extends StatelessWidget {
    6. const MyApp({Key? key}) : super(key: key);
    7.  
    8.   @override
    9.   Widget build(BuildContext context) {
    10.     return MaterialApp(
    11.       title: 'Wisata Bandung',
    12.       theme: ThemeData(),
    13.     );
    14.   }
    15. }
  3. Lalu kita akan membuat kode untuk susunan widget sesuai diagram yang telah kita buat. Untuk membuat kode kita lebih rapi kita akan membuat kelas Stateless Widget baru untuk menampung kode tampilan kita. Mari namakan kelas ini DetailScreen.
    1. class DetailScreen extends StatelessWidget {
    2. const DetailScreen({Key? key}) : super(key: key);
    3.  
    4.   @override
    5.   Widget build(BuildContext context) {
    6.     return Scaffold();
    7.   }
    8. }
    Jangan lupa untuk menambahkan widget DetailScreen sebagai home dari MaterialApp.
    1. class MyApp extends StatelessWidget {
    2. const MyApp({Key? key}) : super(key: key);
    3.  
    4.   @override
    5.   Widget build(BuildContext context) {
    6.     return MaterialApp(
    7.       title: 'Wisata Bandung',
    8.       theme: ThemeData(),
    9.       home: const DetailScreen(),
    10.     );
    11.   }
    12. }
  4. Sesuai diagram di atas, kita akan menyusun beberapa widget secara vertikal sehingga kita perlu menggunakan widget Column.
    1. class DetailScreen extends StatelessWidget {
    2. const DetailScreen({Key? key}) : super(key: key);
    3.  
    4. @override
    5. Widget build(BuildContext context) {
    6. return Scaffold(
    7. body: Column(),
    8. );
    9. }
    10. }
    Jalankan aplikasi Anda. Saat ini device atau emulator Anda memang masih belum menampilkan apa pun. Namun, kita akan memanfaatkan fitur hot reload untuk melihat perubahan-perubahan yang akan kita lakukan ke depan.
  5. Komponen pertama yang akan kita buat adalah bagian judul dari halaman. Tentunya untuk menampilkan teks kita akan menggunakan widget Text.
    1. class DetailScreen extends StatelessWidget {
    2. const DetailScreen({Key? key}) : super(key: key);
    3.  
    4.   @override
    5.   Widget build(BuildContext context) {
    6.     return Scaffold(
    7.       body: Column(
    8.         children: <Widget>[
    9. const Text('Farm House Lembang'),
    10. ],
    11.       ),
    12.     );
    13.   }
    14. }
  6. Ketika Anda menyimpan project atau menjalankan hot reload, tampilan aplikasi Anda sekarang mungkin tidak sesuai dengan keinginan, seperti teks terlalu ke atas dan juga terlalu kecil.
    202104251322093fcb5140ee8a825f4ec2150ec6b9fe84.jpegUntuk itulah kita perlu membungkus widget Text ke dalam Container supaya kita dapat memberikan property seperti margin atau padding. Jika Anda menggunakan IDE Android Studio, Anda dapat memanfaatkan shortcut Alt+Enter untuk membungkus widget ke widget lain.
    202104251322465819b8c1d2b88fdd3ec6d029a0689961.gif
  7. Tambahkan margin atas supaya teks memiliki jarak terhadap bagian atas layar.
    1. class DetailScreen extends StatelessWidget {
    2. const DetailScreen({Key? key}) : super(key: key);
    3.  
    4.   @override
    5.   Widget build(BuildContext context) {
    6.     return Scaffold(
    7.       body: Column(
    8.         children: <Widget>[
    9.           Container(
    10.             margin: const EdgeInsets.only(top: 16.0),
    11.             child: const Text('Farm House Lembang'),
    12.           ),
    13.         ],
    14.       ),
    15.     );
    16.   }
    17. }
    Pada kode di atas kita hanya memberikan margin atas sebesar sebesar 16.0. Anda dapat memanfaatkan metode EdgeInsets lain seperti all() untuk memberikan margin ke semua sisi atau symmetric() apabila Anda ingin memberikan margin ke sisi vertikal atau horizontal.
  8. Jika Anda kesulitan menentukan margin atas, khususnya pada perangkat yang memiliki notch yang umumnya memiliki status bar yang lebih besar, Anda dapat memanfaatkan widget SafeArea.
    1. class DetailScreen extends StatelessWidget {
    2. const DetailScreen({Key? key}) : super(key: key);
    3.  
    4.   @override
    5.   Widget build(BuildContext context) {
    6.     return Scaffold(
    7.       body: SafeArea(
    8.         child: Column(
    9.           children: <Widget>[
    10.             Container(
    11.               margin: const EdgeInsets.only(top: 16.0),
    12.               child: const Text('Farm House Lembang'),
    13.             )
    14.           ],
    15.         ),
    16.       ),
    17.     );
    18.   }
    19. }
    Widget ini akan memberikan padding yang secara otomatis menyesuaikan perangkat yang digunakan.
    20210425132439c166c585093014ef522ac1457bf9e448.png
  9. Selanjutnya, sesuai contoh kita akan membuat teks judul berada di tengah. Tambahkan parameter atau properti textAlign pada widget Text. Selain itu, tambahkan juga style dengan memperbesar ukuran teks agar tulisan dapat dibaca.
    1. Container(
    2.   margin: EdgeInsets.only(top: 16.0),
    3.   child: const Text(
    4.     'Farm House Lembang',
    5.     textAlign: TextAlign.center,
    6.     style: TextStyle(
    7.       fontSize: 30.0,
    8.       fontWeight: FontWeight.bold,
    9. ),
    10.   ),
    11. ),
    Lakukan hot reload. Tidak ada perubahan, apa sebabnya? Jika menggunakan Android Studio Anda dapat memanfaatkan fitur Flutter Inspector untuk melihat layout widget di dalam aplikasi.
    20210425132539b83ca0cdc01669f05d97fbb95f9e5c4c.gifDari gambar di atas bisa kita lihat ternyata layout aplikasi kita tidak penuh hingga seluruh halaman. Ini disebabkan sisi horizontal dari Column hanya menyesuaikan dengan konten yang ada di dalamnya. Untuk memaksimalkan ukuran lebar dari Column, tambahkan kode berikut:
    1. body: SafeArea(
    2.   child: Column(
    3.     crossAxisAlignment: CrossAxisAlignment.stretch,
    4.     children: <Widget>[
    5.       Container(
    6.         margin: EdgeInsets.only(top: 16.0),
    7.         child: Text(
    8.           'Farm House Lembang',
    9.           textAlign: TextAlign.center,
    10.           style: TextStyle(
    11.             fontSize: 30.0,
    12.             fontWeight: FontWeight.bold,
    13.           ),
    14.         ),
    15.       ),
    16.     ],
    17.   ),
    18. ),
  10. Setelah menyelesaikan judul, selanjutnya kita akan membuat bagian kedua yaitu informasi dari tempat wisata.
    20210425132634936b9f6bc4d83c33d804ba3918392edd.jpegSeperti yang terlihat kita perlu menyusun widget secara horizontal dan vertikal. Mari tambahkan child kedua dari Column dengan sebuah Container berisi Row. Tambahkan juga margin pada sisi atas dan bawah untuk memberikan jarak antar widget.
    1. class DetailScreen extends StatelessWidget {
    2. const DetailScreen({Key? key}) : super(key: key);
    3.  
    4.   @override
    5.   Widget build(BuildContext context) {
    6.     return Scaffold(
    7.       body: SafeArea(
    8.         child: Column(
    9.           crossAxisAlignment: CrossAxisAlignment.stretch,
    10.           children: <Widget>[
    11.             Container(...),
    12.             Container(
    13. margin: const EdgeInsets.symmetric(vertical: 16.0),
    14.               child: Row(
    15.                 children: <Widget>[],
    16.               ),
    17. ),
    18.           ],
    19.         ),
    20.       ),
    21.     );
    22.   }
    23. }
  11. Buat widget Column untuk menyusun Icon dan Text.
    1. class DetailScreen extends StatelessWidget {
    2. const DetailScreen({Key? key}) : super(key: key);
    3.  
    4.   @override
    5.   Widget build(BuildContext context) {
    6.     return Scaffold(
    7.       body: SafeArea(
    8.         child: Column(
    9.           crossAxisAlignment: CrossAxisAlignment.stretch,
    10.           children: <Widget>[
    11.             Container(...),
    12.             Container(
    13.               margin: EdgeInsets.symmetric(vertical: 16.0),
    14.               child: Row(
    15.                 children: <Widget>[
    16.                   Column(
    17. children: const <Widget>[
    18.                       Icon(Icons.calendar_today),
    19.                       Text('Open Everyday'),
    20.                     ],
    21. ),
    22.                 ],
    23.               ),
    24.             ),
    25.           ],
    26.         ),
    27.       ),
    28.     );
    29.   }
    30. }
    Jika Anda merasa jarak antara Icon dan Text terlalu rapat, Anda dapat menambahkan widget SizedBoxuntuk membuat “kotak” yang berguna untuk memberikan jarak.
    1. Column(
    2.   children: const <Widget>[
    3.     Icon(Icons.calendar_today),
    4.     SizedBox(height: 8.0),
    5.     Text('Open Everyday'),
    6.   ],
    7. ),
  12. Selanjutnya sebagai tantangan, lengkapilah informasi tempat wisata dengan pasangan ikon dan teks sesuai contoh yang diberikan.
    202104251342330837dda51f8fac145cf27983934d5640.jpeg
  13. Untuk menyusun Row seperti di atas, pastikan menggunakan mainAxisAlignment seperti ini:
    1. class DetailScreen extends StatelessWidget {
    2. const DetailScreen({Key? key}) : super(key: key);
    3.  
    4.   @override
    5.   Widget build(BuildContext context) {
    6.     return Scaffold(
    7.       body: SafeArea(
    8.         child: Column(
    9.           crossAxisAlignment: CrossAxisAlignment.stretch,
    10.           children: <Widget>[
    11.             Container(...),
    12.             Container(
    13.               margin: const EdgeInsets.symmetric(vertical: 16.0),
    14.               child: Row(
    15.                 mainAxisAlignment: MainAxisAlignment.spaceEvenly,
    16.                 children: <Widget>[
    17.                   Column(...),
    18.                   Column(...),
    19.                   Column(...)
    20.                 ],
    21.               ),
    22.             ),
    23.           ],
    24.         ),
    25.       ),
    26.     );
    27.   }
    28. }
  14. Pada langkah ini harusnya Anda sudah bisa menampilkan teks deskripsi sesuai langkah yang diberikan sebelumnya. Anda cukup menambahkan widget Container dan Textuntuk menampilkan konten deskripsi. Anda juga dapat menambahkan style sesuai selera Anda.
    1. Container(
    2.   padding: const EdgeInsets.all(16.0),
    3.   child: const Text(
    4.     'Berada di jalur utama Bandung-Lembang, Farm House menjadi objek wisata yang tidak pernah sepi pengunjung. Selain karena letaknya strategis, kawasan ini juga menghadirkan nuansa wisata khas Eropa. Semua itu diterapkan dalam bentuk spot swafoto Instagramable.',
    5.     textAlign: TextAlign.center,
    6.     style: TextStyle(fontSize: 16.0),
    7.   ),
    8. ),
  15. Yey, Anda berhasil menyusun widget dengan baik. Tampilan aplikasi akan seperti gambar berikut.
    dos:dd36492b0cf574e59c6db1380b4e097120220728111610.pngKeseluruhan kode Anda akan seperti berikut:
    1. import 'package:flutter/material.dart';
    2.  
    3. void main() => runApp(const MyApp());
    4.  
    5. class MyApp extends StatelessWidget {
    6. const MyApp({Key? key}) : super(key: key);
    7.  
    8. @override
    9. Widget build(BuildContext context) {
    10. return MaterialApp(
    11. title: 'Wisata Bandung',
    12. theme: ThemeData(),
    13. home: const DetailScreen(),
    14. );
    15. }
    16. }
    17.  
    18. class DetailScreen extends StatelessWidget {
    19. const DetailScreen({Key? key}) : super(key: key);
    20.  
    21. @override
    22. Widget build(BuildContext context) {
    23. return Scaffold(
    24. body: SafeArea(
    25. child: Column(
    26. crossAxisAlignment: CrossAxisAlignment.stretch,
    27. children: <Widget>[
    28. Container(
    29. margin: const EdgeInsets.only(top: 16.0),
    30. child: const Text(
    31. 'Farm House Lembang',
    32. textAlign: TextAlign.center,
    33. style: TextStyle(
    34. fontSize: 30.0,
    35. fontWeight: FontWeight.bold,
    36. ),
    37. ),
    38. ),
    39. Container(
    40. margin: const EdgeInsets.symmetric(vertical: 16.0),
    41. child: Row(
    42. mainAxisAlignment: MainAxisAlignment.spaceEvenly,
    43. children: <Widget>[
    44. Column(
    45. children: const <Widget>[
    46. Icon(Icons.calendar_today),
    47. SizedBox(height: 8.0),
    48. Text('Open Everyday'),
    49. ],
    50. ),
    51. Column(
    52. children: const <Widget>[
    53. Icon(Icons.access_time),
    54. SizedBox(height: 8.0),
    55. Text('09:00 - 20:00')
    56. ],
    57. ),
    58. Column(
    59. children: const <Widget>[
    60. Icon(Icons.monetization_on),
    61. SizedBox(height: 8.0),
    62. Text('Rp 25.000'),
    63. ],
    64. )
    65. ],
    66. ),
    67. ),
    68. Container(
    69. padding: const EdgeInsets.all(16.0),
    70. child: const Text(
    71. 'Berada di jalur utama Bandung-Lembang, Farm House menjadi objek wisata yang tidak pernah sepi pengunjung. Selain karena letaknya strategis, kawasan ini juga menghadirkan nuansa wisata khas Eropa. Semua itu diterapkan dalam bentuk spot swafoto Instagramable.',
    72. textAlign: TextAlign.center,
    73. style: TextStyle(fontSize: 16.0),
    74. ),
    75. )
    76. ],
    77. ),
    78. ),
    79. );
    80. }
    81. }

Anda juga dapat mengunduh keseluruhan kodenya pada tautan berikut: 

Popular posts from this blog

Build APK

Generic

Build IPA