PRATIKUM APLIKASI MOBILE 3

Pada praktikum ini, mahasiswa diharapkan mampu membuat form dasar (basic form) yang dapat menerima input dari pengguna melalui keyboard, kemudian mengelola input tersebut. Kegiatan praktikum meliputi:

  • Membuat berbagai macam input widgets
  • Mengontrol input yang diberikan oleh pengguna
  • Memahami dan menerapkan konsep basic form

Basic Form

Basic Form adalah sekumpulan widget yang berfungsi untuk menerima masukan dari pengguna, misalnya berupa teks, pilihan, atau aksi tertentu. Beberapa widget yang sering digunakan dalam form antara lain:

  • TextField
  • TextFormField
  • CheckBox
  • Switch
  • Dropdown
  • Radio Button
  • Dialog
  • DatePicker
  • BottomSheet
  • Snackbar

Form digunakan untuk validasi data dan pengelolaan input dari pengguna. Prosesnya adalah: pengguna mengisi data → sistem memeriksa apakah format sesuai aturan → jika valid, data akan diproses lebih lanjut.

TextField

TextField adalah widget dasar untuk menerima input berupa teks. Biasanya digunakan dalam form login, kolom pencarian, atau form sederhana lainnya.

🔹 Fitur TextField:

  • Menerima input dari keyboard.
  • Memiliki banyak properti seperti style, decoration, dan jenis input.
  • Mendukung pengelolaan teks dengan TextEditingController.

TextFormField

TextFormField adalah versi lebih lengkap dari TextField karena sudah terhubung dengan sistem validasi dan form state management.

Fitur TextFormField:

  • Menerima input teks dari keyboard.
  • Mendukung properti validator untuk mengecek kesesuaian input dengan aturan.
  • Menampilkan pesan error otomatis jika validasi gagal.
  • Terintegrasi dengan FormState sehingga validasi bisa dilakukan secara kolektif dengan method validate().

GlobalKey<FormState>

GlobalKey adalah kunci unik yang digunakan untuk mengakses state dari sebuah widget secara global. Dengan GlobalKey, kita bisa mengontrol form dari luar widget, misalnya memanggil validate() atau save() ketika tombol ditekan.

FormState

FormState adalah kelas yang mengelola status sebuah form, termasuk status validasi input.
Dengan menghubungkan Form ke GlobalKey, kita bisa:

  • Memanggil method validate() → untuk mengecek input.
  • Memanggil method save() → untuk menyimpan nilai input.

validate()

Method validate() digunakan untuk menjalankan proses validasi pada setiap TextFormField di dalam Form. Mekanismenya:

  1. Mengecek setiap input pada TextFormField.
  2. Menjalankan fungsi validator yang didefinisikan.
  3. Jika validator mengembalikan pesan error (String), maka validasi gagal → hasil false dan pesan error ditampilkan.
  4. Jika semua validator mengembalikan null, maka validasi berhasil → hasil true.

Sekarang saatnya menerapkan teori yang telah dijelaskan sebelumnya melalui langkah-langkah berikut:

  1.  Basic Form TextField

Buat tampilan form sederhana menggunakan Widget TextField sebagai input, serta ElevatedButton untuk menambahkan event listener. Susun tampilan tersebut dengan menggunakan potongan kode program berikut:

import ‘package:flutter/material.dart’;

void main() {

  runApp(const MyApp());

}

class MyApp extends StatelessWidget {

  const MyApp({super.key});

  @override

  Widget build(BuildContext context) {

    return MaterialApp(

      title: ‘hai’,

      debugShowCheckedModeBanner: false,

      home: const BasicForm(),

    );

  }

}

class BasicForm extends StatefulWidget {

  const BasicForm({super.key});

  @override

  State<BasicForm> createState() => _BasicFormState();

}

class _BasicFormState extends State<BasicForm> {

  final TextEditingController _nameController = TextEditingController();

  @override

  Widget build(BuildContext context) {

    return Scaffold(

      backgroundColor: const Color(0xFFF8F1FF), // warna background lembut

      appBar: AppBar(

        title: const Text(‘hai’),

        backgroundColor: Colors.purple,

      ),

      body: Padding(

        padding: const EdgeInsets.all(16.0),

        child: Column(

          crossAxisAlignment: CrossAxisAlignment.start,

          children: [

            const Text(

              ‘Basic Form’,

              style: TextStyle(

                fontSize: 28,

                fontWeight: FontWeight.bold,

              ),

            ),

            const SizedBox(height: 20),

            const Text(

              ‘Masukkan nama anda :’,

              style: TextStyle(fontSize: 18),

            ),

            const SizedBox(height: 10),

            TextField(

              controller: _nameController,

              decoration: InputDecoration(

                labelText: ‘Nama Lengkap’,

                prefixIcon: const Icon(Icons.person),

                labelStyle: const TextStyle(color: Colors.purple),

                focusedBorder: OutlineInputBorder(

                  borderSide: const BorderSide(color: Colors.purple, width: 2),

                  borderRadius: BorderRadius.circular(8),

                ),

                enabledBorder: OutlineInputBorder(

                  borderSide: const BorderSide(color: Colors.purple),

                  borderRadius: BorderRadius.circular(8),

                ),

              ),

            ),

            const SizedBox(height: 20),

            ElevatedButton(

              onPressed: () {

                final name = _nameController.text;

                if (name.isNotEmpty) {

                  ScaffoldMessenger.of(context).showSnackBar(

                    SnackBar(

                      content: Text(‘Nama anda: $name’),

                      backgroundColor: Colors.purple,

                    ),

                  );

                } else {

                  ScaffoldMessenger.of(context).showSnackBar(

                    const SnackBar(

                      content: Text(‘Nama belum diisi!’),

                      backgroundColor: Colors.redAccent,

                    ),

                  );

                }

              },

              style: ElevatedButton.styleFrom(

                backgroundColor: Colors.amber,

                padding:

                    const EdgeInsets.symmetric(horizontal: 20, vertical: 12),

                shape: RoundedRectangleBorder(

                  borderRadius: BorderRadius.circular(30),

                ),

              ),

              child: const Text(

                ‘Tampilkan nama’,

                style: TextStyle(

                  fontSize: 16,

                  color: Colors.black,

                  fontWeight: FontWeight.bold,

                ),

              ),

            ),

          ],

        ),

      ),

    );

  }

}

kemudian run,dan hasilnya akan seperti ini

Kode Flutter di atas berfungsi untuk membuat sebuah tampilan form sederhana yang meminta pengguna memasukkan nama, kemudian menampilkannya kembali saat tombol ditekan. Struktur programnya terdiri dari tiga bagian utama, yaitu fungsi main(), kelas MyApp, dan kelas BasicForm.

Fungsi main() menjadi titik awal program dengan memanggil runApp(const MyApp()), yang berarti aplikasi akan menjalankan widget utama bernama MyApp. Di dalam kelas MyApp, digunakan widget MaterialApp untuk menentukan kerangka dasar aplikasi Flutter berbasis Material Design. Atribut home menunjuk ke halaman utama yang akan ditampilkan pertama kali, yaitu BasicForm, sedangkan debugShowCheckedModeBanner: false digunakan untuk menghilangkan label debug di pojok kanan atas.

Kelas BasicForm dibuat sebagai StatefulWidget karena data di dalamnya dapat berubah, misalnya ketika pengguna mengetikkan nama atau menekan tombol. Di dalam state-nya (_BasicFormState), terdapat sebuah TextEditingController yang berfungsi untuk mengambil teks yang diketik oleh pengguna di TextField.

Widget Scaffold digunakan sebagai kerangka utama halaman, mencakup AppBar di bagian atas, body yang berisi form, serta pengaturan warna latar belakang halaman. Di dalam body, terdapat struktur Column untuk menata elemen-elemen secara vertikal, seperti teks judul “Basic Form”, label “Masukkan nama anda”, kolom input (TextField), dan tombol (ElevatedButton).

Pada bagian TextField, atribut controller dihubungkan dengan _nameController agar teks yang diketik bisa diambil. Dekorasi input ditentukan melalui InputDecoration dengan label “Nama Lengkap”, ikon pengguna (Icons.person), serta warna border ungu yang berubah ketika aktif.

Tombol “Tampilkan nama” menggunakan widget ElevatedButton dengan gaya kuning (Colors.amber) dan sudut melengkung agar tampil menarik. Saat tombol ditekan, fungsi onPressed akan dijalankan untuk mengambil teks dari TextField. Jika kolom nama tidak kosong, maka akan muncul SnackBar di bagian bawah layar menampilkan teks “Nama anda: [nama yang diketik]”. Jika kosong, maka SnackBar merah muncul dengan pesan “Nama belum diisi!”.

Secara keseluruhan, kode ini menampilkan contoh sederhana bagaimana Flutter menangani input teks, kontrol tampilan, serta interaksi pengguna. Struktur yang digunakan mencerminkan konsep dasar Flutter dalam membangun antarmuka reaktif yang responsif terhadap perubahan data dan interaksi.

Selanjutnya, kita akan membuat Basic Form menggunakan TextFormField.
Buatlah form input yang terdiri dari dua Widget TextFormField dan satu ElevatedButton.
Berikut adalah potongan kode program untuk menampilkan form tersebut:

import ‘package:flutter/material.dart’;

void main() {

  runApp(const MyApp());

}

class MyApp extends StatelessWidget {

  const MyApp({super.key});

  @override

  Widget build(BuildContext context) {

    return MaterialApp(

      title: ‘hai’,

      debugShowCheckedModeBanner: false,

      theme: ThemeData(

        primarySwatch: Colors.purple,

      ),

      home: const BasicFormTextFormField(),

    );

  }

}

class BasicFormTextFormField extends StatefulWidget {

  const BasicFormTextFormField({super.key});

  @override

  State<BasicFormTextFormField> createState() => _BasicFormTextFormFieldState();

}

class _BasicFormTextFormFieldState extends State<BasicFormTextFormField> {

  final _formKey = GlobalKey<FormState>();

  final TextEditingController _nameController = TextEditingController();

  final TextEditingController _emailController = TextEditingController();

  @override

  void dispose() {

    _nameController.dispose();

    _emailController.dispose();

    super.dispose();

  }

  @override

  Widget build(BuildContext context) {

    return Scaffold(

      backgroundColor: const Color(0xFFF8F1FF),

      appBar: AppBar(

        title: const Text(‘hai’),

        backgroundColor: Colors.purple,

      ),

      body: Padding(

        padding: const EdgeInsets.all(20.0),

        child: Form(

          key: _formKey,

          child: Column(

            crossAxisAlignment: CrossAxisAlignment.start,

            children: [

              const Text(

                ‘Basic Form TextFormField’,

                style: TextStyle(fontSize: 24, fontWeight: FontWeight.bold),

              ),

              const SizedBox(height: 30),

              // Field Nama

              const Text(‘Nama :’, style: TextStyle(fontSize: 16)),

              TextFormField(

                controller: _nameController,

                keyboardType: TextInputType.name,

                decoration: const InputDecoration(

                  hintText: ‘Masukkan nama lengkap’,

                  focusedBorder: UnderlineInputBorder(

                    borderSide: BorderSide(color: Colors.purple),

                  ),

                  enabledBorder: UnderlineInputBorder(

                    borderSide: BorderSide(color: Colors.grey),

                  ),

                ),

                validator: (value) {

                  if (value == null || value.isEmpty) {

                    return ‘Nama tidak boleh kosong’;

                  }

                  return null;

                },

              ),

              const SizedBox(height: 25),

              // Field Email

              const Text(‘Email :’, style: TextStyle(fontSize: 16)),

              TextFormField(

                controller: _emailController,

                keyboardType: TextInputType.emailAddress,

                decoration: const InputDecoration(

                  hintText: ‘Masukkan email anda’,

                  focusedBorder: UnderlineInputBorder(

                    borderSide: BorderSide(color: Colors.purple),

                  ),

                  enabledBorder: UnderlineInputBorder(

                    borderSide: BorderSide(color: Colors.grey),

                  ),

                ),

                validator: (value) {

                  if (value == null || value.isEmpty) {

                    return ‘Email tidak boleh kosong’;

                  } else if (!value.contains(‘@’)) {

                    return ‘Email tidak valid’;

                  }

                  return null;

                },

              ),

              const SizedBox(height: 40),

              // Tombol Submit

              Center(

                child: ElevatedButton(

                  onPressed: () {

                    if (_formKey.currentState!.validate()) {

                      String name = _nameController.text.trim();

                      String email = _emailController.text.trim();

                      ScaffoldMessenger.of(context).showSnackBar(

                        SnackBar(

                          content: Text(

                              ‘Nama: $name\nEmail: $email’),

                          backgroundColor: Colors.purple,

                        ),

                      );

                    }

                  },

                  style: ElevatedButton.styleFrom(

                    backgroundColor: Colors.purple[100],

                    padding: const EdgeInsets.symmetric(

                        horizontal: 50, vertical: 15),

                    shape: RoundedRectangleBorder(

                      borderRadius: BorderRadius.circular(10),

                    ),

                  ),

                  child: const Text(

                    ‘Submit’,

                    style: TextStyle(

                      color: Colors.purple,

                      fontSize: 16,

                      fontWeight: FontWeight.bold,

                    ),

                  ),

                ),

              ),

            ],

          ),

        ),

      ),

    );

  }

}

setelah di run hasilnya akan seperti ini

Kode di atas merupakan implementasi form input Flutter menggunakan TextFormField dengan validasi, dua kolom input (nama dan email), serta tombol Submit yang menampilkan hasil input menggunakan SnackBar.
Berikut penjelasan rinci bagian per bagian tanpa poin atau format daftar agar lebih mudah dibaca seperti penjelasan naratif.

Program diawali dengan fungsi main() yang menjalankan widget utama menggunakan runApp(const MyApp()). Kelas MyApp merupakan widget stateless yang menjadi akar dari aplikasi. Di dalamnya, MaterialApp digunakan sebagai struktur utama aplikasi Flutter berbasis Material Design. Properti title berisi teks judul, sementara debugShowCheckedModeBanner diatur false agar tulisan “debug” tidak muncul di pojok kanan atas saat aplikasi dijalankan. Tema utama diatur menggunakan ThemeData dengan warna ungu (Colors.purple) sebagai warna dominan. Halaman utama aplikasi diarahkan ke widget BasicFormTextFormField.

Widget BasicFormTextFormField adalah widget stateful, karena isinya akan berubah seiring interaksi pengguna, seperti saat mengetik atau menekan tombol. Di dalamnya terdapat dua TextEditingController, yaitu _nameController untuk menangani input nama dan _emailController untuk input email. Keduanya digunakan untuk membaca dan mengatur nilai teks pada TextFormField. Kemudian terdapat juga _formKey, yaitu GlobalKey<FormState> yang digunakan untuk mengontrol dan memvalidasi form.

Pada metode dispose(), kedua controller tersebut dihapus (disposed) agar tidak terjadi kebocoran memori ketika widget dihapus dari tampilan. Ini merupakan praktik standar dalam penggunaan controller di Flutter.

Widget utama pada tampilan disusun menggunakan Scaffold, yang menyediakan struktur dasar halaman berupa AppBar, body, dan properti tambahan lain seperti backgroundColor. Warna latar belakang diset ke warna ungu muda (Color(0xFFF8F1FF)), sedangkan AppBar berwarna ungu tua dengan teks “hai” di bagian atas.

Bagian utama form diletakkan di dalam Padding agar tidak menempel ke tepi layar. Komponen input dibungkus dengan widget Form yang memiliki kunci _formKey, memungkinkan validasi dan manajemen status input dilakukan dengan mudah. Di dalam form, Column digunakan agar semua elemen ditampilkan secara vertikal dari atas ke bawah.

Teks pertama bertuliskan “Basic Form TextFormField” dengan ukuran font lebih besar dan tebal sebagai judul. Setelah itu terdapat TextFormField pertama untuk input nama. Field ini dikaitkan dengan _nameController dan memiliki dekorasi seperti hintText untuk membantu pengguna, serta garis bawah (UnderlineInputBorder) yang berubah warna menjadi ungu saat fokus. Pada bagian validator, terdapat fungsi yang memeriksa apakah input kosong. Jika kosong, maka akan muncul pesan kesalahan “Nama tidak boleh kosong”.

Field kedua digunakan untuk input email dan dikaitkan dengan _emailController. Tampilannya mirip dengan field nama, namun memiliki keyboardType bertipe TextInputType.emailAddress agar keyboard menyesuaikan untuk input email. Pada bagian validasi, selain memastikan tidak kosong, juga dicek apakah input mengandung karakter ‘@’. Jika tidak, akan muncul pesan “Email tidak valid”.

Setelah kedua field, terdapat jarak tambahan (SizedBox(height: 40)) sebelum tombol submit. Tombol ini diletakkan di tengah menggunakan Center. Komponen ElevatedButton digunakan untuk membuat tombol dengan gaya tertentu. Warna tombol diatur menjadi ungu muda (Colors.purple[100]) dan teksnya berwarna ungu agar kontras. Tombol juga memiliki padding lebih besar agar terlihat proporsional dan berbentuk agak membulat menggunakan RoundedRectangleBorder dengan borderRadius sebesar 10.

Ketika tombol ditekan, fungsi onPressed akan dijalankan. Pertama, dilakukan pengecekan validasi dengan if (_formKey.currentState!.validate()). Jika semua field valid, maka isi dari TextEditingController dibaca dan disimpan ke variabel name dan email. Nilai-nilai tersebut kemudian ditampilkan ke pengguna menggunakan ScaffoldMessenger.of(context).showSnackBar(), yaitu komponen Flutter yang menampilkan notifikasi kecil di bagian bawah layar. Pesan yang ditampilkan berupa “Nama: [nama]” dan “Email: [email]”, dengan latar belakang berwarna ungu agar konsisten dengan tema aplikasi.

Secara keseluruhan, kode ini menampilkan form sederhana namun lengkap yang mencakup input nama dan email, validasi form, pengaturan tampilan yang rapi, serta penampilan hasil input melalui notifikasi. Struktur kodenya mengikuti praktik terbaik Flutter dalam memisahkan logika dan tampilan, menggunakan controller secara aman, serta menerapkan validasi form yang interaktif.

Tugas

  • Buat 2 buah file dart yaitu main.dart dan user_registration_form.dart
  • Gunakan MaterialApp sebagai root pada main.dart
  • Set propreti home ke widget UserRegistrationForm
  • Gunakan statefulwidget pada UserRegistrationForm
  • Gunakan widget TextFormField untuk inputan, gunakan method validador untuk validasi
  • Validasi : inputan email harus menggunakan format @, inputan password dan confirm password harus sama atau valid
  • Gunakan method onPressed dan Ketika di pencet akan memanggil _submitForm

1. main.dart

import ‘package:flutter/material.dart’;

import ‘user_registration_form.dart’;

void main() {

  runApp(const MyApp());

}

class MyApp extends StatelessWidget {

  const MyApp({super.key});

  @override

  Widget build(BuildContext context) {

    return MaterialApp(

      title: ‘User Registration’,

      debugShowCheckedModeBanner: false,

      theme: ThemeData(primarySwatch: Colors.blue),

      home: const UserRegistrationForm(),

    );

  }

}

kode main.dart diatas merupakan kode utama (entry point) dari aplikasi Flutter yang berfungsi untuk menjalankan dan menampilkan halaman form registrasi pengguna yang berada di file lain bernama user_registration_form.dart

2.user_registration_form.dart

import ‘package:flutter/material.dart’;

void main() {

  runApp(const MyApp());

}

class MyApp extends StatelessWidget {

  const MyApp({super.key});

  @override

  Widget build(BuildContext context) {

    return MaterialApp(

      debugShowCheckedModeBanner: false,

      title: ‘Form Registrasi Pengguna’,

      theme: ThemeData(

        primarySwatch: Colors.purple,

        scaffoldBackgroundColor: const Color(0xFFF8F1FF),

        inputDecorationTheme: const InputDecorationTheme(

          border: UnderlineInputBorder(),

        ),

      ),

      home: const UserRegistrationForm(),

    );

  }

}

class UserRegistrationForm extends StatefulWidget {

  const UserRegistrationForm({super.key});

  @override

  State<UserRegistrationForm> createState() => _UserRegistrationFormState();

}

class _UserRegistrationFormState extends State<UserRegistrationForm> {

  final _formKey = GlobalKey<FormState>();

  final _nameController = TextEditingController();

  final _emailController = TextEditingController();

  final _passwordController = TextEditingController();

  final _confirmPasswordController = TextEditingController();

  void _submitForm() {

    if (_formKey.currentState!.validate()) {

      ScaffoldMessenger.of(context).showSnackBar(

        SnackBar(

          backgroundColor: Colors.purple[300],

          content: Text(

            “Registrasi berhasil!\nEmail: ${_emailController.text}”,

            style: const TextStyle(color: Colors.white),

          ),

        ),

      );

    }

  }

  @override

  void dispose() {

    _emailController.dispose();

    _passwordController.dispose();

    _confirmPasswordController.dispose();

    _nameController.dispose();

    super.dispose();

  }

  @override

  Widget build(BuildContext context) {

    return Scaffold(

      appBar: AppBar(

        title: const Text(“User Registration”),

        backgroundColor: Colors.purple,

      ),

      body: SingleChildScrollView(

        padding: const EdgeInsets.all(20.0),

        child: Form(

          key: _formKey,

          child: Column(

            crossAxisAlignment: CrossAxisAlignment.start,

            children: [

              const Text(

                “Form Registrasi Pengguna”,

                style: TextStyle(

                  fontSize: 22,

                  fontWeight: FontWeight.bold,

                  color: Colors.purple,

                ),

              ),

              const SizedBox(height: 24),

              // Nama

              TextFormField(

                controller: _nameController,

                decoration: const InputDecoration(

                  labelText: “Nama”,

                  prefixIcon: Icon(Icons.person),

                ),

                validator: (value) {

                  if (value == null || value.isEmpty) {

                    return “Nama tidak boleh kosong”;

                  } else if (RegExp(r'[0-9]’).hasMatch(value)) {

                    return “Format nama tidak valid”;

                  }

                  return null;

                },

              ),

              const SizedBox(height: 16),

              // Email

              TextFormField(

                controller: _emailController,

                decoration: const InputDecoration(

                  labelText: “Email”,

                  prefixIcon: Icon(Icons.email),

                ),

                validator: (value) {

                  if (value == null || value.isEmpty) {

                    return “Email tidak boleh kosong”;

                  } else if (!RegExp(r’^[\w\.-]+@[\w\.-]+\.\w+$’).hasMatch(value)) {

                    return “Format email tidak valid”;

                  }

                  return null;

                },

              ),

              const SizedBox(height: 16),

              // Password

              TextFormField(

                controller: _passwordController,

                decoration: const InputDecoration(

                  labelText: “Password”,

                  prefixIcon: Icon(Icons.lock),

                ),

                obscureText: true,

                validator: (value) {

                  if (value == null || value.isEmpty) {

                    return “Password tidak boleh kosong”;

                  } else if (value.length < 6) {

                    return “Password minimal 6 karakter”;

                  }

                  return null;

                },

              ),

              const SizedBox(height: 16),

              // Konfirmasi Password

              TextFormField(

                controller: _confirmPasswordController,

                decoration: const InputDecoration(

                  labelText: “Konfirmasi Password”,

                  prefixIcon: Icon(Icons.lock_outline),

                ),

                obscureText: true,

                validator: (value) {

                  if (value == null || value.isEmpty) {

                    return “Konfirmasi password tidak boleh kosong”;

                  } else if (value != _passwordController.text) {

                    return “Password tidak sama”;

                  }

                  return null;

                },

              ),

              const SizedBox(height: 30),

              // Tombol Submit

              Center(

                child: ElevatedButton(

                  onPressed: _submitForm,

                  style: ElevatedButton.styleFrom(

                    backgroundColor: Colors.purple[100],

                    padding: const EdgeInsets.symmetric(

                      horizontal: 40,

                      vertical: 14,

                    ),

                    shape: RoundedRectangleBorder(

                      borderRadius: BorderRadius.circular(10),

                    ),

                  ),

                  child: const Text(

                    “Register”,

                    style: TextStyle(

                      color: Colors.purple,

                      fontWeight: FontWeight.bold,

                      fontSize: 16,

                    ),

                  ),

                ),

              ),

            ],

          ),

        ),

      ),

    );

  }

}

lalu run kode diatas,dan akan menalpilkan halaman seperti ini

Kode di atas merupakan implementasi aplikasi Flutter sederhana yang menampilkan form registrasi pengguna dengan beberapa input seperti nama, email, password, dan konfirmasi password. Aplikasi ini juga menggunakan validasi input serta menampilkan notifikasi berupa SnackBar ketika data berhasil dikirim.

Program dimulai dari fungsi main() yang berisi runApp(const MyApp()). Fungsi ini adalah titik awal dari aplikasi Flutter. runApp() digunakan untuk menjalankan widget utama yang dalam hal ini adalah MyApp. Widget MyApp merupakan turunan dari StatelessWidget, artinya tampilan di dalamnya tidak akan berubah selama aplikasi berjalan.

Di dalam metode build() milik MyApp, terdapat MaterialApp yang berfungsi sebagai wadah utama seluruh aplikasi dengan tema Material Design. Properti debugShowCheckedModeBanner diatur menjadi false agar tulisan “DEBUG” tidak muncul di pojok layar. Aplikasi diberi judul “Form Registrasi Pengguna” dan memiliki tema berwarna ungu (primarySwatch: Colors.purple). Latar belakang seluruh halaman menggunakan warna ungu muda (scaffoldBackgroundColor: Color(0xFFF8F1FF)) agar tampilan terlihat lembut. Selain itu, inputDecorationTheme diset agar semua TextFormField memiliki gaya garis bawah (underline). Halaman awal aplikasi ditentukan dengan home: const UserRegistrationForm(), yang berarti aplikasi akan langsung menampilkan halaman registrasi pengguna ketika dijalankan.

Widget UserRegistrationForm adalah stateful widget karena tampilan dan datanya dapat berubah saat pengguna berinteraksi. Kelas ini memiliki state class bernama _UserRegistrationFormState yang menyimpan data serta logika validasi form. Di dalamnya terdapat beberapa TextEditingController untuk menangani input pengguna, yaitu _nameController, _emailController, _passwordController, dan _confirmPasswordController. Semua controller ini berfungsi untuk membaca serta mengatur teks yang diketik pengguna di setiap kolom input. Selain itu, terdapat _formKey bertipe GlobalKey<FormState> yang digunakan untuk memvalidasi seluruh form.

Metode _submitForm() dijalankan ketika tombol Register ditekan. Fungsi ini memeriksa apakah semua input valid menggunakan if (_formKey.currentState!.validate()). Jika semua validasi berhasil, maka aplikasi menampilkan SnackBar dengan pesan “Registrasi berhasil!” dan menampilkan email pengguna. SnackBar ini juga diberi warna ungu agar selaras dengan tema aplikasi.

Metode dispose() dipanggil ketika widget dihapus dari tampilan. Di sini, semua controller dihapus dengan dispose() agar tidak menyebabkan kebocoran memori.

Bagian tampilan utama dibuat di dalam metode build(). Widget Scaffold digunakan sebagai struktur utama halaman, yang memiliki AppBar berwarna ungu dengan judul “User Registration”. Isi halaman berada di dalam body yang dibungkus SingleChildScrollView, agar tampilan bisa digulir jika layar terlalu kecil.

Di dalam Form, semua elemen input diletakkan secara vertikal menggunakan Column. Bagian atas terdapat teks judul “Form Registrasi Pengguna” dengan ukuran huruf besar dan warna ungu agar menarik perhatian.

Kemudian terdapat empat buah TextFormField untuk input data pengguna. Field pertama adalah untuk nama, dengan ikon orang (Icons.person) dan validasi agar tidak kosong serta tidak mengandung angka. Field kedua digunakan untuk email, dilengkapi ikon amplop (Icons.email) dan validasi pola email menggunakan regular expression agar format email benar. Field ketiga adalah password dengan ikon gembok (Icons.lock) dan properti obscureText: true agar teks tersembunyi. Password harus minimal enam karakter. Field terakhir adalah konfirmasi password yang memastikan nilai sama dengan password utama. Jika berbeda, maka muncul pesan “Password tidak sama”.

Setelah semua input, terdapat jarak vertikal (SizedBox) dan tombol “Register” di bagian bawah yang diletakkan di tengah menggunakan Center. Tombol ini dibuat dengan ElevatedButton dan gaya khusus menggunakan ElevatedButton.styleFrom(). Warnanya diatur menjadi ungu muda dengan teks berwarna ungu agar tetap konsisten dengan tema aplikasi. Saat tombol ditekan, fungsi _submitForm() dijalankan untuk melakukan validasi dan menampilkan hasilnya.

Secara keseluruhan, kode ini merupakan aplikasi form registrasi dengan tampilan sederhana namun rapi dan interaktif. Ia memanfaatkan struktur standar Flutter seperti MaterialApp, Scaffold, Form, dan TextFormField, dilengkapi dengan validasi data dan SnackBar sebagai umpan balik ketika form berhasil dikirim.

KESIMPULAN

Dari hasil praktikum ini dapat disimpulkan bahwa penggunaan Flutter memungkinkan pengembangan aplikasi dengan tampilan interaktif dan responsif secara efisien. Melalui implementasi form registrasi pengguna, mahasiswa dapat memahami cara kerja widget dasar Flutter seperti MaterialApp, Scaffold, AppBar, Form, dan TextFormField, serta bagaimana cara mengelola input dan validasi data menggunakan TextEditingController dan GlobalKey<FormState>.

Selain itu, praktikum ini juga memperkenalkan konsep Stateful Widget, di mana tampilan aplikasi dapat berubah sesuai interaksi pengguna, misalnya ketika tombol ditekan atau input diisi. Validasi form membantu memastikan data yang dimasukkan sudah sesuai format, sedangkan penggunaan SnackBar memberikan umpan balik langsung kepada pengguna setelah proses registrasi berhasil.

Secara keseluruhan, praktikum ini memberikan pemahaman mendasar mengenai pembuatan form, validasi input, serta manajemen state pada Flutter, yang menjadi dasar penting dalam membangun aplikasi mobile yang fungsional dan user-friendly.

Leave a Comment

Your email address will not be published. Required fields are marked *