Membuat pencarian/search ListView di Flutter

Pada Artikel kali ini akan membahas cara membuat filter atau pencarian ListView di Flutter.
Seperti yang telah kita ketahui bahwa fasilitas search atau pencarian disuatu aplikasi sangat penting,
karena fasilitas ini akan membuat pengguna lebih mudah dalam mencari sesuatu di aplikasi kita.

Kita akan membuat function untuk memfilter data dari model, dan function ini akan dipanggil
ketika user atau pengguna aplikasi melakukan input di kolom teks (onChanged).
Algoritma pencarian dapat berbeda berdasarkan kasus per kasus, namun yang paling sederhana dan populer adalah dengan menggunakan Dart methods berikut:

Methods where() : Returns a new lazy Iterable dengan semua elemen yang memenuhi satu atau banyak kondisi

Methods contains() : Digunakan untuk menentukan apakah suatu string berisi string lain (Anda dapat mencoba metode string lain seperti startWith(), endWith(), dll.)

Methods toLowerCase() : Metode string ini akan mengubah semua karakter dalam string ini menjadi huruf kecil sehingga tidak masalah apakah kata kunci pencariannya huruf besar atau kecil.

Baiklah langsung saja kita akan mempraktekan dengan membuat project baru, Pada kasus ini kita akan membuat daftar menu kategori yang berisi data sebagai berikut :

idmodel : berfungsi sebagai index data

namamodel : berisi nama kategori

descmodel : berisi penjelasan kategori

images : berisi photo kategori

Pada awalnya, semua menu kategori ini ditampilkan dalam ListView. Jika Anda mengetikkan sesuatu pada kolom pencarian, hanya menu kategori yang namanya sesuai dengan kata kunci yang akan ditampilkan. Jika Anda mengosongkan kolom pencarian, daftar lengkap pengguna akan muncul kembali.

Ada 2 file yang akan kita buat yaitu main.dart dan categori.dart

Code main.dart

 

import 'package:flutter/material.dart';
import 'package:monsieurspoon/model/categori.dart';

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

  @override
  State<HomePage> createState() => _MysearchAppState();
}

class _MysearchAppState extends State<HomePage> {
  List<CategoriModel> _allCategori = [];

  void _getCategori() {
    _allCategori = CategoriModel.getCategories();
  }

  List<CategoriModel> _foundCategori = [];

  @override
  void initState() {
    _getCategori();
    _foundCategori = _allCategori;
    super.initState();
  }

  void _runFilter(String enteredKeyword) {
    List<CategoriModel> results = [];
    if (enteredKeyword.isEmpty) {
      // if the search field is empty or only contains white-space, we'll display all users
      results = _allCategori;
    } else {
      results = _allCategori
          .where((user) => user.namemodel
              .toLowerCase()
              .contains(enteredKeyword.toLowerCase()))
          .cast<CategoriModel>()
          .toList();
      // we use the toLowerCase() method to make it case-insensitive
    }

    // Refresh the UI
    setState(() {
      _foundCategori = results;
    });
  }

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      debugShowCheckedModeBanner: false,
      home: Scaffold(
        appBar: AppBar(
          title: const Text('Search Data'),
        ),
        body: Container(
          decoration: const BoxDecoration(
            gradient: LinearGradient(
                colors: [Color.fromARGB(255, 145, 161, 250), Color(0xffBDBDB2)],
                begin: Alignment.topLeft,
                end: Alignment.bottomRight),
          ),
          child: Column(
            children: [
              Container(
                  margin: const EdgeInsets.all(20),
                  child: TextField(
                    onChanged: (value) => _runFilter(value),
                    decoration: const InputDecoration(
                        labelText: 'Search', suffixIcon: Icon(Icons.search)),
                  )),
              Container(

                  //margin: EdgeInsets.all(20),
                  child: Expanded(
                child: _foundCategori.isNotEmpty
                    ? ListView.builder(
                        itemCount: _foundCategori.length,
                        itemBuilder: (context, index) => Card(
                          key: ValueKey(_foundCategori[index].idmodel),
                          color: Colors.amberAccent,
                          elevation: 4,
                          //margin: const EdgeInsets.symmetric(vertical: 10),
                          margin: const EdgeInsets.all(15),
                          child: ListTile(
                            leading: Text(
                              _foundCategori[index].idmodel.toString(),
                              style: const TextStyle(fontSize: 24),
                            ),
                            title: Text(_foundCategori[index].namemodel),
                            subtitle: Text(_foundCategori[index].namemodel),
                          ),
                        ),
                      )
                    : const Text(
                        'No results found',
                        style: TextStyle(fontSize: 24),
                      ),
              )),
            ],
          ),
        ),
      ),
    );
  }
}

Penjelasan kode diatas:

import ‘package:flutter/material.dart’; kode ini berfungsi untuk mengambil library material flutter

import ‘package:monsieurspoon/model/categori.dart’; kode ini berfungsi mengambil data categori yang ada di file categori.dart

class HomePage extends StatefulWidget kode ini berfungsi untuk membuat class HomePage, dimana class ini merupakan turunan/extends dari widget StatefulWidget. Beberapa contoh dari stateful widget bawaan Flutter adalah: Checkbox, Radio, Slider, TextField, dan lain-lain.

List<CategoriModel> _allCategori = []; Kode ini menginisialisasi variabel bernama _allCategori sebagai sebuah list yang berisi objek CategoriModel. List tersebut awalnya kosong ( [ ] menandakan list kosong ) dan akan dapat menyimpan objek-objek dari tipe CategoriModel.

const HomePage({super.key}); kode ini merupakan sebuah konstruktor yang menerima parameter bernama key dan meneruskannya ke konstruktor dari kelas induk (parent class) menggunakan super.key.
 
@override
  State<HomePage> createState() => _MysearchAppState(); kode ini berfungsi untuk meng-override metode createState() dari class StatefulWidget.
 
class _MysearchAppState extends State<HomePage> kode ini memiliki arti sebagai berikut:
  1. class: Ini menandakan bahwa kita sedang membuat sebuah kelas di dalam bahasa pemrograman Dart.
  2. _MysearchAppState: Nama dari kelas yang sedang dibuat. Nama ini diawali dengan garis bawah (_), yang menunjukkan bahwa kelas ini bersifat privat dalam file Dart tempat kodenya ditulis. Kelas ini merupakan turunan dari kelas State yang memiliki tipe data HomePage, artinya kelas _MysearchAppState bertanggung jawab untuk mengelola state dari widget HomePage.
  3. extends State<HomePage>: Dalam kerangka kerja Flutter, State adalah bagian yang mengelola state dari widget. Melalui extends State<HomePage>, kelas _MysearchAppState memperluas (extends) kelas State dan terkait khususnya dengan widget HomePage. Ini berarti kelas _MysearchAppState akan mengelola state yang berkaitan dengan widget HomePage, seperti perubahan data atau tampilan pada layar yang terkait dengan widget tersebut.

Dengan demikian, kelas _MysearchAppState ini merupakan bagian vital dalam menentukan bagaimana HomePage akan bereaksi terhadap perubahan-perubahan data serta bagaimana tampilannya akan diubah atau diperbarui ketika state berubah.

List<CategoriModel> _allCategori = []; kode ini memiliki arti sebagai berikut:

List<CategoriModel>: kode Ini adalah deklarasi variabel dengan tipe data List yang menyimpan objek-objek dari tipe CategoriModel. List merupakan struktur data yang dapat menyimpan sejumlah nilai yang terurut. Dalam hal ini, list ini akan berisi objek-objek yang merupakan instance dari kelas CategoriModel.

_allCategori: Kode Ini adalah nama dari variabel yang dideklarasikan. Variabel ini dapat digunakan untuk menyimpan dan mengakses list dari objek CategoriModel.

= [];  Kode ini adalah inisialisasi variabel. Pada saat deklarasi, variabel _allCategori diinisialisasi sebagai list kosong ([] menandakan list kosong). Dengan demikian, variabel tersebut siap untuk menyimpan objek-objek dari tipe CategoriModel.

void _getCategori() {
    _allCategori = CategoriModel.getCategories();
  }
Kode ini mendefinisikan sebuah fungsi bernama _getCategori() yang tidak mengembalikan nilai (void). Fungsi ini bertujuan untuk mengisi nilai dari variabel _allCategori dengan hasil dari pemanggilan fungsi statis CategoriModel.getCategories(). getCategories() ini merupakan function yang ada di file categori.dart

List<CategoriModel> _foundCategori = []; kode ini adalah deklarasi variabel _foundCategori yang merupakan list kosong yang akan menampung objek-objek dari tipe CategoriModel.

 @override
  void initState() {
    _getCategori();
    _foundCategori = _allCategori;
    super.initState();
  }

Kode ini merupakan penggantian atau penimpaan metode initState() yang ada dalam kelas State pada Flutter. Berikut penjelasannya:

@override: Anotasi ini menandakan bahwa metode initState() sedang menggantikan (override) metode yang ada dalam kelas yang diwarisi (inherited class), dalam konteks ini kelas State.

void initState() { … }: Metode initState() digunakan dalam pembangunan widget pada Flutter. Ini adalah salah satu dari metode siklus hidup (lifecycle method) yang dipanggil hanya sekali ketika widget pertama kali dibuat. Pada contoh ini, metode initState() dipanggil ketika widget ini pertama kali dimuat ke dalam pohon widget Flutter.

_getCategori();: Memanggil fungsi _getCategori() yang kemungkinan menginisialisasi atau mengisi nilai ke dalam variabel _allCategori.

_foundCategori = _allCategori;: Mengatur variabel _foundCategori agar memiliki nilai yang sama dengan variabel _allCategori. Dalam konteks ini, =_allCategori mengcopy referensi ke list yang sama, sehingga kedua variabel ini akan menunjuk ke objek yang sama di dalam memori.

super.initState();: Memanggil metode initState() dari kelas induk (parent class) State. Hal ini penting karena initState() dari kelas induk mungkin melakukan tugas-tugas inisialisasi yang diperlukan oleh State.

Secara ringkasnya, metode initState() di sini digunakan untuk menginisialisasi beberapa variabel, menjalankan fungsi yang diperlukan pada awal pembuatan widget, dan mempersiapkan widget untuk ditampilkan.

void _runFilter(String enteredKeyword) {
    List<CategoriModel> results = [];
    if (enteredKeyword.isEmpty) {
      // if the search field is empty or only contains white-space, we’ll display all users
      results = _allCategori;
    } else {
      results = _allCategori
          .where((user) => user.namemodel
              .toLowerCase()
              .contains(enteredKeyword.toLowerCase()))
          .cast<CategoriModel>()
          .toList();
      // we use the toLowerCase() method to make it case-insensitive
    }

Kode tersebut mendefinisikan fungsi _runFilter(String enteredKeyword) yang mengelola proses pencarian pada daftar kategori. Berikut Penjelasannya:

void _runFilter(String enteredKeyword) { … }: Ini adalah fungsi yang tidak mengembalikan nilai (void) dan menerima satu parameter, yaitu enteredKeyword yang merupakan string yang akan digunakan sebagai kriteria pencarian.

List<CategoriModel> results = []; kode ini Mendeklarasikan variabel results sebagai list kosong yang akan menampung hasil pencarian yang sesuai dengan kriteria.

if (enteredKeyword.isEmpty) { … } else { … }: kode ini Melakukan pengecekan apakah enteredKeyword kosong atau tidak. Jika kosong, results akan diisi dengan seluruh daftar kategori (_allCategori). Jika tidak kosong, pencarian akan dilakukan dengan kriteria tertentu.

Proses pencarian:
results = _allCategori…: Jika enteredKeyword tidak kosong, dilakukan pencarian pada _allCategori menggunakan metode .where() yang memfilter kategori berdasarkan enteredKeyword. Ini dilakukan dengan memeriksa apakah namemodel dari kategori tersebut mengandung enteredKeyword secara case-insensitive.
.cast<CategoriModel>(): Kode ini Mengonversi hasil filter menjadi list yang berisi objek-objek CategoriModel.
.toList(): Kode ini Mengonversi hasil filter yang berupa iterable menjadi list.

Jadi, kode diatas bertanggung jawab untuk melakukan pencarian pada daftar kategori berdasarkan kata kunci yang dimasukkan. Jika kata kunci kosong, akan menampilkan seluruh daftar kategori. Jika tidak, akan menampilkan kategori-kategori yang sesuai dengan kata kunci tersebut.

setState(() {
      _foundCategori = results;
    });
Kode ini digunakan dalam Flutter untuk memperbarui state dari widget.

Code categori.dart

class CategoriModel {
  int idmodel;
  String namemodel;
  String descmodel;
  String images;

  CategoriModel({
    required this.idmodel,
    required this.namemodel,
    required this.descmodel,
    required this.images,
  });

  static List<CategoriModel> getCategories() {
    List<CategoriModel> categories = [];

    categories.add(CategoriModel(
      idmodel: 1,
      namemodel: 'viennoiseries',
      descmodel: 'Resepnya : ',
      images: 'assets/images/viennoiseries_cover.jpg',
    ));
    categories.add(CategoriModel(
      idmodel: 2,
      namemodel: 'Pastries',
      descmodel: 'Resepnya : ',
      images: 'assets/images/pastries_cover.jpg',
    ));

    categories.add(CategoriModel(
      idmodel: 3,
      namemodel: 'Bread & Buns',
      descmodel: 'Resepnya : ',
      images: 'assets/images/bread_cover.jpg',
    ));

    categories.add(CategoriModel(
      idmodel: 3,
      namemodel: 'COFFEE',
      descmodel: 'Resepnya : ',
      images: 'assets/images/coffee_cover.jpg',
    ));

    categories.add(CategoriModel(
      idmodel: 3,
      namemodel: 'JUICE',
      descmodel: 'Resepnya : ',
      images: 'assets/images/juice_cover.jpg',
    ));

    categories.add(CategoriModel(
      idmodel: 3,
      namemodel: 'Latte',
      descmodel: 'Resepnya : ',
      images: 'assets/images/latte_cover.jpg',
    ));

    categories.add(CategoriModel(
      idmodel: 3,
      namemodel: 'Crime',
      descmodel: 'Resepnya : ',
      images: 'assets/images/crime_cover.jpg',
    ));
    return categories;
  }

  toLowerCase() {}
}

Jika kode diatas dijalankan akan tampak seperti video dibawah ini

Demikian tutorial Membuat pencarian/search ListView di Flutter semoga bermanfaat ya

Tinggalkan Balasan

Alamat email Anda tidak akan dipublikasikan. Ruas yang wajib ditandai *