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

Postingan populer dari blog ini

Jenis-jenis sistem operasi mobile

flutter todo list app

Aplikasi Manajemen Barang Pinjaman dengan Flutter + Fitur Upload Gambar