Input Widgets dan Basic Form

Konsep Dasar Input Widgets dan Form

Basic Form

Widget yang berfungsi sebagai inputan nilai seperti TextField, TextFormField, CheckBox, Switch, Dropdown, Radio, Dialog, DatePicker, BottomSheet, Snackbar. Digunakan untuk validasi dan mengelola inputan dari berbagai field.

TextField

Widget untuk memasukkan teks oleh pengguna, biasanya digunakan untuk form inputan seperti login, pencarian, dll. Menerima input dari keyboard dengan property lengkap untuk style, decoration, dan jenis inputan.

TextFormField

Versi lengkap dari TextField yang terintegrasi dengan logika validasi dan manajemen state dari sebuah form. Memiliki properti validator untuk memeriksa input sesuai aturan yang ditentukan.

GlobalKey & FormState

GlobalKey digunakan untuk mengidentifikasi dan mengakses state secara global. FormState mengelola status dari Form, seperti status validasi setiap inputan. Memungkinkan pemanggilan metode validate() atau save() dari luar widget.

Langkah Implementasi sesuai Modul

A
Basic Form dengan TextField
Langkah-langkah:
  1. Membuat file baru dengan nama form-textfield.dart
  2. Membuat tampilan basic form dengan Widget TextField dan ElevatedButton
  3. Menambahkan TextEditingController untuk mengelola inputan
  4. Menambahkan event listener pada TextField
  5. Menampilkan hasil input menggunakan SnackBar
Kode Implementasi:
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(
      home: Scaffold(
        appBar: AppBar(title: const Text('Basic Form')),
        body: const MyForm(),
      ),
    );
  }
}

class MyForm extends StatefulWidget {
  const MyForm({super.key});

  @override
  State createState() => _MyFormState();
}

class _MyFormState extends State {
  TextEditingController _textEditingController = TextEditingController();
  String inputText = '';
  @override
  void dispose() {
    _textEditingController.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Padding(
      padding: const EdgeInsets.all(20.0),
      child: Column(
        crossAxisAlignment: CrossAxisAlignment.start,
        children: [
          const Text('Masukkan nama anda:'),
          const SizedBox(height: 10),
          TextField(
            decoration: InputDecoration(
              labelText: 'Nama lengkap',
              hintText: 'John Doe',
              border: OutlineInputBorder(),
              prefixIcon: Icon(Icons.person),
            ),
            controller: _textEditingController,
            keyboardType: TextInputType.text,
            onChanged: (text) {
              print('Sedang mengetik teks : ,$text');
            },
          ),
          const SizedBox(height: 20),
          ElevatedButton(
            onPressed: () {
              inputText = _textEditingController.text;
              ScaffoldMessenger.of(context).showSnackBar(
                SnackBar(content: Text('Nama anda adalah, $inputText')),
              );
              setState(() {
                inputText = _textEditingController.text;
              });
            },
            style: ElevatedButton.styleFrom(
              backgroundColor: Colors.amber,
              foregroundColor: Colors.black,
            ),
            child: const Text('Tampilkan nama'),
          ),
          SizedBox(height: 20),
          Text('Nama Anda : $inputText', style: const TextStyle(fontSize: 20)),
        ],
      ),
    );
  }
}
Dokumentasi:
PraktikumMobileApp2 PraktikumMobileApp2 PraktikumMobileApp2

Gambar 1: Tampilan Basic Form dengan TextField

B
Basic Form dengan TextFormField
Langkah-langkah:
  1. Membuat file baru dengan nama form-textformfield.dart
  2. Membuat form dengan 2 TextFormField dan ElevatedButton
  3. Menggunakan GlobalKey untuk mengelola state form
  4. Menambahkan validator untuk validasi input
  5. Menampilkan pesan error jika validasi gagal
Kode Implementasi:
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(
      home: Scaffold(
        appBar: AppBar(title: const Text("Basic Form TextFormField")),
        body: const MyFormText(),
      ),
    );
  }
}

class MyFormText extends StatefulWidget {
  const MyFormText({super.key});

  @override
  State createState() => _MyFormTextState();
}

class _MyFormTextState extends State {
  final _formKey = GlobalKey();
  final _nameController = TextEditingController();
  final _emailController = TextEditingController();

  @override
  void dispose() {
    _nameController.dispose();
    _emailController.dispose();
    super.dispose();
  }

  void _submitForm() {
    if (_formKey.currentState!.validate()) {
      String name = _nameController.text;
      String email = _emailController.text;

      ScaffoldMessenger.of(context).showSnackBar(
        SnackBar(content: Text('Validasi $name, $email Berhasil')),
      );
    }
  }

  @override
  Widget build(BuildContext context) {
    return Form(
      key: _formKey,
      child: Padding(
        padding: const EdgeInsets.all(20.0),
        child: Column(
          mainAxisAlignment: MainAxisAlignment.start,
          children: [
            const SizedBox(height: 10),
            TextFormField(
              controller: _nameController,
              decoration: const InputDecoration(
                labelText: "Nama : ",
                border: OutlineInputBorder(),
              ),
              validator: (value) {
                if (value == null || value.isEmpty) {
                  return 'Masukkan nama anda';
                }
                return null;
              },
            ),
            const SizedBox(height: 10),
            TextFormField(
              controller: _emailController,
              decoration: const InputDecoration(
                labelText: "Email : ",
                border: OutlineInputBorder(),
              ),
              validator: (value) {
                if (value == null || value.isEmpty) {
                  return 'Masukkan email anda';
                }
                if (!value.contains('@')) {
                  return 'Email tidak valid';
                }
                return null;
              },
            ),
            const SizedBox(height: 10),
            SizedBox(
              width: double.infinity,
              child: ElevatedButton(
                onPressed: _submitForm,
                child: const Text('Submit'),
              ),
            ),
          ],
        ),
      ),
    );
  }
}
Dokumentasi:
PraktikumMobileApp3 PraktikumMobileApp3

Gambar 2: Tampilan Basic Form dengan TextFormField

Tugas: Aplikasi Kalkulator Kabataku

1
Implementasi Kalkulator Kabataku

Berdasarkan tugas pada modul, saya telah membuat aplikasi kalkulator yang dapat melakukan operasi kabataku (kali, bagi, tambah, kurang) menggunakan Flutter.

Fitur yang Diimplementasikan:
  • 2 buah TextField untuk menerima input angka dari pengguna
  • 4 buah ElevatedButton untuk operasi matematika (+, -, ×, ÷)
  • Validasi input untuk memastikan angka yang dimasukkan valid
  • Penanganan error untuk pembagian dengan nol
  • Widget Text untuk menampilkan hasil perhitungan
Kode Implementasi:
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(
      home: Scaffold(
        appBar: AppBar(title: const Text('Kabataku Kalkulator')),
        body: const KabatakuCalculator(),
      ),
    );
  }
}

class KabatakuCalculator extends StatefulWidget {
  const KabatakuCalculator({super.key});

  @override
  State createState() => _KabatakuCalculatorState();
}

class _KabatakuCalculatorState extends State {
  final TextEditingController _controller1 = TextEditingController();
  final TextEditingController _controller2 = TextEditingController();
  String _result = '';

  void _calculate(String operator) {
    final num1 = double.tryParse(_controller1.text);
    final num2 = double.tryParse(_controller2.text);

    if (num1 == null || num2 == null) {
      setState(() {
        _result = 'Input tidak valid!';
      });
      return;
    }

    double hasil;
    switch (operator) {
      case '+':
        hasil = num1 + num2;
        break;
      case '-':
        hasil = num1 - num2;
        break;
      case '×':
        hasil = num1 * num2;
        break;
      case '÷':
        if (num2 == 0) {
          _result = 'Tidak bisa dibagi 0!';
          setState(() {});
          return;
        }
        hasil = num1 / num2;
        break;
      default:
        hasil = 0;
    }
    setState(() {
      _result = 'Hasil: $hasil';
    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Padding(
        padding: const EdgeInsets.all(24.0),
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            TextField(
              controller: _controller1,
              keyboardType: TextInputType.number,
              decoration: const InputDecoration(
                labelText: 'Angka pertama',
                border: OutlineInputBorder(),
              ),
            ),
            const SizedBox(height: 16),
            TextField(
              controller: _controller2,
              keyboardType: TextInputType.number,
              decoration: const InputDecoration(
                labelText: 'Angka kedua',
                border: OutlineInputBorder(),
              ),
            ),
            const SizedBox(height: 24),
            Row(
              mainAxisAlignment: MainAxisAlignment.spaceEvenly,
              children: [
                ElevatedButton(
                  onPressed: () => _calculate('+'),
                  child: const Text('+'),
                ),
                ElevatedButton(
                  onPressed: () => _calculate('-'),
                  child: const Text('-'),
                ),
                ElevatedButton(
                  onPressed: () => _calculate('×'),
                  child: const Text('×'),
                ),
                ElevatedButton(
                  onPressed: () => _calculate('÷'),
                  child: const Text('÷'),
                ),
              ],
            ),
            const SizedBox(height: 24),
            Text(
              _result,
              style: const TextStyle(fontSize: 20, fontWeight: FontWeight.bold),
            ),
          ],
        ),
      ),
    );
  }
}
Penjelasan Kode:
  • TextEditingController: Digunakan untuk mengambil nilai dari TextField
  • _calculate(): Fungsi yang menangani logika perhitungan berdasarkan operator
  • setState(): Memperbarui UI ketika hasil perhitungan berubah
  • tryParse(): Mengonversi input string menjadi angka dengan penanganan error
  • Validasi pembagian dengan nol: Mencegah error ketika pengguna mencoba membagi dengan nol
Dokumentasi:
\ PraktikumMobileApp3

Gambar 3: Tampilan Aplikasi Kalkulator Kabataku

Kesimpulan

Dalam praktikum ini, kita telah mempelajari:

  1. Perbedaan antara TextField dan TextFormField dalam Flutter
  2. Cara menggunakan TextEditingController untuk mengelola input dari pengguna
  3. Implementasi validasi form menggunakan GlobalKey dan FormState
  4. Pembuatan form yang interaktif dengan feedback menggunakan SnackBar
  5. Penerapan konsep-konsep tersebut dalam aplikasi kalkulator kabataku

Pemahaman tentang input widgets dan form management sangat penting dalam pengembangan aplikasi Flutter karena hampir setiap aplikasi memerlukan interaksi dengan pengguna melalui form input. Dengan menguasai konsep-konsep ini, kita dapat membuat aplikasi yang lebih interaktif dan user-friendly.

Untuk kode lengkap praktikum dan tugas dapat diakses pada repository GitHub: https://github.com/Alone1011/2311532011-RifkiY-MobileApp.git

Komentar (0)

Tinggalkan Komentar