Flutter’da Custom Bottom Navigation Bar Nasıl Oluşturulur?

 

Sıfırdan Adım Adım Anlatım


Uygulamanı açan bir kullanıcı ilk olarak nereye bakar? Genelde ekranın en altına. İşte tam bu yüzden Bottom Navigation Bar, kullanıcı deneyiminin kalbinde yer alır. Ama varsayılan bar yetmez. Özgün, akılda kalıcı ve sana ait bir deneyim istiyorsan custom bar şart.

Bu yazıda, Flutter’da kendi özel alt gezinme çubuğunu (Custom Bottom Navigation Bar) nasıl sıfırdan yazabileceğini sade ve anlaşılır bir dille anlatıyorum. Hazırsan başlayalım.

1. Hazırlık: Neyi Yapacağız?

  • Dört sekmeli bir uygulama
  • Her sekmenin kendine ait ekranı olacak

Alt menüdeki butonlar:

  • Seçili ise farklı bir renkte gösterilecek
  • Tıklanınca sayfa değişecek
  • Animasyonla canlandırılacak

2. Proje Yapısı

Ana sayfa dosyamız:

main.dart

Sayfa dosyalarımız:

screens/
home_screen.dart
search_screen.dart
profile_screen.dart
settings_screen.dart
widgets/
custom_nav_bar.dart

3. Ana Yapı: Stateful Widget ile Sayfa Değişimi

Önce main.dart içinde tabların geçişini yönetecek olan temel yapıyı kuralım:

import 'package:custom_nav_bar/widgets/custom_nav_bar.dart';
import 'package:flutter/material.dart';
import 'screens/home_screen.dart';
import 'screens/search_screen.dart';
import 'screens/profile_screen.dart';
import 'screens/settings_screen.dart';

void main() {
runApp(MyApp());
}

class MyApp extends StatelessWidget {
const MyApp({super.key});

@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Custom BottomNav Demo',
debugShowCheckedModeBanner: false,
home: MainScreen(),
);
}
}

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

@override
State<MainScreen> createState() => _MainScreenState();
}

class _MainScreenState extends State<MainScreen> {
int currentIndex = 0;

final screens = [
HomeScreen(),
SearchScreen(),
ProfileScreen(),
SettingsScreen(),
];

@override
Widget build(BuildContext context) {
return Scaffold(
body: screens[currentIndex],
bottomNavigationBar: CustomBottomNavBar(
currentIndex: currentIndex,
onTap: (index) {
setState(() {
currentIndex = index;
});
},
),
);
}
}

4. Custom BottomNavigationBar’ı Yazalım

widgets klasörü içerisineCustomBottomNavBar adında bir widget oluşturalım:

import 'package:flutter/material.dart';

class CustomBottomNavBar extends StatelessWidget {
final int currentIndex;
final Function(int) onTap;

const CustomBottomNavBar({
required this.currentIndex,
required this.onTap,
});

@override
Widget build(BuildContext context) {
return Container(
padding: const EdgeInsets.symmetric(vertical: 12, horizontal: 16),
decoration: BoxDecoration(
color: Colors.white,
boxShadow: [
BoxShadow(color: Colors.black12, blurRadius: 10),
],
borderRadius: const BorderRadius.only(
topLeft: Radius.circular(16),
topRight: Radius.circular(16),
),
),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: [
_buildNavItem(icon: Icons.home, index: 0, label: 'Ana Sayfa'),
_buildNavItem(icon: Icons.search, index: 1, label: 'Ara'),
_buildNavItem(icon: Icons.person, index: 2, label: 'Profil'),
_buildNavItem(icon: Icons.settings, index: 3, label: 'Ayarlar'),
],
),
);
}

Widget _buildNavItem({
required IconData icon,
required int index,
required String label,
}) {
final isSelected = index == currentIndex;

return GestureDetector(
onTap: () => onTap(index),
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
AnimatedContainer(
duration: Duration(milliseconds: 250),
padding: EdgeInsets.all(8),
decoration: BoxDecoration(
color: isSelected ? Colors.blue.shade100 : Colors.transparent,
shape: BoxShape.circle,
),
child: Icon(
icon,
color: isSelected ? Colors.blue : Colors.grey,
size: isSelected ? 28 : 24,
),
),
const SizedBox(height: 4),
Text(
label,
style: TextStyle(
fontSize: 12,
color: isSelected ? Colors.blue : Colors.grey,
fontWeight: isSelected ? FontWeight.bold : FontWeight.normal,
),
),
],
),
);
}
}

5. Sayfa Örneklerini Ekleyelim

Her ekran için basit bir scaffold yapısı yeterli:

home_screen.dart

import 'package:flutter/material.dart';

class HomeScreen extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.grey[100],
body: Center(
child: Text('Ana Sayfa'),
),
);
}
}

search_screen.dart

import 'package:flutter/material.dart';

class SearchScreen extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.blueAccent[100],
body: Center(
child: Text('Arama Sayfası'),
),
);
}
}

profile_screen.dart

import 'package:flutter/material.dart';

class ProfileScreen extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.amber[100],
body: Center(
child: Text('Profil Sayfası'),
),
);
}
}

settings_screen.dart

import 'package:flutter/material.dart';

class SettingsScreen extends StatelessWidget {
const SettingsScreen({super.key});

@override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.purpleAccent[100],
body: Center(child: Text('Ayarlar Sayfası')),
);
}
}

Ve Sonuç

Artık uygulamanda kendi tarzını yansıtan, sade ama güçlü bir alt gezinme çubuğu var.
Bu yapıyı dilediğin gibi renklendirebilir, şekillendirebilir, ikonları değiştirebilir ya da butonlara bildirim rozetleri ekleyebilirsin.

Kendi custom widget’ını yazmak, Flutter’ı derinlemesine öğrenmenin en keyifli yollarından biri. Hem görünüm senin olur, hem de kullanıcı deneyimi fark yaratır.



Umarım faydalı olmuştur.

Daha fazlası için abone olmayı unutmayın.

Teşekkürler.

Selin.

Hiç yorum yok: