Membuat Flutter Web Di Zapp.run
Membuat To-Do List Flutter Web dengan Background Foto
02 Februari 2026
Pada tutorial ini, kita akan membuat aplikasi To-Do List Flutter Web yang lengkap: bisa menambah jadwal, checklist selesai, hapus jadwal, pilih tanggal & jam, dan punya background foto keren.
Kode Flutter Lengkap
import 'package:flutter/material.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return const MaterialApp(
debugShowCheckedModeBanner: false,
home: TodoPage(),
);
}
}
class TodoPage extends StatefulWidget {
const TodoPage({super.key});
@override
State<TodoPage> createState() => _TodoPageState();
}
class _TodoPageState extends State<TodoPage> {
final TextEditingController todoController = TextEditingController();
DateTime? selectedDate;
TimeOfDay? selectedTime;
final List<Map<String, dynamic>> todoList = [];
void addTodo() {
if (todoController.text.isEmpty ||
selectedDate == null ||
selectedTime == null) return;
setState(() {
todoList.add({
'title': todoController.text,
'date': selectedDate,
'time': selectedTime,
'isDone': false,
});
todoController.clear();
selectedDate = null;
selectedTime = null;
});
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Jadwal / To-Do List'),
centerTitle: true,
backgroundColor: Colors.black.withOpacity(0.6),
),
body: Container(
decoration: const BoxDecoration(
image: DecorationImage(
image: NetworkImage(
'https://images.unsplash.com/photo-1517248135467-4c7edcad34c4',
),
fit: BoxFit.cover,
),
),
child: Container(
color: Colors.black.withOpacity(0.5),
child: Padding(
padding: const EdgeInsets.all(16),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
const Text(
'Tambah Jadwal',
style: TextStyle(
fontSize: 22,
fontWeight: FontWeight.bold,
color: Colors.white,
),
),
const SizedBox(height: 12),
Container(
padding: const EdgeInsets.all(12),
decoration: BoxDecoration(
color: Colors.white.withOpacity(0.9),
borderRadius: BorderRadius.circular(8),
),
child: Column(
children: [
TextField(
controller: todoController,
decoration: const InputDecoration(
border: OutlineInputBorder(),
hintText: 'Contoh: Meeting jam 9',
),
),
const SizedBox(height: 10),
Row(
children: [
Expanded(
child: ElevatedButton(
onPressed: () async {
final date = await showDatePicker(
context: context,
initialDate: DateTime.now(),
firstDate: DateTime.now(),
lastDate: DateTime(2100),
);
if (date != null) {
setState(() => selectedDate = date);
}
},
child: Text(
selectedDate == null
? 'Pilih Tanggal'
: '${selectedDate!.day}/${selectedDate!.month}/${selectedDate!.year}',
),
),
),
const SizedBox(width: 8),
Expanded(
child: ElevatedButton(
onPressed: () async {
final time = await showTimePicker(
context: context,
initialTime: TimeOfDay.now(),
);
if (time != null) {
setState(() => selectedTime = time);
}
},
child: Text(
selectedTime == null
? 'Pilih Jam'
: selectedTime!.format(context),
),
),
),
],
),
],
),
),
const SizedBox(height: 16),
const Text(
'Daftar Jadwal',
style: TextStyle(fontSize: 18, color: Colors.white),
),
const SizedBox(height: 8),
Expanded(
child: todoList.isEmpty
? const Center(
child: Text(
'Belum ada jadwal',
style: TextStyle(color: Colors.white),
),
)
: ListView.builder(
itemCount: todoList.length,
itemBuilder: (context, index) {
final todo = todoList[index];
return Container(
margin: const EdgeInsets.only(bottom: 8),
padding: const EdgeInsets.all(12),
decoration: BoxDecoration(
color: Colors.white.withOpacity(0.9),
borderRadius: BorderRadius.circular(8),
),
child: Row(
children: [
Checkbox(
value: todo['isDone'],
onChanged: (value) {
setState(() {
todo['isDone'] = value;
});
},
),
Expanded(
child: Column(
crossAxisAlignment:
CrossAxisAlignment.start,
children: [
Text(
todo['title'],
style: TextStyle(
fontSize: 16,
decoration: todo['isDone']
? TextDecoration.lineThrough
: null,
),
),
Text(
'${todo['date'].day}/${todo['date'].month}/${todo['date'].year} • ${todo['time'].format(context)}',
style:
const TextStyle(fontSize: 12),
),
],
),
),
IconButton(
icon: const Icon(Icons.delete,
color: Colors.red),
onPressed: () {
setState(() {
todoList.removeAt(index);
});
},
),
],
),
);
},
),
),
],
),
),
),
),
floatingActionButton: FloatingActionButton(
onPressed: addTodo,
child: const Icon(Icons.add),
),
);
}
}
Penjelasan Widget Flutter
- MaterialApp: Root aplikasi Flutter, menyediakan theme & navigator.
- Scaffold: Struktur dasar halaman, termasuk AppBar, body, floatingActionButton.
- AppBar: Bar atas dengan judul.
- Container: Box serbaguna, bisa diberi background, padding, border radius, dll.
- TextField: Input teks untuk menambahkan jadwal.
- Row & Column: Layout horizontal & vertikal.
- Expanded: Membuat widget mengambil space yang tersedia.
- Checkbox: Menandai jadwal selesai.
- IconButton: Tombol hapus jadwal.
- ListView.builder: Menampilkan list jadwal secara dinamis.
- FloatingActionButton: Tombol + untuk menambahkan jadwal.
- showDatePicker / showTimePicker: Widget built-in untuk memilih tanggal & jam.
Dengan kode ini, kamu punya aplikasi Flutter Web yang lengkap, interaktif, dan tampilannya modern. Background foto membuat UI lebih hidup, sementara overlay transparan menjaga teks tetap terbaca.
ih meni butut picanπΏ
BalasHapuspunya kamu juga butut pican
Hapus