Flutter UI: Aplikasi Elite Sports Cars
🚗 Flutter UI: Aplikasi Elite Sports Cars
Aplikasi ini adalah contoh showcase mobil sport mewah menggunakan Flutter. Didesain dengan tampilan elegan, animasi, dan informasi detail tiap mobil.
📱 Fitur Aplikasi:
- UI tema gelap modern
- PageView dengan animasi
- Bottom Navigation
- Dialog pop-up deskripsi mobil
🔧 Penjelasan Struktur:
- MyApp: Set tema dan warna global
- HomePage: Navigasi mobil dan UI utama
- CarPage: Tampilkan tiap mobil
- Car: Model data mobil
💻 Kode Lengkap:
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
static const Color primaryColor = Color(0xFF0F172A);
static const Color secondaryColor = Color(0xFF1E293B);
static const Color accentColor = Color(0xFF3B82F6);
static const Color goldAccent = Color(0xFFFBBF24);
static const Color cardColor = Color(0xFF1E293B);
static const Color backgroundColor = Color(0xFF0F172A);
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Elite Sport Cars',
theme: ThemeData(
brightness: Brightness.dark,
primaryColor: primaryColor,
scaffoldBackgroundColor: backgroundColor,
appBarTheme: AppBarTheme(
backgroundColor: Colors.transparent,
elevation: 0,
foregroundColor: Colors.white,
centerTitle: true,
),
bottomNavigationBarTheme: BottomNavigationBarThemeData(
selectedItemColor: goldAccent,
unselectedItemColor: Colors.grey[400],
backgroundColor: secondaryColor,
elevation: 20,
type: BottomNavigationBarType.fixed,
),
elevatedButtonTheme: ElevatedButtonThemeData(
style: ElevatedButton.styleFrom(
backgroundColor: accentColor,
foregroundColor: Colors.white,
elevation: 8,
shadowColor: accentColor.withOpacity(0.3),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(25),
),
padding: EdgeInsets.symmetric(horizontal: 32, vertical: 16),
),
),
),
home: HomePage(),
debugShowCheckedModeBanner: false,
);
}
}
class HomePage extends StatefulWidget {
@override
_HomePageState createState() => _HomePageState();
}
class _HomePageState extends State with TickerProviderStateMixin {
int _currentIndex = 0;
final PageController _pageController = PageController();
late AnimationController _animationController;
late Animation _fadeAnimation;
final List cars = [
Car(
image: 'assets/lambo.jpg',
title: 'Lamborghini Aventador',
brand: 'Lamborghini',
price: '\$500,000',
power: '730 HP',
speed: '350 km/h',
acceleration: '2.9s',
shortDesc: 'Supercar ikonik dengan mesin V12 dan desain agresif yang memukau.',
longDesc:
'Lamborghini Aventador adalah lambang kekuatan dan kemewahan absolut. Dilengkapi dengan mesin V12 6.5L naturally aspirated, mampu melesat dari 0–100 km/jam dalam 2.9 detik dengan kecepatan maksimum 350 km/h. Didesain dengan bahasa desain futuristik dan teknologi aerodinamis canggih yang terinspirasi dari dunia penerbangan. Aventador sangat populer di kalangan kolektor supercar karena suara mesinnya yang menggelegar dan performa tinggi baik di sirkuit maupun jalan raya.',
gradient: [Color(0xFFFF6B35), Color(0xFFFF8E53)],
),
Car(
image: 'assets/ferrari.jpg',
title: 'Ferrari F8 Tributo',
brand: 'Ferrari',
price: '\$280,000',
power: '710 HP',
speed: '340 km/h',
acceleration: '2.9s',
shortDesc: 'Ferrari bermesin V8 twin-turbo dengan warisan balap yang legendaris.',
longDesc:
'Ferrari F8 Tributo adalah penghormatan terhadap mesin V8 terbaik dalam sejarah Ferrari. Mengusung tenaga 710 HP dengan handling presisi tinggi dan teknologi Formula 1, F8 Tributo menyatukan estetika Italia, performa balap, dan inovasi teknologi. Interiornya menampilkan perpaduan sempurna antara kemewahan modern dan tradisi craftmanship Ferrari, menjadikannya pilihan utama bagi pecinta Ferrari sejati yang menghargai sejarah dan performa.',
gradient: [Color(0xFFDC143C), Color(0xFFFF1744)],
),
Car(
image: 'assets/porsche.jpg',
title: 'Porsche 911 Turbo S',
brand: 'Porsche',
price: '\$230,000',
power: '640 HP',
speed: '330 km/h',
acceleration: '2.7s',
shortDesc: 'Perpaduan sempurna kenyamanan harian dan performa balap kelas dunia.',
longDesc:
'Porsche 911 Turbo S menawarkan akselerasi yang menakjubkan: 0–100 km/jam dalam 2.7 detik berkat mesin boxer 3.8L twin-turbo yang dipadukan dengan sistem penggerak AWD dan kontrol traksi canggih. Sebagai puncak dari evolusi 911, Turbo S memadukan tradisi desain ikonik dengan teknologi terdepan. Cocok untuk penggunaan harian maupun track day, 911 Turbo S selalu siap memberikan pengalaman berkendara yang tak terlupakan dengan kenyamanan premium.',
gradient: [Color(0xFF1565C0), Color(0xFF42A5F5)],
),
];
@override
void initState() {
super.initState();
_animationController = AnimationController(
duration: Duration(milliseconds: 800),
vsync: this,
);
_fadeAnimation = Tween(begin: 0.0, end: 1.0).animate(
CurvedAnimation(parent: _animationController, curve: Curves.easeInOut),
);
_animationController.forward();
}
@override
void dispose() {
_animationController.dispose();
super.dispose();
}
void _onPageChanged(int index) {
setState(() => _currentIndex = index);
}
void _onNavTapped(int index) {
_pageController.animateToPage(
index,
duration: Duration(milliseconds: 500),
curve: Curves.easeOutCubic,
);
}
@override
Widget build(BuildContext context) {
return Scaffold(
extendBodyBehindAppBar: true,
appBar: AppBar(
title: ShaderMask(
shaderCallback: (bounds) => LinearGradient(
colors: [MyApp.goldAccent, Colors.orange],
).createShader(bounds),
child: Text(
'ELITE SPORTS CARS(aku nak satu)',
style: TextStyle(
fontSize: 20,
fontWeight: FontWeight.bold,
color: Colors.white,
letterSpacing: 2,
),
),
),
backgroundColor: Colors.transparent,
),
body: Container(
decoration: BoxDecoration(
gradient: LinearGradient(
begin: Alignment.topCenter,
end: Alignment.bottomCenter,
colors: [
MyApp.backgroundColor,
MyApp.secondaryColor.withOpacity(0.8),
],
),
),
child: FadeTransition(
opacity: _fadeAnimation,
child: PageView.builder(
controller: _pageController,
itemCount: cars.length,
onPageChanged: _onPageChanged,
itemBuilder: (_, index) => CarPage(car: cars[index]),
),
),
),
bottomNavigationBar: Container(
decoration: BoxDecoration(
boxShadow: [
BoxShadow(
color: Colors.black.withOpacity(0.3),
blurRadius: 20,
offset: Offset(0, -5),
),
],
),
child: ClipRRect(
borderRadius: BorderRadius.vertical(top: Radius.circular(25)),
child: BottomNavigationBar(
currentIndex: _currentIndex,
onTap: _onNavTapped,
items: [
BottomNavigationBarItem(
icon: Icon(Icons.directions_car_outlined),
activeIcon: Icon(Icons.directions_car),
label: 'Lambo',
),
BottomNavigationBarItem(
icon: Icon(Icons.flash_on_outlined),
activeIcon: Icon(Icons.flash_on),
label: 'Ferrari',
),
BottomNavigationBarItem(
icon: Icon(Icons.speed_outlined),
activeIcon: Icon(Icons.speed),
label: 'Porsche',
),
],
),
),
),
);
}
}
class CarPage extends StatefulWidget {
final Car car;
const CarPage({required this.car});
@override
_CarPageState createState() => _CarPageState();
}
class _CarPageState extends State with SingleTickerProviderStateMixin {
late AnimationController _slideController;
late Animation _slideAnimation;
@override
void initState() {
super.initState();
_slideController = AnimationController(
duration: Duration(milliseconds: 600),
vsync: this,
);
_slideAnimation = Tween(
begin: Offset(0, 0.3),
end: Offset.zero,
).animate(CurvedAnimation(
parent: _slideController,
curve: Curves.easeOutBack,
));
_slideController.forward();
}
@override
void dispose() {
_slideController.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return SingleChildScrollView(
physics: BouncingScrollPhysics(),
child: Column(
children: [
SizedBox(height: 100),
// Hero Image Section
Container(
height: 250,
width: double.infinity,
margin: EdgeInsets.symmetric(horizontal: 20),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(20),
boxShadow: [
BoxShadow(
color: widget.car.gradient[0].withOpacity(0.3),
blurRadius: 30,
spreadRadius: 5,
offset: Offset(0, 10),
),
],
),
child: ClipRRect(
borderRadius: BorderRadius.circular(20),
child: Image.asset(
widget.car.image,
fit: BoxFit.cover,
errorBuilder: (context, error, stackTrace) {
return Container(
decoration: BoxDecoration(
gradient: LinearGradient(
colors: widget.car.gradient,
),
),
child: Center(
child: Icon(
Icons.directions_car,
size: 80,
color: Colors.white.withOpacity(0.7),
),
),
);
},
),
),
),
SizedBox(height: 30),
// Main Card
SlideTransition(
position: _slideAnimation,
child: Container(
margin: EdgeInsets.symmetric(horizontal: 20),
padding: EdgeInsets.all(24),
decoration: BoxDecoration(
gradient: LinearGradient(
begin: Alignment.topLeft,
end: Alignment.bottomRight,
colors: [
MyApp.cardColor,
MyApp.cardColor.withOpacity(0.8),
],
),
borderRadius: BorderRadius.circular(25),
boxShadow: [
BoxShadow(
color: Colors.black.withOpacity(0.3),
blurRadius: 20,
spreadRadius: 5,
offset: Offset(0, 10),
),
],
border: Border.all(
color: widget.car.gradient[0].withOpacity(0.3),
width: 1,
),
),
child: Column(
children: [
// Brand Badge
Container(
padding: EdgeInsets.symmetric(horizontal: 16, vertical: 8),
decoration: BoxDecoration(
gradient: LinearGradient(colors: widget.car.gradient),
borderRadius: BorderRadius.circular(20),
),
child: Text(
widget.car.brand,
style: TextStyle(
color: Colors.white,
fontWeight: FontWeight.bold,
fontSize: 12,
letterSpacing: 1,
),
),
),
SizedBox(height: 16),
// Car Title
Text(
widget.car.title,
textAlign: TextAlign.center,
style: TextStyle(
fontSize: 28,
fontWeight: FontWeight.bold,
color: Colors.white,
letterSpacing: 0.5,
),
),
SizedBox(height: 8),
// Price
Text(
widget.car.price,
style: TextStyle(
fontSize: 20,
color: MyApp.goldAccent,
fontWeight: FontWeight.w600,
),
),
SizedBox(height: 20),
// Specs Row
Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
_buildSpecItem(Icons.flash_on, widget.car.power, 'Power'),
_buildSpecItem(Icons.speed, widget.car.speed, 'Top Speed'),
_buildSpecItem(Icons.timer, widget.car.acceleration, '0-100'),
],
),
SizedBox(height: 20),
// Description
Text(
widget.car.shortDesc,
textAlign: TextAlign.center,
style: TextStyle(
fontSize: 16,
color: Colors.grey[300],
height: 1.4,
),
),
SizedBox(height: 24),
// CTA Button
Container(
width: double.infinity,
child: ElevatedButton.icon(
onPressed: () => _showDetailDialog(context),
icon: Icon(Icons.info_outline),
label: Text(
'Detail Lengkap',
style: TextStyle(
fontSize: 16,
fontWeight: FontWeight.w600,
),
),
style: ElevatedButton.styleFrom(
backgroundColor: widget.car.gradient[0],
padding: EdgeInsets.symmetric(vertical: 16),
),
),
),
],
),
),
),
SizedBox(height: 40),
],
),
);
}
Widget _buildSpecItem(IconData icon, String value, String label) {
return Column(
children: [
Container(
padding: EdgeInsets.all(12),
decoration: BoxDecoration(
color: widget.car.gradient[0].withOpacity(0.2),
borderRadius: BorderRadius.circular(12),
),
child: Icon(
icon,
color: widget.car.gradient[0],
size: 24,
),
),
SizedBox(height: 8),
Text(
value,
style: TextStyle(
color: Colors.white,
fontWeight: FontWeight.bold,
fontSize: 14,
),
),
Text(
label,
style: TextStyle(
color: Colors.grey[400],
fontSize: 12,
),
),
],
);
}
void _showDetailDialog(BuildContext context) {
showDialog(
context: context,
builder: (context) => Dialog(
backgroundColor: Colors.transparent,
child: Container(
margin: EdgeInsets.all(20),
padding: EdgeInsets.all(24),
decoration: BoxDecoration(
gradient: LinearGradient(
begin: Alignment.topLeft,
end: Alignment.bottomRight,
colors: [
MyApp.cardColor,
MyApp.backgroundColor,
],
),
borderRadius: BorderRadius.circular(25),
boxShadow: [
BoxShadow(
color: Colors.black.withOpacity(0.5),
blurRadius: 30,
spreadRadius: 10,
),
],
border: Border.all(
color: widget.car.gradient[0].withOpacity(0.3),
width: 1,
),
),
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
// Header
Row(
children: [
Container(
padding: EdgeInsets.all(12),
decoration: BoxDecoration(
gradient: LinearGradient(colors: widget.car.gradient),
borderRadius: BorderRadius.circular(12),
),
child: Icon(
Icons.directions_car,
color: Colors.white,
size: 24,
),
),
SizedBox(width: 12),
Expanded(
child: Text(
widget.car.title,
style: TextStyle(
color: Colors.white,
fontSize: 20,
fontWeight: FontWeight.bold,
),
),
),
],
),
SizedBox(height: 20),
// Content
Container(
constraints: BoxConstraints(maxHeight: 300),
child: SingleChildScrollView(
physics: BouncingScrollPhysics(),
child: Text(
widget.car.longDesc,
style: TextStyle(
color: Colors.grey[300],
fontSize: 16,
height: 1.5,
),
),
),
),
SizedBox(height: 24),
// Close Button
Container(
width: double.infinity,
child: ElevatedButton(
onPressed: () => Navigator.pop(context),
child: Text(
'Tutup',
style: TextStyle(
fontSize: 16,
fontWeight: FontWeight.w600,
),
),
style: ElevatedButton.styleFrom(
backgroundColor: widget.car.gradient[0],
padding: EdgeInsets.symmetric(vertical: 16),
),
),
),
],
),
),
),
);
}
}
class Car {
final String image;
final String title;
final String brand;
final String price;
final String power;
final String speed;
final String acceleration;
final String shortDesc;
final String longDesc;
final List gradient;
Car({
required this.image,
required this.title,
required this.brand,
required this.price,
required this.power,
required this.speed,
required this.acceleration,
required this.shortDesc,
required this.longDesc,
required this.gradient,
});
}
Untuk versi lengkap kode, kamu juga bisa embed dari GitHub Gist atau simpan di repo publik.
📌 Catatan Penting:
- Pastikan folder
assets/berisi file:lambo.jpg,ferrari.jpg,porsche.jpg - Update
pubspec.yaml:flutter: assets: - assets/lambo.jpg - assets/ferrari.jpg - assets/porsche.jpg
📎 Sumber Demo
➡️ Klik di sini untuk mencoba aplikasinya langsung
📣 Ingin belajar lebih dalam Flutter UI/UX? Cek dokumentasi resmi di flutter.dev atau ikuti channel YouTube komunitas Flutter Indonesia.
Komentar
Posting Komentar