
Chào các bạn gen Z năng động, lại là anh Creyt đây! Hôm nay, chúng ta sẽ "bóc tách" một em widget cực kỳ thú vị trong Flutter, giúp app của tụi mình flex được nhiều tính năng hơn mà không cần drama: đó là ToggleButtons.
Cứ tưởng tượng thế này: Bạn đang ở trong một quán cà phê "chill" hết nấc, và muốn chọn loại sữa cho ly trà sữa của mình. Bình thường thì phải bấm từng cái nút chọn: 'Sữa tươi', 'Sữa đặc', 'Không sữa'… rồi lại phải 'unselect' cái cũ nếu muốn đổi. Mất vibe kinh khủng!
ToggleButtons sinh ra để 'auto-chill' vụ này. Nó giống như một nhóm bạn thân, mỗi đứa đại diện cho một lựa chọn. Bạn có thể chọn một đứa, hai đứa, hoặc cả lũ tùy theo rules. Cứ bấm là nó 'toggle' trạng thái: đang chọn thì bỏ chọn, đang không chọn thì chọn. Đơn giản, tiện lợi, và quan trọng là… nhìn nó 'pro' hơn hẳn mấy cái nút bấm đơn lẻ.
Tóm lại, ToggleButtons là một widget trong Flutter cho phép bạn hiển thị một nhóm các nút có thể được bật hoặc tắt (toggle). Nó cực kỳ hữu ích khi bạn muốn người dùng chọn một hoặc nhiều tùy chọn từ một danh sách cố định mà các tùy chọn đó có liên quan mật thiết với nhau.
ToggleButtons trong Flutter: "Chìa Khóa" Quyết Định Vibe
Trong Flutter, ToggleButtons là một widget được thiết kế để hiển thị một hàng các nút liên quan. Mỗi nút có thể được chọn (selected) hoặc không được chọn (unselected). Điểm đặc biệt của nó là bạn phải tự quản lý trạng thái chọn cho từng nút.
Các thuộc tính quan trọng nhất mà bạn cần nắm để 'flex' em nó:
children: Một list cácWidget(thường làTexthoặcIcon) sẽ hiển thị bên trong mỗi nút. Đây chính là 'tụi bạn thân' mà anh Creyt nói đó.isSelected: Một list cácboolcó độ dài tương ứng vớichildren. Mỗiboolsẽ cho Flutter biết nút tương ứng có đang được chọn hay không. Đây là 'trạng thái' của từng đứa bạn.onPressed: Một callback function được gọi khi một nút được nhấn. Trong hàm này, bạn sẽ cập nhật trạng tháiisSelectedcủa mình. Đây là 'hành động' khi bạn 'chạm' vào đứa bạn đó.color,selectedColor,fillColor,splashColor,borderColor,selectedBorderColor,borderRadius: Các thuộc tính để 'tút tát' cho em nó đẹp trai, đẹp gái hơn.
Code Ví Dụ Minh Họa: Chọn Phong Cách Âm Nhạc
Giờ thì, lý thuyết suông mãi cũng chán. Chúng ta sẽ cùng nhau viết một ví dụ 'sương sương' để thấy ToggleButtons hoạt động như thế nào trong thực tế. Chúng ta sẽ tạo một nhóm nút chọn 'Phong cách âm nhạc yêu thích' nhé!
4 Lượt xem
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: 'Creyt\'s ToggleButtons Demo',
theme: ThemeData(
primarySwatch: Colors.blueGrey,
visualDensity: VisualDensity.adaptivePlatformDensity,
),
home: const MyHomePage(),
);
}
}
class MyHomePage extends StatefulWidget {
const MyHomePage({super.key});
@override
State<MyHomePage> createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
// Đây là "trạng thái" của từng nút.
// Mặc định, tất cả đều false (không được chọn).
List<bool> _selections = List.generate(3, (_) => false);
final List<String> _musicStyles = ['Pop', 'Rock', 'EDM'];
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Chọn Phong Cách Âm Nhạc (ToggleButtons)'),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
const Text(
'Chọn phong cách âm nhạc yêu thích của bạn:',
style: TextStyle(fontSize: 18),
),
const SizedBox(height: 20),
ToggleButtons(
// List các widget con (thường là Text hoặc Icon)
children: _musicStyles.map((style) => Padding(
padding: const EdgeInsets.symmetric(horizontal: 16.0),
child: Text(style),
)).toList(),
// Trạng thái hiện tại của từng nút
isSelected: _selections,
// Hàm được gọi khi một nút được nhấn
onPressed: (int index) {
// Rất quan trọng: Phải gọi setState để cập nhật UI
setState(() {
// Đảo ngược trạng thái của nút được nhấn
_selections[index] = !_selections[index];
});
// In ra các lựa chọn hiện tại để debug/kiểm tra
print('Các lựa chọn hiện tại: ${ _selections.map((e) => e ? 'Selected' : 'Unselected').toList()}');
},
// Tùy chỉnh giao diện (styling)
color: Colors.grey[600], // Màu chữ/icon khi không chọn
selectedColor: Colors.white, // Màu chữ/icon khi được chọn
fillColor: Colors.blueGrey, // Màu nền khi được chọn
borderColor: Colors.blueGrey.shade200, // Màu viền
selectedBorderColor: Colors.blueGrey.shade800, // Màu viền khi được chọn
borderRadius: BorderRadius.circular(8), // Bo góc
borderWidth: 2,
),
const SizedBox(height: 30),
Text(
'Bạn đã chọn: ${
_musicStyles
.asMap()
.entries
.where((entry) => _selections[entry.key])
.map((entry) => entry.value)
.join(', ')
}',
style: const TextStyle(fontSize: 16, fontWeight: FontWeight.bold),
),
],
),
),
);
}
}

Mẹo Hay và Best Practices từ Giảng Viên Creyt
Thấy chưa, code Flutter nó 'flex' dễ hiểu vậy đó. Giờ thì, nghe anh Creyt 'deep dive' thêm vài mẹo để tụi mình không bị 'nghiệp quật' khi dùng ToggleButtons nhé:
- Quản lý State là linh hồn:
ToggleButtonslà một widget "stateful" (có trạng thái). Điều này có nghĩa là bạn PHẢI quản lý trạng tháiisSelectedcủa nó bên ngoài widget, thường là trong mộtStatefulWidgetvà cập nhật nó bằngsetState(). Nếu không, nút sẽ không thay đổi trạng thái khi bạn nhấn vào đâu. Nó giống như bạn bấm nút mà máy không nhận lệnh vậy, 'phèn' lắm! - Độ dài
isSelectedvàchildrenphải khớp: Đây là lỗi sơ đẳng mà nhiều bạn hay mắc phải. Số lượngbooltrongisSelectedPHẢI BẰNG số lượngWidgettrongchildren. Nếu không, Flutter sẽ "giận dỗi" và ném lỗi ngay. Cứ tưởng tượng bạn có 3 đứa bạn mà chỉ có 2 cái ghế để ngồi vậy. - Styling đồng bộ: Dùng các thuộc tính như
color,selectedColor,fillColormột cách nhất quán để tạo ra một UI "hợp gu", dễ nhìn. Đừng để mỗi nút một màu, nhìn nó 'ô dề' lắm. - Accessibility (Khả năng tiếp cận): Luôn đảm bảo các nút của bạn có đủ tương phản màu sắc và kích thước dễ bấm. Người dùng có thị lực kém hoặc gặp khó khăn về vận động cũng cần được 'chill' khi dùng app của bạn chứ.
- Khi nào thì chọn 1, khi nào thì chọn nhiều?
- Chọn 1 (Single Selection): Nếu chỉ muốn người dùng chọn DUY NHẤT một tùy chọn (ví dụ: chọn giới tính, chọn đơn vị tiền tệ chính), thì trong hàm
onPressed, bạn phải reset tất cả các giá trị trong_selectionsvềfalse, rồi mới set_selections[index]thànhtrue. - Chọn nhiều (Multiple Selection): Như ví dụ trên, chỉ cần đảo ngược trạng thái của nút được nhấn (
_selections[index] = !_selections[index]).
- Chọn 1 (Single Selection): Nếu chỉ muốn người dùng chọn DUY NHẤT một tùy chọn (ví dụ: chọn giới tính, chọn đơn vị tiền tệ chính), thì trong hàm
- Ghi nhớ: Cứ nhớ ToggleButtons là "nhóm bạn thân" nhiều lựa chọn. Mỗi đứa bạn có một "trạng thái" (isSelected) và khi bạn "tương tác" (onPressed) với đứa nào thì đứa đó sẽ "thay đổi mood" (setState).
Ứng Dụng Thực Tế: "Flex" Khắp Nơi!
Vậy thì, ngoài việc chọn nhạc, ToggleButtons còn được các app 'xịn xò' dùng ở đâu nữa?
- App chỉnh sửa ảnh/video: Chọn các bộ lọc (filters) khác nhau (ví dụ: "Vintage", "B&W", "Sepia"). Bạn có thể chọn nhiều bộ lọc để kết hợp.
- Ứng dụng thời tiết: Chọn đơn vị nhiệt độ (C/F), đơn vị gió (km/h, m/s). Thường là chọn 1.
- App mua sắm/tìm kiếm: Bộ lọc sản phẩm (ví dụ: "Size S", "Màu Đỏ", "Còn hàng"). Người dùng có thể chọn nhiều tiêu chí.
- Trình soạn thảo văn bản: Các nút định dạng văn bản như B (Bold), I (Italic), U (Underline), căn lề (Trái, Giữa, Phải). Đây là một ví dụ kinh điển của ToggleButtons, mỗi nút có thể bật/tắt độc lập.
- Cài đặt: Bật/tắt các tùy chọn riêng lẻ hoặc nhóm các tùy chọn liên quan.
Nên Dùng Khi Nào và "Né" Khi Nào?
Anh Creyt đã từng 'thử nghiệm' nhiều với ToggleButtons và nhận ra nó thực sự là 'cứu cánh' trong các trường hợp sau:
- Khi bạn có một nhóm lựa chọn nhỏ (khoảng 2-5 tùy chọn) và các tùy chọn đó có liên quan chặt chẽ đến nhau. Ví dụ: chọn chế độ xem (Grid/List), chọn đơn vị đo lường, chọn ngôn ngữ hiển thị (nếu chỉ có 2-3 ngôn ngữ chính).
- Khi bạn muốn người dùng dễ dàng nhìn thấy tất cả các tùy chọn cùng một lúc mà không cần mở một menu dropdown. Nó giúp giảm số lần click và tăng trải nghiệm người dùng.
- Khi bạn cần một UI rõ ràng, trực quan cho các tùy chọn bật/tắt.
Không nên dùng khi nào?
- Khi có quá nhiều tùy chọn (hơn 5-6): Lúc này ToggleButtons sẽ chiếm quá nhiều không gian trên màn hình và trông rất 'rối'. Hãy nghĩ đến
DropdownButton,RadioListTile(nếu chọn 1) hoặcCheckboxListTile(nếu chọn nhiều) thay thế. - Khi các tùy chọn không liên quan đến nhau: Mỗi tùy chọn nên là một
SwitchhoặcCheckboxriêng lẻ. - Khi bạn cần chọn từ một danh sách động: ToggleButtons hoạt động tốt nhất với danh sách cố định.
Vậy đó, các bạn gen Z! Hi vọng qua bài giảng 'sương sương' này, tụi mình đã 'nắm vibe' được ToggleButtons trong Flutter rồi nhé. Cứ thực hành nhiều vào, có gì 'bí' thì cứ 'ới' anh Creyt. Chúc các bạn code 'mượt' như lụa!
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é!