ফ্লাটারে টপবার, বটমবার, ড্রয়ার ন্যাভিগেশন

ফ্লাটার অ্যাপে খুব সহজে আমরা টপবার, বটমবার, ড্রয়ার এমনকি বটমশীট ন্যাভিগেশন যোগ করতে পারি। এর আগে আমরা ফ্লাটারে ন্যাভিগেশন সম্পর্কে জেনেছি। এবার প্রথমে দেখি কিভাবে বটমবার ন্যাভিগেশন তৈরি করা যায়।

import 'package:flutter/material.dart';

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

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Bottom Navigation Example',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: BottomNavScreen(),
    );
  }
}

class BottomNavScreen extends StatefulWidget {
  @override
  _BottomNavScreenState createState() => _BottomNavScreenState();
}

class _BottomNavScreenState extends State<BottomNavScreen> {
  int _selectedIndex = 0;

  // List of widget screens
  static const List<Widget> _pages = <Widget>[
    HomeScreen(),
    LibraryScreen(),
    ProfileScreen(),
  ];

  void _onItemTapped(int index) {
    setState(() {
      _selectedIndex = index;
    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Bottom Nav Example'),
      ),
      body: _pages[_selectedIndex],
      bottomNavigationBar: BottomNavigationBar(
        currentIndex: _selectedIndex,
        onTap: _onItemTapped,
        selectedItemColor: Colors.blue,
        unselectedItemColor: Colors.grey,
        items: const [
          BottomNavigationBarItem(
            icon: Icon(Icons.home),
            label: 'Home',
          ),
          BottomNavigationBarItem(
            icon: Icon(Icons.book),
            label: 'Library',
          ),
          BottomNavigationBarItem(
            icon: Icon(Icons.person),
            label: 'Profile',
          ),
        ],
      ),
    );
  }
}

// Dummy Screens
class HomeScreen extends StatelessWidget {
  const HomeScreen();

  @override
  Widget build(BuildContext context) {
    return Center(child: Text('🏠 Home Screen'));
  }
}

class LibraryScreen extends StatelessWidget {
  const LibraryScreen();

  @override
  Widget build(BuildContext context) {
    return Center(child: Text('📚 Library Screen'));
  }
}

class ProfileScreen extends StatelessWidget {
  const ProfileScreen();

  @override
  Widget build(BuildContext context) {
    return Center(child: Text('👤 Profile Screen'));
  }
}

আউটপুট পাবো এমনঃ

এখানে অ্যাপের এন্ট্রি পয়েন্টে আমরা হোম হিসেবে BottomNavScreen সেট করেছি। যেখানে Scaffold এ bottomNavigationBar প্রোপার্টি ব্যবহার করে তিনটা আইটেম যোগ করেছি। কোন আইটেমে ক্লিক করলে কোন স্ক্রিন দেখাবে, তা সিলেক্ট করেছি _selectedIndex ভ্যারিয়েবলের মাধ্যমে। এই _selectedIndex ভ্যারিয়েবলের ভ্যালু অনুযায়ী _pages লিস্টে থাকা স্ক্রিন গুলোর যে কোন একটা দেখাবে।

নিচের দিকে আমরা কিছু ডামি স্ক্রিন তৈরি করে নিয়েছি। এগুলোর পরিবর্তে প্রয়োজন অনুযায়ী যে কোন উইজেট আমরা ব্যবহার করতে পারব। এখানে তিনটা আইটেম যোগ করেছি। প্রয়োজন অনুযায়ী আরো আইটেম যোগ করতে পারেন। সর্বোচ্চ ৫টা আইটেম যদি যোগ করি, তাহলে আইটেম গুলো সুন্দর মত দেখাবে। এর বেশি দেখাতে গেলে হিবিজিবি হয়ে যাবে। বটমবারে স্ক্রলভিউ সাপোর্ট করে না। যদি এর থেকে বেশি আইটেম দেখাতে চাই, স্ক্রল ফিচার সহ, তাহলে কাস্টম বটমবার তৈরি করে নিতে হবে। অথবা কোন প্যাকেজ ব্যবহার করতে পারি।

টপবার ন্যাভিগেশন

টপব্যার ন্যাভিগেশনের জন্য আমরা অ্যাপবারের botom প্রোপার্টি ব্যবহার করতে পারি। যেমন এভাবে লিখতে পারি কোডঃ

import 'package:flutter/material.dart';

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

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Top Tab Navigation',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: TopTabScreen(),
    );
  }
}

class TopTabScreen extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return DefaultTabController(
      length: 3, // Number of tabs
      child: Scaffold(
        appBar: AppBar(
          title: Text('Top Tab Navigation'),
          bottom: TabBar(
            tabs: [
              Tab(icon: Icon(Icons.home), text: 'Home'),
              Tab(icon: Icon(Icons.book), text: 'Library'),
              Tab(icon: Icon(Icons.person), text: 'Profile'),
            ],
          ),
        ),
        body: TabBarView(
          children: [
            HomeScreen(),
            LibraryScreen(),
            ProfileScreen(),
          ],
        ),
      ),
    );
  }
}

// Dummy Screens
class HomeScreen extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Center(child: Text('🏠 Home Screen'));
  }
}

class LibraryScreen extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Center(child: Text('📚 Library Screen'));
  }
}

class ProfileScreen extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Center(child: Text('👤 Profile Screen'));
  }
}

যার আউটপুট পাবো এমনঃ

টপবার ন্যাভিগেশনের ক্ষেত্রে ডিফল্ট ভাবেই স্ক্রল ফিচার সাপোর্ট করে। তাই আমরা প্রয়োজন অনুযায়ী একাধিক আইটেম যোগ করতে পারি। এই ক্ষেত্রে isScrollable: true মডিফায়ার যোগ করে নিতে হবে।

import 'package:flutter/material.dart';

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

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Scrollable Tabs',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: ScrollableTabsScreen(),
    );
  }
}

class ScrollableTabsScreen extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return DefaultTabController(
      length: 6, // Total number of tabs
      child: Scaffold(
        appBar: AppBar(
          title: Text('Scrollable Tabs'),
          bottom: TabBar(
            isScrollable: true, // <- Important
            tabs: [
              Tab(icon: Icon(Icons.home), text: 'Home'),
              Tab(icon: Icon(Icons.book), text: 'Library'),
              Tab(icon: Icon(Icons.person), text: 'Profile'),
              Tab(icon: Icon(Icons.settings), text: 'Settings'),
              Tab(icon: Icon(Icons.info), text: 'About'),
              Tab(icon: Icon(Icons.contact_mail), text: 'Contact'),
            ],
          ),
        ),
        body: TabBarView(
          children: [
            Center(child: Text('🏠 Home')),
            Center(child: Text('📚 Library')),
            Center(child: Text('👤 Profile')),
            Center(child: Text('⚙️ Settings')),
            Center(child: Text('ℹ️ About')),
            Center(child: Text('📬 Contact')),
          ],
        ),
      ),
    );
  }
}

এখানে TabBarView এর children এ যে কোন উইজেট আমরা দেখাতে পারব।

বটমশিট ন্যাভিগেশন

আমরা চাইলে টপবার, বটমবারের পাশাপাশি অ্যাপের যে কোন যায়গায় বটমশিটের মাধ্যমে ন্যাভিগেশন যোগ করেত পারি। যেমনঃ

import 'package:flutter/material.dart';

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

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Bottom Sheet Navigation',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: HomeScreen(),
    );
  }
}

class HomeScreen extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Home Screen'),
      ),
      body: Center(
        child: ElevatedButton(
          onPressed: () {
            showModalBottomSheet(
              context: context,
              builder: (BuildContext context) {
                return Container(
                  height: 200, // Adjust as needed
                  child: Column(
                    children: <Widget>[
                      ListTile(
                        leading: Icon(Icons.home),
                        title: Text('Home'),
                        onTap: () {
                          Navigator.pop(context); // Close the bottom sheet
                          // Navigate to Home screen (already here!)
                          ScaffoldMessenger.of(context).showSnackBar(
                            SnackBar(content: Text('Already on Home!')),
                          );
                        },
                      ),
                      ListTile(
                        leading: Icon(Icons.settings),
                        title: Text('Settings'),
                        onTap: () {
                          Navigator.pop(context); // Close the bottom sheet
                          Navigator.push(
                            context,
                            MaterialPageRoute(builder: (context) => SettingsScreen()),
                          );
                        },
                      ),
                      ListTile(
                        leading: Icon(Icons.info),
                        title: Text('About'),
                        onTap: () {
                          Navigator.pop(context); // Close the bottom sheet
                          Navigator.push(
                            context,
                            MaterialPageRoute(builder: (context) => AboutScreen()),
                          );
                        },
                      ),
                    ],
                  ),
                );
              },
            );
          },
          child: Text('Show Navigation'),
        ),
      ),
    );
  }
}

class SettingsScreen extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Settings'),
      ),
      body: Center(
        child: Text('Settings Screen Content'),
      ),
    );
  }
}

class AboutScreen extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('About'),
      ),
      body: Center(
        child: Text('About Screen Content'),
      ),
    );
  }
}

যার আউটপুট পাবো এমনঃ

এখানে হোম স্ক্রিনে আমরা একটা বাটন যোগ করেছি। যেখানে ক্লিক করলে বটমশীট দেখাবে। যেখানে লিস্ট আকারে বিভিন্ন স্ক্রিনের লিস্ট দেখিয়েছি। এরপর এগুলোর যে কোন একটাতে ক্লিক করলে নির্দিষ্ট স্ক্রিনে যাবে।

ন্যাভিগেশন ড্রয়ার / সাইড প্যানেল

ফ্লাটারে ন্যাভিগেশন ড্রয়ার তৈরি করা খুবি সহজ। আইওএস অথবা এন্ড্রয়েডে ন্যাটিভ কোডে একই কাজের জন্য প্রচুর কোড লিখতে হয়। অথচ ফ্লাটারে ডিফল্ট ভাবেই ড্রয়ার মডিফায়ার রয়েছেঃ

import 'package:flutter/material.dart';

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Drawer Navigation',
      theme: ThemeData(primarySwatch: Colors.blue),
      home: HomeScreen(),
    );
  }
}

class HomeScreen extends StatefulWidget {
  @override
  _HomeScreenState createState() => _HomeScreenState();
}

class _HomeScreenState extends State<HomeScreen> {
  String _title = "Home";

  void _selectDrawerItem(String title) {
    setState(() {
      _title = title;
    });
    Navigator.pop(context); // Close the drawer
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(_title),
      ),
      drawer: Drawer(
        child: ListView(
          padding: EdgeInsets.zero,
          children: [
            DrawerHeader(
              decoration: BoxDecoration(color: Colors.blue),
              child: Text('Menu', style: TextStyle(color: Colors.white, fontSize: 24)),
            ),
            ListTile(
              leading: Icon(Icons.home),
              title: Text('Home'),
              onTap: () => _selectDrawerItem('Home'),
            ),
            ListTile(
              leading: Icon(Icons.book),
              title: Text('Library'),
              onTap: () => _selectDrawerItem('Library'),
            ),
            ListTile(
              leading: Icon(Icons.settings),
              title: Text('Settings'),
              onTap: () => _selectDrawerItem('Settings'),
            ),
          ],
        ),
      ),
      body: Center(
        child: Text('This is the $_title screen', style: TextStyle(fontSize: 24)),
      ),
    );
  }
}

যার আউটপুট পাবো এমনঃ

এখানে প্রয়োজন মত আরো তথ্য, যেমন ইউজারের বিভিন্ন তথ্য দেখানো যাবে।

ফ্লাটার অনেক বেশি কাস্টোমাইজেরবল। এগুলো ছাড়াও আরো অনেক ভাবেই আমরা ন্যাভিগেশন যোগ করতে পারি।

ফ্লোটিং বোটমবার ন্যাভিগেশন

ফ্লোটিং বোটমবার ন্যাভিগেশনের জন্য Positioned উইজেট ব্যবহার করে এভাবে লিখতে পারিঃ

import 'package:flutter/material.dart';

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(home: FloatingTabBarPage());
  }
}

class FloatingTabBarPage extends StatefulWidget {
  @override
  _FloatingTabBarPageState createState() => _FloatingTabBarPageState();
}

class _FloatingTabBarPageState extends State<FloatingTabBarPage> {
  int selectedIndex = 0;

  final List<Map<String, dynamic>> items = [
    {'icon': Icons.home, 'label': 'Home'},
    {'icon': Icons.menu_book, 'label': 'Courses'},
    {'icon': Icons.tv, 'label': 'Conference'},
    {'icon': Icons.person, 'label': 'My Profile'},
    {'icon': Icons.more_horiz, 'label': 'More'},
  ];

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Container(
        decoration: BoxDecoration(
          gradient: LinearGradient(
            begin: Alignment.topCenter,
            end: Alignment.bottomCenter,
            colors: [Colors.red, Colors.white],
            stops: [0.3, 1.0],
          ),
        ),

        child: Stack(
          children: [
            Center(child: Text("Selected: ${items[selectedIndex]['label']}")),

            // Floating Bottom Bar
            Positioned(
              left: 20,
              right: 20,
              bottom: 20,
              child: Container(
                padding: EdgeInsets.symmetric(horizontal: 8, vertical: 10),
                decoration: BoxDecoration(
                  color: Colors.grey.shade800.withValues(alpha: 0.9),
                  borderRadius: BorderRadius.circular(40),
                  boxShadow: [BoxShadow(color: Colors.black26, blurRadius: 8)],
                ),
                child: Row(
                  mainAxisAlignment: MainAxisAlignment.spaceAround,
                  children:
                      items.asMap().entries.map((entry) {
                        int index = entry.key;
                        var item = entry.value;
                        bool isSelected = index == selectedIndex;

                        return GestureDetector(
                          onTap: () {
                            setState(() => selectedIndex = index);
                          },
                          child: AnimatedContainer(
                            duration: Duration(milliseconds: 200),
                            padding: EdgeInsets.symmetric(
                              horizontal: 12,
                              vertical: 8,
                            ),
                            decoration:
                                isSelected
                                    ? BoxDecoration(
                                      color: Colors.grey.shade700,
                                      borderRadius: BorderRadius.circular(30),
                                    )
                                    : null,
                            child: Row(
                              children: [
                                Icon(
                                  item['icon'],
                                  color:
                                      isSelected
                                          ? Colors.white
                                          : Colors.white60,
                                ),
                                if (isSelected)
                                  Padding(
                                    padding: const EdgeInsets.only(left: 8.0),
                                    child: Text(
                                      item['label'],
                                      style: TextStyle(color: Colors.white),
                                    ),
                                  ),
                              ],
                            ),
                          ),
                        );
                      }).toList(),
                ),
              ),
            ),
          ],
        ),
      ),
    );
  }
}

যার আউটপুট পাবো এমনঃ

বোনাস হিসেবে লিনিয়ার গ্র্যাডিয়েন্ট ব্যাকগ্রাউন্ডে যোগ করেছি।

Leave a Comment