
Các em cứ hình dung thế này, khi mình lướt TikTok, đọc tin nhắn hay soạn email, đôi lúc mình muốn bôi đen một đoạn chữ để copy, cắt, hay đơn giản là để "đánh dấu" đoạn đó quan trọng. Cái thao tác bôi đen ấy, chính là "text selection" đó. Và cái màu sắc của đoạn chữ được bôi đen, cái "cờ lê" nhỏ nhỏ để kéo giãn vùng chọn, đó chính là "giao diện" của text selection.
1. TextSelectionTheme là gì? Để làm gì? (Theo phong cách GenZ và Creyt)
TextSelectionTheme trong Flutter, nói một cách dễ hiểu, nó giống như "bộ trang phục" cho cái thao tác bôi đen chữ của em vậy. Mặc định, Flutter nó có một bộ đồ "công sở" màu xanh lam hoặc màu xám xám trông cũng được, nhưng đôi khi nó không hợp với "gu" thời trang tổng thể của app mình. Ví dụ, app em tông màu tím mộng mơ, mà bôi đen ra màu xanh chuối thì "out trình" quá đúng không? TextSelectionTheme sinh ra là để em có thể "tút tát" lại cái màu sắc của vùng chọn văn bản, màu của các "tay cầm" (selection handles) và con trỏ (cursor) sao cho nó "tone sur tone" với cái theme app của em. Nó giúp app của em trông chuyên nghiệp hơn, "đã mắt" hơn và "ăn nhập" hơn trong mọi ngóc ngách.
Nó giống như việc em đi mua đồ vậy. Thay vì mặc định hãng nào cũng chỉ có một màu áo sơ mi trắng, thì nay em có thể chọn màu hồng pastel, xanh mint, hay đen huyền bí tùy thích. TextSelectionTheme chính là cái "bảng màu" để em "design" lại trải nghiệm bôi đen của người dùng, biến một chi tiết nhỏ nhặt thành một điểm nhấn "có gu".
2. Code Ví Dụ Minh Hoạ Rõ Ràng, Chuẩn Kiến Thức
Nói suông thì ai cũng nói được, giờ anh em mình cùng "xắn tay áo" vào code một phát cho "nó máu"!
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: 'TextSelectionTheme Demo',
theme: ThemeData(
primarySwatch: Colors.deepPurple, // Example primary color
// Global text selection theme for the entire app
textSelectionTheme: const TextSelectionThemeData(
selectionColor: Colors.deepPurpleAccent, // Màu vùng chọn
cursorColor: Colors.purple, // Màu con trỏ
selectionHandleColor: Colors.purpleAccent, // Màu tay cầm kéo
),
),
home: const MyHomePage(),
);
}
}
class MyHomePage extends StatefulWidget {
const MyHomePage({super.key});
@override
State<MyHomePage> createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
final TextEditingController _controller = TextEditingController();
@override
void dispose() {
_controller.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('TextSelectionTheme by Creyt'),
backgroundColor: Theme.of(context).primaryColor,
),
body: Padding(
padding: const EdgeInsets.all(16.0),
child: Column(
children: [
const Text(
'Thử bôi đen đoạn văn bản này xem có gì "khác bọt" không nhé, các đệ tử!',
style: TextStyle(fontSize: 18),
),
const SizedBox(height: 20),
TextField(
controller: _controller,
decoration: const InputDecoration(
labelText: 'Nhập gì đó vào đây để thử bôi đen...',
border: OutlineInputBorder(),
),
maxLines: 5,
),
const SizedBox(height: 20),
// You can also override the theme locally if needed
TextSelectionTheme(
data: const TextSelectionThemeData(
selectionColor: Colors.redAccent, // Override locally
cursorColor: Colors.red,
selectionHandleColor: Colors.orange,
),
child: const SelectableText(
'Đây là một đoạn văn bản có thể chọn được. Hãy thử bôi đen đoạn này để thấy sự khác biệt của TextSelectionTheme cục bộ nhé!',
style: TextStyle(fontSize: 16),
),
),
],
),
),
);
}
}

3. Giải thích Code "Tận Răng":
Trong ví dụ trên, anh em mình có thể thấy rõ ràng cách TextSelectionTheme hoạt động.
TextSelectionThemeData: "Bảng điều khiển" màu sắc
Đây chính là "bảng điều khiển" để em tùy chỉnh các màu sắc. Nó có các thuộc tính chính:
selectionColor: Màu của cái vùng chữ được bôi đen. Giống như màu của bút highlight của em vậy.cursorColor: Màu của con trỏ nhấp nháy khi em gõ chữ. Cái "chấm nhỏ" báo hiệu em đang gõ ở đâu đó.selectionHandleColor: Màu của hai cái "tay cầm" nhỏ xíu ở hai đầu vùng chọn, dùng để kéo giãn vùng chọn. Hai cái "cờ lê" thần thánh để em "căn chỉnh" vùng bôi đen đó.
Đặt TextSelectionTheme ở đâu?
- Cách "chuẩn bài" nhất là đặt nó trong
ThemeDatacủaMaterialApp(hoặcCupertinoApp). Khi đó, toàn bộ cácTextField,TextFormField,SelectableTexttrong app của em sẽ "thừa hưởng" cái theme này. Đây là cách để "đồng bộ" trải nghiệm người dùng toàn cục. - Tuy nhiên, nếu em muốn "phá cách" một chút, chỉ một vài chỗ đặc biệt có màu bôi đen khác biệt, em có thể dùng widget
TextSelectionThemeđể bọc riêng từng widget cụ thể. Như trong ví dụ, anh đã bọcSelectableTextvới mộtTextSelectionThemekhác để các em thấy rõ sự "linh hoạt" của nó.
4. Mẹo (Best Practices) Để Ghi Nhớ Hoặc Dùng Thực Tế:
- "Tone sur tone" là chân ái: Luôn cố gắng chọn màu
selectionColor,cursorColor,selectionHandleColorsao cho nó hợp vớiprimaryColorhoặcaccentColorcủa app em. Đừng để nó "lạc quẻ" như mặc áo vest với quần đùi đi họp nhé. Sự nhất quán tạo nên vẻ đẹp chuyên nghiệp. - Đừng quá "lòe loẹt": Màu sắc nổi bật là tốt, nhưng đừng quá chói mắt hay quá tương phản khiến người dùng khó chịu. Mục đích là để dễ nhìn, chứ không phải để "dọa" người dùng.
- Kiểm tra trên các nền tảng (Android/iOS): Đôi khi, các màu này có thể hiển thị hơi khác một chút giữa Android và iOS. Hãy test kỹ để đảm bảo trải nghiệm đồng nhất hoặc có điều chỉnh phù hợp.
- Sử dụng
Theme.of(context): Khi cần truy cập các màu đã định nghĩa trong theme, hãy dùngTheme.of(context).textSelectionTheme.selectionColorđể đảm bảo em luôn lấy được màu sắc chính xác theo theme hiện tại, kể cả khi theme đó được override cục bộ.
5. Ví Dụ Thực Tế Các Ứng Dụng/Website Đã Ứng Dụng (hoặc tương tự):
Các em có thấy khi dùng ứng dụng Zalo, Messenger, hay thậm chí là Google Docs trên điện thoại không? Khi em bôi đen một đoạn chat hay một đoạn văn bản, cái màu highlight nó sẽ không phải là màu xanh mặc định của hệ điều hành đâu. Nó thường sẽ là màu xanh lá của Zalo, màu xanh dương của Messenger, hay màu xanh của Google Drive/Docs. Đó chính là cách họ "cá nhân hóa" trải nghiệm người dùng, làm cho app của họ có "bản sắc" riêng, kể cả từ những chi tiết nhỏ nhất như Text Selection.
Các trình duyệt web hiện đại cũng cho phép các nhà phát triển CSS tùy chỉnh ::selection để thay đổi màu bôi đen trên website. Về bản chất, nó cũng là một cách để đồng bộ UI/UX đấy.
6. Thử Nghiệm Đã Từng Và Hướng Dẫn Nên Dùng Cho Case Nào:
Creyt đã từng "vật lộn" thế nào:
Ngày xưa, khi Flutter mới ra, anh Creyt cũng từng đau đầu với mấy cái màu mặc định này lắm. App làm tông đen-vàng mà bôi đen ra cái màu xanh lè của Android, nhìn nó "phèn" hết sức. Sau này mới biết đến TextSelectionTheme, đúng là "chân ái" cứu rỗi cuộc đời dev của anh em mình.
Nên dùng cho case nào?
- App có branding riêng: Đây là lúc em cần
TextSelectionThemenhất. Khi app em có một bộ nhận diện thương hiệu rõ ràng (màu sắc, font chữ), thì mọi chi tiết nhỏ nhất cũng nên "thở" ra cái branding đó. - App có Dark Mode/Light Mode: Cực kỳ quan trọng! Màu bôi đen mặc định có thể ổn với Light Mode, nhưng khi chuyển sang Dark Mode, nó có thể trở nên khó nhìn hoặc chói mắt. Em cần tùy chỉnh
TextSelectionThemeriêng cho từng chế độ để đảm bảo trải nghiệm tốt nhất. - Cải thiện khả năng đọc: Trong một số trường hợp, màu bôi đen mặc định có thể không đủ tương phản với màu nền của text. Việc tùy chỉnh giúp tăng cường khả năng đọc, đặc biệt với người dùng có thị lực kém.
- Tạo điểm nhấn đặc biệt: Dù ít gặp hơn, nhưng đôi khi em muốn một vùng văn bản nào đó có màu bôi đen đặc biệt để thu hút sự chú ý. Lúc này, dùng
TextSelectionThemecục bộ là một ý hay.
Đấy, các em thấy không? Một chi tiết nhỏ như TextSelectionTheme thôi, nhưng nếu biết cách dùng, nó có thể nâng tầm app của em lên một đẳng cấp khác, từ một app "tầm thường" thành một sản phẩm "có gu", "có tâm". Hãy nhớ, sự tinh tế nằm ở những chi tiết nhỏ nhất!
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é!