EditableText: "Cái ruột" của mọi khung nhập liệu trong Flutter
Flutter

EditableText: "Cái ruột" của mọi khung nhập liệu trong Flutter

Author

Admin System

@root

Ngày xuất bản

18 Mar, 2026

Lượt xem

22 Lượt

"EditableText"

Chào mừng các "đệ tử" đến với bài học hôm nay! Giảng viên Creyt sẽ cùng các bạn "mổ xẻ" một khái niệm mà nhiều khi chúng ta bỏ qua, nhưng nó lại là "trái tim" của mọi thứ liên quan đến nhập liệu văn bản trong Flutter: EditableText.

1. EditableText là gì và để làm gì? – "Cái ruột" trần trụi

Các bạn cứ hình dung thế này: Nếu TextField là một chiếc xe hơi đã hoàn thiện, bóng loáng, có đầy đủ ghế da, điều hòa mát lạnh, thì EditableText chính là cái khung sườn (chassis) trần trụi, khối động cơ và hệ thống lái cơ bản của chiếc xe đó. Nó là widget cấp thấp nhất trong Flutter chịu trách nhiệm xử lý việc nhập liệu, chọn văn bản, và di chuyển con trỏ mà không hề có bất kỳ trang trí (decoration) hay hiệu ứng hình ảnh mặc định nào.

Mục đích sinh ra của nó? Đơn giản là để bạn có toàn quyền kiểm soát! Khi bạn cần một trường nhập liệu có giao diện "độc lạ Bình Dương", hoặc một hành vi tương tác mà TextField không thể đáp ứng được (ví dụ, một trình soạn thảo code, một editor rich-text với đủ thứ định dạng), thì EditableText chính là "công cụ" bạn cần để "đẽo gọt" từ đầu.

2. Tại sao không dùng TextField luôn cho rồi?

Câu hỏi hay! TextField là "người anh em" phổ biến hơn nhiều, và trong 99% trường hợp, bạn nên dùng TextField. Nó đã "đóng gói" sẵn EditableText bên trong và thêm vào hàng tá tiện ích như InputDecoration (viền, label, hint text, icon), errorText, padding, scrollPhysics... Nó giống như việc bạn mua một căn nhà đã xây sẵn, đầy đủ tiện nghi, chỉ việc dọn vào ở.

Nhưng đôi khi, bạn không muốn căn nhà xây sẵn đó. Bạn muốn tự mình "thiết kế kiến trúc" từng viên gạch, từng đường dây điện để tạo ra một "kiệt tác" có một không hai. Khi đó, EditableText là "viên gạch" cơ bản nhất để bạn bắt đầu xây dựng.

Illustration

3. Code Ví Dụ Minh Hoạ – "Mổ xẻ" cái ruột

Để các bạn dễ hình dung, chúng ta hãy cùng xem EditableText hoạt động như thế nào. Các bạn sẽ thấy nó "trần trụi" đến mức nào!

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: 'EditableText Demo',
      theme: ThemeData(primarySwatch: Colors.blue),
      home: const EditableTextScreen(),
    );
  }
}

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

  @override
  State<EditableTextScreen> createState() => _EditableTextScreenState();
}

class _EditableTextScreenState extends State<EditableTextScreen> {
  // 1. Controller: "Người quản lý" nội dung văn bản
  late final TextEditingController _textController;
  // 2. FocusNode: "Người gác cổng" cho trạng thái tập trung (focus)
  late final FocusNode _focusNode;

  @override
  void initState() {
    super.initState();
    _textController = TextEditingController(text: 'Hello Giảng viên Creyt!');
    _focusNode = FocusNode();
  }

  @override
  void dispose() {
    _textController.dispose(); // Luôn nhớ "dọn dẹp" controller
    _focusNode.dispose();      // Luôn nhớ "dọn dẹp" focus node
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('EditableText Demo của Creyt'),
      ),
      body: Center(
        child: Padding(
          padding: const EdgeInsets.all(20.0),
          child: Container(
            padding: const EdgeInsets.all(12.0),
            decoration: BoxDecoration(
              color: Colors.grey[200],
              border: Border.all(color: Colors.blueAccent, width: 2),
              borderRadius: BorderRadius.circular(8.0),
            ),
            child: EditableText(
              controller: _textController,
              focusNode: _focusNode,
              style: const TextStyle(
                fontSize: 20,
                color: Colors.black,
                fontWeight: FontWeight.bold,
              ),
              cursorColor: Colors.red, // Màu con trỏ
              backgroundCursorColor: Colors.blue, // Màu con trỏ khi không focus (ít dùng)
              selectionColor: Colors.lightBlue.withOpacity(0.5), // Màu vùng chọn
              readOnly: false, // Có cho phép sửa đổi không?
              maxLines: 1, // Số dòng tối đa
              keyboardType: TextInputType.text,
              autofocus: true, // Tự động focus khi widget được tạo
              onChanged: (text) {
                // Bất cứ khi nào văn bản thay đổi
                print('Văn bản đã thay đổi: $text');
              },
              onSubmitted: (text) {
                // Khi người dùng nhấn Enter/Done
                print('Người dùng đã submit: $text');
                _focusNode.unfocus(); // Bỏ focus sau khi submit
              },
            ),
          ),
        ),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: () {
          // Thao tác với văn bản từ bên ngoài
          _textController.text = 'Creyt đã thay đổi nội dung!';
          _focusNode.requestFocus(); // Yêu cầu focus lại
        },
        child: const Icon(Icons.edit),
      ),
    );
  }
}

Trong ví dụ trên, các bạn thấy EditableText chỉ cung cấp những thứ cốt lõi nhất: controller, focusNode, style, cursorColor, selectionColor và các callback như onChanged, onSubmitted. Mọi thứ về "khung viền", "nền", "padding" đều phải do bạn tự "đắp" bên ngoài bằng các widget như Container, Padding, BoxDecoration.

4. Mẹo (Best Practices) từ Giảng viên Creyt – "Bí kíp" để không "đi vào vết xe đổ"

  • "Đừng đụng vào nó nếu không cần!": Đây là quy tắc vàng! Luôn bắt đầu với TextField. Chỉ khi nào bạn gặp phải một yêu cầu UI/UX quá đặc biệt mà TextField không thể đáp ứng, hoặc bạn cần tối ưu hiệu năng cực đoan cho một lượng lớn input, thì mới nghĩ đến EditableText. Nó giống như việc bạn chỉ nên tự xây nhà khi bạn là kiến trúc sư và thợ xây lành nghề, chứ không phải chỉ vì muốn "thử cho biết".

  • Quản lý TextEditingControllerFocusNode: Hai "anh bạn" này cực kỳ quan trọng và hay bị quên. Luôn nhớ khai báo chúng bằng late final hoặc khởi tạo trong initStatephải dispose() chúng trong phương thức dispose() của StatefulWidget. Nếu không, chúng sẽ gây ra rò rỉ bộ nhớ (memory leak), làm ứng dụng của bạn "nặng nề" và "chậm chạp" dần theo thời gian. Đây là "nghiệp vụ" cơ bản mà một lập trình viên "có tâm" phải làm.

  • Tùy biến "đến tận chân răng": EditableText cho phép bạn kiểm soát màu con trỏ (cursorColor), màu vùng chọn (selectionColor), và thậm chí cả màu con trỏ khi không focus (backgroundCursorColor). Tận dụng điều này để tạo ra những trải nghiệm nhập liệu độc đáo, phù hợp với branding của ứng dụng bạn.

  • Hiệu năng (Performance): Vì EditableText ít "phụ kiện" hơn TextField, trong những trường hợp cực đoan (ví dụ: một màn hình có hàng trăm ô nhập liệu nhỏ), nó có thể mang lại hiệu năng tốt hơn một chút. Tuy nhiên, đừng "mù quáng" mà hãy luôn dùng công cụ Profile của Flutter để kiểm tra trước khi quyết định "hy sinh" sự tiện lợi của TextField để đổi lấy EditableText.

5. Ứng dụng thực tế – "EditableText" đang ở đâu ngoài kia?

"Thầy ơi, có ai dùng cái này không hay chỉ mình em học?" – Chắc chắn rồi! EditableText là nền tảng cho nhiều ứng dụng phức tạp mà bạn thấy hàng ngày:

  • Trình soạn thảo mã nguồn (Code Editors): Các ứng dụng như VS Code (phiên bản web), hoặc các editor trên di động thường cần hiển thị cú pháp highlight, đánh số dòng, và các tính năng chỉnh sửa phức tạp. EditableText cung cấp cơ chế nhập liệu cơ bản, sau đó các lớp logic khác sẽ "vẽ" thêm các hiệu ứng đó lên trên.

  • Trình soạn thảo văn bản đa định dạng (Rich Text Editors): Tưởng tượng các ứng dụng như Google Docs, Notion, hay thậm chí là phần soạn thảo tin nhắn trên các mạng xã hội cho phép bạn in đậm, in nghiêng, chèn link... EditableText xử lý phần nhập liệu thô, còn việc áp dụng các định dạng là do các lớp cao hơn quản lý.

  • Các thanh tìm kiếm tùy chỉnh (Custom Search Bars): Đôi khi, một thanh tìm kiếm không chỉ đơn thuần là nhập text. Nó có thể có gợi ý đặc biệt, hiệu ứng chuyển động riêng, hoặc tích hợp trực tiếp vào một phần của UI game. EditableText là "viên gạch" lý tưởng để xây dựng những thanh tìm kiếm như vậy từ đầu.

  • Ứng dụng game hoặc tương tác cao: Trong một số game, bạn có thể cần một ô nhập tên người chơi hoặc mật khẩu mà nó phải hòa quyện hoàn hảo vào phong cách đồ họa của game, không hề có một chút "mùi" của widget hệ thống. EditableText là lựa chọn tuyệt vời cho các tình huống này.

Vậy là các bạn đã "thấm" được phần nào về EditableText rồi chứ? Hãy nhớ, nó là một "công cụ" mạnh mẽ, nhưng hãy sử dụng nó một cách thông minh và có mục đích. Đừng bao giờ ngại "mổ xẻ" các khái niệm cơ bản để hiểu sâu hơn về cách Flutter vận hành nhé! Hẹn gặp lại trong bài học tiếp theo!

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!