Sitemap

Displaying Restaurant List

7 min readDec 1, 2025

--

Displaying Restaurant List from Apps Development with Flutter Path MySkill.id

Yuk subscribe untuk mendapatkan email notifikasi setiap ada artikel terbaru oleh MySkill

Press enter or click to view image in full size
Sumber : My Skill

Dalam industri kuliner digital, kemampuan menampilkan daftar restoran secara efisien dan menarik menjadi fondasi kesuksesan aplikasi. Pengguna modern mengharapkan akses cepat ke informasi restoran dengan visual yang memukau dan navigasi yang intuitif. Flutter hadir sebagai solusi ideal karena kemampuannya menghasilkan UI native yang konsisten di berbagai platform dengan performa tinggi.

1. Persiapan Lingkungan Pengembangan

Sebelum memulai implementasi, pastikan struktur proyek sudah terorganisir dengan baik. Struktur folder yang direkomendasikan:

lib/
├── main.dart
├── models/
│ └── restaurant_model.dart
├── screens/
│ ├── home_screen.dart
│ └── restaurant_detail_screen.dart
└── widgets/
└── restaurant_card.dart
assets/
└── images/
├── banner_0.jpg
├── banner_1.jpg
├── banner_2.jpg
├── sate.jpg
├── gudeg.jpg
├── rendang.jpg
└── pempek.jpg

Penjelasan Struktur:

  • models/: Menyimpan struktur data restoran
  • screens/: Berisi halaman utama aplikasi
  • widgets/: Komponen UI yang dapat digunakan kembali
  • assets/: Menyimpan gambar dan resource statis

a. File: main.dart (Entry Point Aplikasi)

import 'package:flutter/material.dart';
import 'screens/home_screen.dart';

void main() {
runApp(const RestaurantApp());
}

class RestaurantApp extends StatelessWidget {
const RestaurantApp({Key? key}) : super(key: key);

@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Restaurant Explorer',
theme: ThemeData(
primarySwatch: Colors.deepOrange,
visualDensity: VisualDensity.adaptivePlatformDensity,
),
home: const HomeScreen(),
debugShowCheckedModeBanner: false,
);
}
}

Penjelasan:

  • MaterialApp: Widget root aplikasi Flutter
  • theme: Mengatur tema warna utama aplikasi
  • home: Halaman pertama yang ditampilkan (HomeScreen)
  • debugShowCheckedModeBanner: Menyembunyikan banner debug

2. Membangun Model Data Restoran

File restaurant_model.dart berfungsi sebagai cetakan untuk data restoran:

class Restaurant {
final String id; // Identifikasi unik setiap restoran
final String name; // Nama restoran yang ditampilkan
final String city; // Lokasi kota restoran
final String imageUrl; // Path gambar thumbnail
final double rating; // Rating restoran (0-5)

Restaurant({
required this.id,
required this.name,
required this.city,
required this.imageUrl,
required this.rating,
});
}

Penjelasan Kode untuk Pemula:

  • class Restaurant: Seperti blueprint untuk membuat objek restoran
  • final String id: Variabel yang tidak bisa diubah setelah dibuat, berfungsi sebagai KTP restoran
  • required: Memastikan setiap restoran harus memiliki data ini saat dibuat
  • double rating: Angka desimal untuk rating (contoh: 4.5)

3. Implementasi UI Dashboard

Dashboard dibangun dengan komponen-komponen yang saling terintegrasi dalam satu layar utama.

a. App Bar — Jendela Utama Aplikasi

AppBar(
elevation: 0, // Menghilangkan bayangan di bawah app bar
backgroundColor: Colors.white, // Latar belakang putih bersih
title: const Text(
'Jelajahi Restoran',
style: TextStyle(
color: Colors.deepOrange, // Warna teks oranye untuk branding
fontWeight: FontWeight.bold, // Tebal untuk penekanan
fontSize: 20, // Ukuran teks yang mudah dibaca
),
),
actions: [ // Tombol di sisi kanan app bar
IconButton(
icon: const Icon(Icons.search, color: Colors.deepOrange),
onPressed: () {
// Tempat logika pencarian restoran
},
),
IconButton(
icon: const Icon(Icons.filter_list, color: Colors.deepOrange),
onPressed: () {
// Tempat logika filter restoran
},
),
],
)

Penjelasan Visual:

  • elevation: 0 membuat app bar menyatu dengan layar (flat design)
  • actions seperti rak tempat menyimpan tombol aksi cepat
  • Ikon berwarna oranye menciptakan konsistensi visual dengan tema aplikasi

b. Promotional Banner — Media Promosi Interaktif

Container(
height: 180, // Tinggi banner 180 pixel
margin: const EdgeInsets.all(16), // Jarak 16 pixel dari semua sisi
child: PageView.builder( // Widget untuk slide gambar
itemCount: 3, // Jumlah slide banner
itemBuilder: (context, index) {
return Container(
margin: const EdgeInsets.only(right: 8), // Jarak antar slide
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(16), // Sudut melengkung
image: DecorationImage(
image: AssetImage('assets/images/banner_$index.jpg'),
fit: BoxFit.cover, // Gambar menutupi seluruh area
),
),
);
},
),
)

Penjelasan Cara Kerja:

  • PageView.builder seperti karusel foto yang bisa digeser
  • BoxDecoration seperti bingkai foto dengan sudut melengkung
  • BoxFit.cover memastikan gambar tidak terdistorsi dan memenuhi area

c. Restaurant List — Daftar Restoran Interaktif

Struktur Data Contoh:

final List<Restaurant> restaurantList = [
Restaurant(
id: '1',
name: 'Sate Khas Senayan',
city: 'Jakarta',
imageUrl: 'assets/images/sate.jpg',
rating: 4.5,
),
Restaurant(
id: '2',
name: 'Gudeg Yu Djum',
city: 'Yogyakarta',
imageUrl: 'assets/images/gudeg.jpg',
rating: 4.8,
),
];

Implementasi ListView:

Expanded(                      // Memastikan list mengambil sisa ruang layar
child: ListView.builder(
padding: const EdgeInsets.symmetric(horizontal: 16), // Jarak dalam list
itemCount: restaurantList.length, // Jumlah item dalam list
itemBuilder: (context, index) {
final restaurant = restaurantList[index]; // Ambil data restoran ke-index
return Container(
margin: const EdgeInsets.only(bottom: 16), // Jarak antar kartu
child: Card(
elevation: 4, // Efek bayangan untuk kedalaman
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(12), // Sudut melengkung
),
child: InkWell( // Membuat area bisa diklik
borderRadius: BorderRadius.circular(12),
onTap: () {
// Aksi saat kartu diklik
},
child: Padding(
padding: const EdgeInsets.all(12), // Jarak dalam kartu
child: Row(
children: [
// Gambar Thumbnail
ClipRRect( // Widget untuk memotong sudut gambar
borderRadius: BorderRadius.circular(8),
child: Image.asset(
restaurant.imageUrl,
width: 100, // Lebar gambar
height: 100, // Tinggi gambar
fit: BoxFit.cover, // Gambar menutupi area
),
),
const SizedBox(width: 16), // Jarak horizontal
// Informasi Restoran
Expanded( // Mengisi sisa ruang horizontal
child: Column(
crossAxisAlignment: CrossAxisAlignment.start, // Rata kiri
children: [
Text(
restaurant.name,
style: const TextStyle(
fontWeight: FontWeight.bold, // Teks tebal
fontSize: 16, // Ukuran teks
),
),
const SizedBox(height: 4), // Jarak vertikal
Row( // Baris untuk lokasi
children: [
const Icon(
Icons.location_on, // Ikon lokasi
size: 16, // Ukuran ikon kecil
color: Colors.grey, // Warna abu-abu
),
const SizedBox(width: 4), // Jarak kecil
Text(
restaurant.city,
style: const TextStyle(color: Colors.grey),
),
],
),
const SizedBox(height: 8), // Jarak vertikal
Row( // Baris untuk rating
children: [
const Icon(
Icons.star, // Ikon bintang
color: Colors.amber, // Warna kuning emas
size: 16,
),
const SizedBox(width: 4),
Text(
restaurant.rating.toString(),
style: const TextStyle(
fontWeight: FontWeight.bold,
),
),
],
),
],
),
),
// Tombol Check
ElevatedButton(
onPressed: () {
// Aksi saat tombol ditekan
},
style: ElevatedButton.styleFrom(
backgroundColor: Colors.deepOrange, // Warna tombol
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(8), // Sudut tombol
),
),
child: const Text('Check'), // Teks tombol
),
],
),
),
),
),
);
},
),
)

Penjelasan Mendalam untuk Pemula:

  1. Struktur Kartu Restoran:
  • Card seperti kartu nama fisik dengan efek bayangan
  • InkWell memberikan efek riak saat disentuh (feedback visual)
  • Row menyusun elemen secara horizontal seperti meja dengan kursi

2. Komponen Visual:

Get My Skill’s stories in your inbox

Join Medium for free to get updates from this writer.

Gambar Thumbnail:

  • ClipRRect seperti gunting yang memotong sudut gambar
  • Ukuran 100x100 pixel seimbang untuk layar ponsel

Informasi Teks:

  • Nama restoran dengan font tebal sebagai fokus utama
  • Lokasi dengan ikon pin untuk pengenalan cepat
  • Rating dengan bintang untuk visualisasi kualitas

Tombol Aksi:

  • Warna oranye konsisten dengan tema aplikasi
  • Ukuran proporsional tidak terlalu besar/kecil

3. Optimasi Performa:

  • ListView.builder hanya membuat item yang terlihat di layar
  • Expanded memastikan layout tidak pecah saat layar berubah

d. Bottom Navigation Bar — Peta Navigasi Aplikasi

BottomNavigationBar(
type: BottomNavigationBarType.fixed, // Mencegah pergeseran label
selectedItemColor: Colors.deepOrange, // Warna item aktif
unselectedItemColor: Colors.grey, // Warna item non-aktif
currentIndex: 0, // Halaman aktif (Beranda)
onTap: (index) {
// Logika perpindahan halaman berdasarkan index
},
items: const [
BottomNavigationBarItem(
icon: Icon(Icons.home), // Ikon rumah
label: 'Beranda', // Label teks
),
BottomNavigationBarItem(
icon: Icon(Icons.explore), // Ikon kompas
label: 'Jelajahi',
),
BottomNavigationBarItem(
icon: Icon(Icons.bookmark), // Ikon bookmark
label: 'Favorit',
),
BottomNavigationBarItem(
icon: Icon(Icons.person), // Ikon orang
label: 'Profil',
),
],
)

Penjelasan Fungsional:

  • type: fixed membuat semua menu selalu terlihat
  • currentIndex menentukan menu yang sedang dibuka
  • onTap seperti pintu yang membuka halaman berbeda
  • Setiap item memiliki ikon dan label untuk kejelasan

4. Integrasi Navigasi ke Halaman Detail

Saat tombol “Check” ditekan, pengguna akan diarahkan ke halaman detail restoran:

// Di dalam onPressed tombol Check
onPressed: () {
Navigator.push( // Perintah untuk berpindah halaman
context,
MaterialPageRoute(
builder: (context) => RestaurantDetailPage(
restaurant: restaurant, // Kirim data restoran ke halaman detail
),
),
);
},

Halaman Detail Restoran:

class RestaurantDetailPage extends StatelessWidget {
final Restaurant restaurant; // Terima data restoran

const RestaurantDetailPage({Key? key, required this.restaurant}) : super(key: key);

@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(restaurant.name), // Judul dengan nama restoran
backgroundColor: Colors.deepOrange,
),
body: SingleChildScrollView( // Agar konten bisa di-scroll
child: Column(
children: [
Image.asset(restaurant.imageUrl), // Gambar utama restoran
Padding(
padding: const EdgeInsets.all(16),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
restaurant.name,
style: const TextStyle(
fontSize: 24, // Ukuran besar untuk judul
fontWeight: FontWeight.bold,
),
),
const SizedBox(height: 8),
Row(
children: [
const Icon(Icons.location_on),
const SizedBox(width: 8),
Text(restaurant.city),
],
),
// Tambahkan informasi detail lainnya seperti:
// - Deskripsi restoran
// - Jam operasional
// - Menu makanan
// - Ulasan pengguna
],
),
),
],
),
),
);
}
}

Penjelasan Alur Navigasi:

  1. Pengguna menekan tombol “Check” pada kartu restoran
  2. Navigator.push membuka halaman baru seperti menambahkan lembar baru di atas
  3. Data restoran dikirim melalui konstruktor halaman detail
  4. Halaman detail menampilkan informasi lengkap dengan gambar besar

5. Tips Praktis untuk Pengembang Pemula

  1. Manajemen Gambar:
  • Simpan gambar di folder assets/images
  • Daftarkan di pubspec.yaml dengan format:
flutter:
assets:
- assets/images/
  • Gunakan format WebP untuk ukuran file lebih kecil

2. Optimasi Performa:

  • Gunakan const untuk widget yang tidak berubah
  • Batasi jumlah item dalam ListView (ideal < 100 untuk data statis)
  • Implementasikan ListView.separated untuk pembatas antar item

3. Debugging Visual:

  • Gunakan debugPaintSizeEnabled = true di main.dart untuk melihat batas widget
  • Aktifkan Flutter Inspector di Android Studio/Dart DevTools

4. Responsivitas:

  • Gunakan MediaQuery untuk menyesuaikan ukuran:
final screenWidth = MediaQuery.of(context).size.width;
  • Atur padding berdasarkan ukuran layar

Cara Menjalankan Aplikasi:

  1. Buat proyek Flutter baru
  2. Buat struktur folder seperti di atas
  3. Salin semua kode ke file yang sesuai
  4. Tambahkan gambar ke folder assets/images
  5. Konfigurasi pubspec.yaml
  6. Jalankan dengan flutter run

Kesimpulan

Implementasi daftar restoran dalam Flutter membutuhkan perhatian pada tiga aspek utama: struktur data yang jelas, komponen UI yang intuitif, dan alur navigasi yang mulus. Dengan mengikuti panduan ini, kita telah membangun fondasi kuat untuk aplikasi kuliner yang tidak hanya fungsional tetapi juga menarik secara visual. Setiap komponen dirancang dengan pertimbangan khusus untuk pengalaman pengguna optimal — dari app bar yang informatif hingga kartu restoran yang interaktif.

Langkah selanjutnya yang dapat dikembangkan:

  • Integrasi dengan API untuk data real-time
  • Implementasi fitur pencarian dan filter
  • Penambahan animasi transisi halaman
  • Optimasi untuk berbagai ukuran layar
  • Implementasi state management (Provider/Riverpod)

Dengan Flutter, kemungkinan pengembangan fitur kuliner menjadi tak terbatas — tergantung pada kreativitas dan kebutuhan pengguna akhir. Pastikan selalu menguji aplikasi di berbagai perangkat untuk memastikan konsistensi pengalaman pengguna.

Learn More Via: https://myskill.id/course/state-and-props-management

--

--