DrawerController: Nắm Quyền Điều Khiển Ngăn Kéo Ứng Dụng Flutter
Flutter

DrawerController: Nắm Quyền Điều Khiển Ngăn Kéo Ứng Dụng Flutter

Author

Admin System

@root

Ngày xuất bản

18 Mar, 2026

Lượt xem

21 Lượt

"DrawerController"

Chào các bạn, Creyt đây! Hôm nay chúng ta sẽ mổ xẻ một khái niệm mà nhiều bạn hay nhầm lẫn hoặc chưa khai thác hết sức mạnh của nó: cái gọi là 'DrawerController' trong Flutter. Nghe tên thì hoành tráng, nhưng thực chất, nó là cách chúng ta nắm quyền điều khiển cái 'ngăn kéo bí mật' của ứng dụng – cái Drawer thần thánh đó.

Tưởng tượng ứng dụng của bạn là một cái bàn làm việc. Cái Drawer chính là hộc tủ kéo ra kéo vào, chứa đủ thứ đồ nghề, các tùy chọn điều hướng quan trọng. Bình thường, bạn chỉ cần gạt tay (vuốt từ mép màn hình) là nó tự mở. Nhưng đôi khi, bạn muốn có một cái 'điều khiển từ xa', bấm nút là hộc tủ tự động mở ra, hoặc tự động đóng lại, thay vì phải tự tay kéo. Đó chính là lúc 'DrawerController' (mà thực chất là cơ chế điều khiển Drawer thông qua ScaffoldState) phát huy tác dụng.

Nói cách khác, nó giúp bạn mở/đóng Drawer bằng mã lệnh, không chỉ dựa vào thao tác vuốt của người dùng.

Điều Khiển Ngăn Kéo: Chìa Khóa Nằm Ở Đâu?

Trong Flutter, Drawer là một widget được đặt trong Scaffold. Scaffold chính là khung sườn chính của ứng dụng bạn, nó quản lý AppBar, BottomNavigationBar, và cả cái Drawer này nữa. Để điều khiển được Drawer, chúng ta cần 'nói chuyện' trực tiếp với Scaffold đang chứa nó. Và cách để làm điều đó chính là thông qua ScaffoldState.

ScaffoldState là một đối tượng chứa trạng thái hiện tại của Scaffold, và nó cung cấp các phương thức như openDrawer() hay closeDrawer(). Vấn đề là làm sao để có được ScaffoldState này từ bất kỳ đâu trong cây widget của bạn?

Có hai cách chính, và cách phổ biến nhất, 'chuẩn chỉ Harvard' nhất, là dùng GlobalKey<ScaffoldState>. Đây giống như việc bạn dán một cái 'mã số định danh' duy nhất lên cái Scaffold của mình, sau đó từ bất cứ đâu, bạn chỉ cần gọi cái mã số đó là có thể 'gọi điện' cho Scaffold và ra lệnh cho nó.

Cách thứ hai là dùng Scaffold.of(context). Cách này tiện hơn nếu bạn đang ở sâu bên trong cây widget và biết chắc chắn có một Scaffold ở phía trên. Tuy nhiên, nó yêu cầu context phải là con cháu của Scaffold đó, nếu không sẽ báo lỗi.

Hôm nay, chúng ta sẽ tập trung vào GlobalKey vì nó linh hoạt hơn và cho phép bạn điều khiển Drawer từ bất kỳ đâu, kể cả từ một widget không phải là con trực tiếp của Scaffold.

Illustration

Code Ví Dụ Minh Họa: Nắm Quyền Điều Khiển

Để minh họa, chúng ta sẽ tạo một ứng dụng Flutter đơn giản với một Drawer và các nút để mở/đóng nó bằng mã lệnh.

import 'package:flutter/material.dart';

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

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'DrawerController Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: const HomePage(),
    );
  }
}

class HomePage extends StatefulWidget {
  const HomePage({super.key});

  @override
  State<HomePage> createState() => _HomePageState();
}

class _HomePageState extends State<HomePage> {
  // Bước 1: Khai báo một GlobalKey cho ScaffoldState
  // Đây là "mã số định danh" duy nhất của Scaffold của chúng ta
  final GlobalKey<ScaffoldState> _scaffoldKey = GlobalKey<ScaffoldState>();

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      // Bước 2: Gán GlobalKey này vào Scaffold
      // Giờ thì Scaffold này đã có một "điều khiển từ xa"
      key: _scaffoldKey,
      appBar: AppBar(
        title: const Text('Điều khiển Ngăn kéo (Drawer)'),
        leading: IconButton(
          icon: const Icon(Icons.menu),
          onPressed: () {
            // Bước 3: Sử dụng GlobalKey để truy cập ScaffoldState
            // và gọi phương thức openDrawer()
            // Giống như bấm nút "mở hộc tủ" trên điều khiển từ xa
            if (_scaffoldKey.currentState != null && !_scaffoldKey.currentState!.isDrawerOpen) {
              _scaffoldKey.currentState!.openDrawer();
            } else if (_scaffoldKey.currentState != null && _scaffoldKey.currentState!.isDrawerOpen) {
              _scaffoldKey.currentState!.closeDrawer();
            }
          },
        ),
      ),
      drawer: Drawer(
        child: ListView(
          padding: EdgeInsets.zero,
          children: <Widget>[
            const DrawerHeader(
              decoration: BoxDecoration(
                color: Colors.blue,
              ),
              child: Text(
                'Menu Chính',
                style: TextStyle(
                  color: Colors.white,
                  fontSize: 24,
                ),
              ),
            ),
            ListTile(
              leading: const Icon(Icons.home),
              title: const Text('Trang Chủ'),
              onTap: () {
                // Đóng Drawer sau khi chọn
                _scaffoldKey.currentState?.closeDrawer();
                // Xử lý hành động Trang Chủ
              },
            ),
            ListTile(
              leading: const Icon(Icons.settings),
              title: const Text('Cài Đặt'),
              onTap: () {
                // Đóng Drawer sau khi chọn
                _scaffoldKey.currentState?.closeDrawer();
                // Xử lý hành động Cài Đặt
              },
            ),
          ],
        ),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            const Text(
              'Bấm nút Menu trên AppBar hoặc nút dưới đây để điều khiển Drawer.',
              textAlign: TextAlign.center,
            ),
            const SizedBox(height: 20),
            ElevatedButton(
              onPressed: () {
                // Bạn cũng có thể mở/đóng Drawer từ body
                // Kiểm tra trạng thái hiện tại để quyết định mở hay đóng
                if (_scaffoldKey.currentState != null) {
                  if (_scaffoldKey.currentState!.isDrawerOpen) {
                    _scaffoldKey.currentState!.closeDrawer();
                  } else {
                    _scaffoldKey.currentState!.openDrawer();
                  }
                }
              },
              child: const Text('Mở/Đóng Drawer'),
            ),
          ],
        ),
      ),
    );
  }
}

Mẹo (Best Practices) Để Ghi Nhớ và Ứng Dụng Thực Tế

  1. Khi nào dùng? Khi bạn muốn mở Drawer từ một nút bấm không phải nút mặc định trên AppBar, hoặc muốn tự động đóng Drawer sau một hành động nào đó (ví dụ, sau khi chọn một mục trong menu). Hoặc thậm chí tự động mở Drawer khi người dùng lần đầu vào ứng dụng để hướng dẫn.
  2. Tránh lạm dụng GlobalKey: GlobalKey mạnh mẽ nhưng cũng có thể gây khó hiểu nếu dùng quá nhiều. Hãy dùng nó khi thực sự cần truy cập vào trạng thái của một widget từ xa, không phải là con trực tiếp của nó.
  3. Kiểm tra currentState: Luôn luôn kiểm tra _scaffoldKey.currentState != null trước khi gọi các phương thức như openDrawer() hoặc closeDrawer(). Đôi khi, widget chưa được gắn vào cây widget hoặc đã bị hủy, việc truy cập currentState trực tiếp có thể gây lỗi.
  4. Dùng Scaffold.of(context) khi có thể: Nếu bạn đang ở trong một widget là con của Scaffold và chỉ cần truy cập ScaffoldState từ đó, Scaffold.of(context) sẽ gọn gàng và dễ đọc hơn GlobalKey. Ví dụ, trong onTap của một ListTile trong Drawer, bạn có thể dùng Navigator.pop(context) (thực chất là đóng Drawer) hoặc Scaffold.of(context).closeDrawer().

Ứng Dụng Thực Tế Các Website/Ứng Dụng Đã Ứng Dụng

Hầu hết các ứng dụng có Drawer đều sử dụng cơ chế này để điều khiển nó. Ví dụ điển hình:

  • Gmail: Khi bạn bấm vào biểu tượng menu ba gạch ở góc trên bên trái, Drawer sẽ mở ra. Đây chính là openDrawer() được gọi từ IconButton trên AppBar.
  • Facebook/LinkedIn: Các ứng dụng này thường có Drawer hoặc một dạng navigation panel tương tự, cho phép bạn truy cập các phần khác nhau của ứng dụng. Việc đóng Drawer sau khi chọn một mục là một ví dụ của closeDrawer().
  • Các ứng dụng quản lý tác vụ (Todoist, Trello): Thường có một menu bên cạnh để chuyển đổi giữa các dự án hoặc danh sách, và cơ chế điều khiển Drawer giúp quản lý trạng thái hiển thị của menu đó.

Thuộc Series: Flutter

Bài giảng này được tự động xuất bản ngẫu nhiên từ thư viện kiến thức. Đừng quên đón xem các Từ khoá Hướng Dẫn tiếp theo nhé!

#tech #cyberpunk #laravel
Chỉnh sửa bài viết

Bình luận (0)

Vui lòng Đăng Nhập để Bình luận

Hỗ trợ Markdown cơ bản
Nguyễn Văn A
1 ngày trước

Tính năng này đỉnh quá ad ơi, chờ mãi mới thấy một blog Tiếng Việt có UI/UX xịn như vầy!