+5

TabBar & Drawer trong Flutter – Tạo giao diện điều hướng linh hoạt

Trong bài viết trước chúng ta đã cùng nhau đi tìm hiểu về BottomNavigationBar trong flutter tuy nhiên khi sử dụng BottomNavigationBar chỉ phù hợp cho các giao diện có từ 3 đến 5 menu thôi. Vậy với những menu có nhiều hơn 5 thì phải làm như thế nào?

Đó chính là lý do xuất hiện bài hôm nay TabBar & Drawer trong Flutter

🧭 Tại sao cần TabBar & Drawer?

Khi xây dựng ứng dụng có nhiều màn hình hoặc chức năng, người dùng cần một cách dễ dàng để chuyển qua lại giữa các phần. Flutter cung cấp nhiều lựa chọn điều hướng – trong đó:

  • TabBar thường dùng khi muốn có thanh tab ngang trên đầu – chuyển nhanh giữa các nội dung liên quan.
  • Drawer là menu trượt từ cạnh trái – phù hợp khi app có nhiều tính năng nhưng không muốn hiển thị hết lên giao diện chính.

📌 Tạo giao diện với TabBar

Trong Flutter chúng ta được cung cấp DefaultTabController để quản lý các tab một cách dễ dàng.

Ví dụ:

Các bạn có thể sử dụng https://dartpad.dev/ để xem hình ảnh trực quan nhé 😆

import 'package:flutter/material.dart';

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

class MyApp extends StatelessWidget {
  
  Widget build(BuildContext context) {
    return MaterialApp(
      home: DefaultTabController(
        length: 3, // Số tab
        child: Scaffold(
          appBar: AppBar(
            title: Text('Ví dụ TabBar'),
            bottom: TabBar(
              tabs: [
                Tab(icon: Icon(Icons.home), text: 'Trang chủ'),
                Tab(icon: Icon(Icons.star), text: 'Yêu thích'),
                Tab(icon: Icon(Icons.settings), text: 'Cài đặt'),
              ],
            ),
          ),
          body: TabBarView(
            children: [
              Center(child: Text('Nội dung Trang chủ')),
              Center(child: Text('Nội dung Yêu thích')),
              Center(child: Text('Nội dung Cài đặt')),
            ],
          ),
        ),
      ),
    );
  }
}

Các thuộc tính thường dùng của TabBar

Dưới đây là một số thuộc tính quan trọng bạn có thể tùy chỉnh khi sử dụng TabBar:

  • tabs: (Bắt buộc) Một List<Widget> chứa các tab hiển thị trên thanh. Mỗi widget thường là một Tab widget.
  • controller: Một TabController để quản lý trạng thái của tab (ví dụ: tab hiện tại được chọn). Nếu không được cung cấp, TabBar sẽ cố gắng sử dụng DefaultTabController ở phía trên trong cây widget.
  • isScrollable: Một bool cho biết thanh tab có nên cuộn được hay không khi có quá nhiều tab. Mặc định là false.
  • indicatorColor: Màu sắc của đường gạch chân (indicator) dưới tab đang được chọn.
  • indicatorWeight: Độ dày của đường gạch chân (indicator).
  • indicatorPadding: Khoảng cách padding xung quanh đường gạch chân (indicator).
  • indicator: Một widget tùy chỉnh để hiển thị thay vì đường gạch chân mặc định.
  • labelColor: Màu sắc của văn bản và icon của tab đang được chọn.
  • unselectedLabelColor: Màu sắc của văn bản và icon của các tab chưa được chọn.
  • labelStyle: Kiểu chữ của văn bản trên tab đang được chọn.
  • unselectedLabelStyle: Kiểu chữ của văn bản trên các tab chưa được chọn.
  • labelPadding: Khoảng cách padding xung quanh văn bản của mỗi tab.
  • overlayColor: Màu sắc hiệu ứng khi người dùng chạm vào một tab.
  • splashFactory: Xác định loại hiệu ứng splash khi chạm vào tab.
  • enableFeedback: Một bool cho biết có nên phát ra phản hồi xúc giác khi một tab được chọn hay không.
  • physics: Cách thanh tab phản hồi các cử chỉ cuộn.

📌 Tạo menu Drawer

Chúng ta sẽ thêm Drawer vào Scaffold để hiển thị menu trượt từ trái.

Ví dụ:

Các bạn có thể sử dụng https://dartpad.dev/ để xem hình ảnh trực quan nhé 😆

import 'package:flutter/material.dart';

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

class MyDrawerApp extends StatelessWidget {
  
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(title: Text('Drawer Demo')),
        drawer: Drawer(
          child: ListView(
            padding: EdgeInsets.zero,
            children: [
              DrawerHeader(
                decoration: BoxDecoration(color: Colors.blue),
                child: Text('Chào Luân!', style: TextStyle(color: Colors.white, fontSize: 24)),
              ),
              ListTile(
                leading: Icon(Icons.home),
                title: Text('Trang chủ'),
                onTap: () {
                  Navigator.pop(context); // Đóng Drawer
                },
              ),
              ListTile(
                leading: Icon(Icons.settings),
                title: Text('Cài đặt'),
                onTap: () {
                  Navigator.pop(context);
                },
              ),
            ],
          ),
        ),
        body: Center(child: Text('Nội dung chính')),
      ),
    );
  }
}

Các thuộc tính thường dùng của Drawer

Dưới đây là một số thuộc tính quan trọng bạn có thể tùy chỉnh khi sử dụng Drawer:

  • child: Widget con hiển thị bên trong Drawer (thường là một ListView để chứa các mục menu).
  • elevation: Độ đổ bóng của Drawer khi nó trượt ra. Mặc định là 16.0.
  • semanticLabel: Nhãn ngữ nghĩa cho Drawer, hữu ích cho khả năng truy cập.
  • backgroundColor: Màu nền của Drawer. Nếu null, sẽ sử dụng màu nền của theme.
  • shape: Hình dạng của Drawer.
  • width: Chiều rộng của Drawer. Nếu null, sẽ sử dụng một giá trị mặc định hợp lý.
  • dragStartBehavior: Xác định cách cử chỉ kéo để mở Drawer bắt đầu. Mặc định là DragStartBehavior.start.
  • scrimColor: Màu sắc của lớp phủ (scrim) hiển thị khi Drawer đang mở, làm tối phần còn lại của màn hình. Nếu null, sẽ sử dụng màu đen với độ mờ 50%.
  • surfaceTintColor: Màu sắc lớp phủ bề mặt của Drawer, được sử dụng cho các hiệu ứng nâng cao trên Android S trở lên.
  • clipBehavior: Cách nội dung của Drawer bị cắt. Mặc định là Clip.none.

⚖️ So sánh ưu và nhược điểm của TabBar và Drawer

Dưới đây là bảng so sánh ngắn gọn về ưu và nhược điểm của TabBarDrawer để chúng ta có cái nhìn tổng quan hơn và giúp chúng ta đưa ra được các lựa chọn khi nào thì nên dùng cái nào:

Tính năng TabBar Drawer
Ưu điểm - Điều hướng nhanh chóng giữa các mục nội dung liên quan. - Phù hợp với số lượng lớn các tùy chọn/tính năng.
- Hiển thị trực quan các tùy chọn chính trên màn hình. - Giữ cho giao diện chính gọn gàng, không bị quá tải thông tin.
- Dễ dàng nhận biết trạng thái tab hiện tại. - Có thể chứa các thành phần giao diện phức tạp hơn (ví dụ: header tài khoản).
Nhược điểm - Chiếm không gian trên màn hình (thường ở phía trên hoặc dưới). - Cần thao tác vuốt hoặc nhấn icon để mở, có thể làm chậm thao tác.
- Không phù hợp với quá nhiều tab (trên 5 tab có thể gây rối). - Các tùy chọn không hiển thị trực tiếp, người dùng cần khám phá.
- Khó tùy biến các hiệu ứng chuyển đổi phức tạp giữa các tab. - Việc điều hướng có thể kém trực quan hơn so với các tùy chọn hiển thị sẵn.
Trường hợp sử dụng phù hợp - Ứng dụng có ít các mục nội dung chính liên quan đến nhau. - Ứng dụng có nhiều tính năng, cài đặt, hoặc các khu vực ít được truy cập thường xuyên.
- Muốn người dùng dễ dàng chuyển đổi qua lại giữa các mục. - Muốn giữ cho giao diện chính tập trung vào nội dung quan trọng nhất.

Lời kết

Qua bài ngày hôm nay chúng ta thấy được chúng ta cần có sự linh hoạt khi tạo dựng menu cho app sao cho phù hợp nhất

Ngày mai, chúng ta có thể sẽ tiếp tục với việc hiển thị danh sách bằng ListView hoặc học cách xử lý dữ liệu mạng (API).

Nếu bạn có bất kỳ câu hỏi hoặc muốn chia sẻ thêm kinh nghiệm, đừng ngần ngại để lại bình luận bên dưới nhé!

Hẹn gặp lại ở bài viết tiếp theo nhé! 😄


All Rights Reserved

Viblo
Let's register a Viblo Account to get more interesting posts.