147 lines
4.5 KiB
Dart
147 lines
4.5 KiB
Dart
import 'package:flutter/material.dart';
|
|
import 'package:mobile_monitoring/core/constants/constants.dart';
|
|
|
|
class BottomNavbar extends StatelessWidget {
|
|
final int currentIndex;
|
|
final ValueChanged<int> onTap;
|
|
|
|
const BottomNavbar({
|
|
super.key,
|
|
required this.currentIndex,
|
|
required this.onTap,
|
|
});
|
|
|
|
// Warna hijau yang dicocokkan dengan desain
|
|
final Color activeGreen = AppColors.navbarActive;
|
|
|
|
Widget _buildNavItem(IconData icon, String label, int index) {
|
|
final isSelected = currentIndex == index;
|
|
return GestureDetector(
|
|
onTap: () => onTap(index),
|
|
behavior: HitTestBehavior.translucent,
|
|
child: SizedBox(
|
|
width: 70, // Memberikan area tap yang cukup
|
|
child: Column(
|
|
mainAxisAlignment: MainAxisAlignment.center,
|
|
children: [
|
|
Icon(
|
|
icon,
|
|
color: isSelected ? activeGreen : Colors.grey.shade400,
|
|
size: 28,
|
|
),
|
|
const SizedBox(height: 4),
|
|
Text(
|
|
label,
|
|
style: TextStyle(
|
|
color: isSelected ? activeGreen : Colors.grey.shade500,
|
|
fontSize: 12,
|
|
fontWeight: isSelected ? FontWeight.w600 : FontWeight.normal,
|
|
),
|
|
),
|
|
],
|
|
),
|
|
),
|
|
);
|
|
}
|
|
|
|
Widget _buildHomeNavItem(int index) {
|
|
return GestureDetector(
|
|
onTap: () => onTap(index),
|
|
child: Container(
|
|
width: 60,
|
|
height: 60,
|
|
decoration: BoxDecoration(
|
|
shape: BoxShape.circle,
|
|
color: activeGreen, // Warna hijau solid sesuai gambar
|
|
// Shadow dihapus/diminimalisir karena di desain aslinya terlihat flat
|
|
),
|
|
child: const Icon(
|
|
Icons.home_rounded,
|
|
color: Colors.white,
|
|
size: 34,
|
|
),
|
|
),
|
|
);
|
|
}
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
// Tinggi total navbar diperbesar sedikit untuk mengakomodasi notch & tombol melayang
|
|
return SizedBox(
|
|
height: 100,
|
|
child: Stack(
|
|
clipBehavior: Clip.none,
|
|
children: [
|
|
// Background dengan notch melengkung yang di-generate otomatis
|
|
Positioned.fill(
|
|
child: CustomPaint(
|
|
painter: _NavbarNotchPainter(),
|
|
),
|
|
),
|
|
|
|
// Menu Kiri dan Kanan
|
|
Positioned(
|
|
bottom: 0,
|
|
left: 0,
|
|
right: 0,
|
|
height: 65, // Tinggi area bar putihnya saja
|
|
child: Row(
|
|
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
|
|
children: [
|
|
// Menggunakan icon bar_chart agar mirip dengan desain 3 tiang grafik
|
|
_buildNavItem(Icons.bar_chart_rounded, AppStrings.monitoring, 0),
|
|
const SizedBox(width: 80), // Ruang kosong untuk notch di tengah
|
|
_buildNavItem(Icons.show_chart_rounded, AppStrings.graph, 2),
|
|
],
|
|
),
|
|
),
|
|
|
|
// Home Button di tengah
|
|
Positioned(
|
|
top: 5, // Mengatur posisi tombol melayang pas di atas lengkungan
|
|
left: 0,
|
|
right: 0,
|
|
child: Center(
|
|
child: _buildHomeNavItem(1),
|
|
),
|
|
),
|
|
],
|
|
),
|
|
);
|
|
}
|
|
}
|
|
|
|
class _NavbarNotchPainter extends CustomPainter {
|
|
@override
|
|
void paint(Canvas canvas, Size size) {
|
|
// Menggunakan bawaan Flutter agar lekukan otomatis presisi dan tidak ada glitch visual/abu-abu
|
|
const notchShape = CircularNotchedRectangle();
|
|
|
|
// Titik awal y untuk background putih (y = 35)
|
|
// Area dari y=0 hingga y=35 akan murni transparan menembus background aplikasi
|
|
final backgroundRect = Rect.fromLTWH(0, 35, size.width, size.height - 35);
|
|
|
|
// Ukuran dan posisi lubang (notch)
|
|
final notchRect = Rect.fromCenter(
|
|
center: Offset(size.width / 2, 35),
|
|
width: 80, // Dibuat sedikit lebih besar dari tombol (60) agar ada spasi putihnya
|
|
height: 80,
|
|
);
|
|
|
|
// Dapatkan jalur (path) yang sudah dihitung otomatis
|
|
final path = notchShape.getOuterPath(backgroundRect, notchRect);
|
|
|
|
// Gambar bayangan (shadow) yang halus, tidak menghasilkan blok abu-abu gelap
|
|
canvas.drawShadow(path, Colors.black.withValues(alpha: 0.1), 8.0, false);
|
|
|
|
// Gambar background navbar putih
|
|
final paint = Paint()
|
|
..color = Colors.white
|
|
..style = PaintingStyle.fill;
|
|
|
|
canvas.drawPath(path, paint);
|
|
}
|
|
|
|
@override
|
|
bool shouldRepaint(covariant CustomPainter oldDelegate) => false;
|
|
} |