0
0
Lập trình
Sơn Tùng Lê
Sơn Tùng Lê103931498422911686980

Kết nối hai widget trong Flutter bằng LayerLink

Đăng vào 2 tuần trước

• 6 phút đọc

Chủ đề:

KungFuTech

Kết nối hai widget trong Flutter bằng LayerLink

LayerLink là một khái niệm mạnh mẽ trong Flutter, cho phép bạn định vị chính xác các widget. Trong bài viết này, mình sẽ giải thích chi tiết về LayerLink và cách sử dụng nó để kết nối hai widget trong Flutter.

LayerLink tạo ra một kết nối giữa hai phần của cây widget có thể nằm trong các ngữ cảnh khác nhau (như giữa một widget và một overlay). Đây là một phần của hệ thống lớp kết hợp (composited layers) của Flutter.

Hãy tưởng tượng nó như một "sợi dây vô hình" kết nối hai widget:

Copy
CompositedTransformTarget (nguồn) ← LayerLink → CompositedTransformFollower (người theo)

Giả sử bạn có:

  1. Nút trong cây widget chính (nội dung cuộn)
  2. Menu popup trong Overlay (vị trí cố định trên màn hình)

Nếu không có LayerLink, khi bạn cuộn, nút sẽ di chuyển nhưng menu popup sẽ ở vị trí cố định trên màn hình.

dart Copy
class _InlineFilterPopupState extends State<InlineFilterPopup> {
  final LayerLink _layerLink = LayerLink(); // ← Tạo liên kết
  final GlobalKey _iconKey = GlobalKey();

  @override
  Widget build(BuildContext context) {
    return CompositedTransformTarget( // ← Widget nguồn
      link: _layerLink, // ← Kết nối liên kết
      child: IconButton(
        key: _iconKey,
        icon: const Icon(Icons.filter_list),
        onPressed: _toggleMenu,
      ),
    );
  }

  void _showMenu() {
    _overlayEntry = OverlayEntry(
      builder: (context) => Stack(
        children: [
          Positioned(
            child: CompositedTransformFollower( // ← Widget người theo
              link: _layerLink, // ← Kết nối liên kết giống nhau
              showWhenUnlinked: false,
              offset: Offset(0, 40), // Vị trí tương đối so với mục tiêu
              child: Material(
                // Nội dung menu popup của bạn
                child: _buildMenuContent(),
              ),
            ),
          ),
        ],
      ),
    );
  }
}

Những gì xảy ra khi cuộn

  1. Người dùng cuộn → Nút di chuyển trong khu vực cuộn
  2. CompositedTransformTarget phát hiện sự thay đổi vị trí
  3. LayerLink tự động cập nhật kết nối
  4. CompositedTransformFollower nhận dữ liệu vị trí mới
  5. Menu popup di chuyển để duy trì vị trí tương đối với nút

Ví dụ minh họa

Copy
Trước khi cuộn:
┌─────────────────────┐
│ [Nút]              │
│                     │
│ ┌─────────────────┐ │
│ │     Popup       │ │
│ └─────────────────┘ │
│                     │
└─────────────────────┘

Sau khi cuộn xuống:
┌─────────────────────┐
│                     │
│                     │
│ [Nút]              │
│ ┌─────────────────┐ │
│ │     Popup       │ │
│ └─────────────────┘ │
└─────────────────────┘

Các thuộc tính chính

showWhenUnlinked

  • true: Người theo hiển thị ngay cả khi mục tiêu không có trong cây
  • false: Người theo ẩn khi mục tiêu không khả dụng

offset

Vị trí tương đối từ mục tiêu:

Copy
offset: Offset(0, 40) // 0px bên phải, 40px xuống từ nút
offset: Offset(-20, 0) // 20px bên trái, cùng vị trí dọc
dart Copy
// Popup giữ vị trí cố định trên màn hình
Positioned(
  top: 100, // Vị trí cố định
  left: 100,
  child: PopupMenu(),
)
// Khi cuộn: Nút di chuyển, popup giữ nguyên ✓
dart Copy
// Popup di chuyển theo nút động
CompositedTransformFollower(
  link: _layerLink,
  offset: Offset(0, 40),
  child: PopupMenu(),
)
// Khi cuộn: Popup di chuyển cùng nút ✓

Ví dụ thực tế

  1. Nam châm: Giống như hai nam châm giữ kết nối ngay cả khi bạn di chuyển một cái
  2. Dây xích giữa cha và con: Như một người cha nắm tay con - khi cha di chuyển, con sẽ theo
  3. Thiết bị theo dõi GPS: Luôn biết vị trí hiện tại của mục tiêu

Khám phá kỹ thuật

Bên dưới, LayerLink sử dụng CompositedTransformTargetLayerCompositedTransformFollowerLayer:

dart Copy
// Triển khai nội bộ đơn giản
class CompositedTransformTarget extends SingleChildRenderObjectWidget {
  final LayerLink link;

  @override
  RenderObject createRenderObject(BuildContext context) {
    return RenderCompositedTransformTarget(
      link: link,
    );
  }
}

class CompositedTransformFollower extends SingleChildRenderObjectWidget {
  final LayerLink link;
  final Offset offset;

  @override
  RenderObject createRenderObject(BuildContext context) {
    return RenderCompositedTransformFollower(
      link: link,
      offset: offset,
    );
  }
}

Sử dụng LayerLink khi bạn cần:

  • ✅ Các popup theo nội dung cuộn
  • ✅ Các tooltip gắn liền với các phần tử di chuyển
  • ✅ Các menu dropdown tùy chỉnh trong các khu vực cuộn
  • ✅ Bất kỳ UI "gắn liền" nào cần di chuyển cùng với cha của nó

Không nên sử dụng khi:

  • ❌ Các overlay với vị trí cố định đơn giản
  • ❌ Các hộp thoại modal cần trung tâm trên màn hình
  • ❌ Các phần tử UI không nên di chuyển cùng nội dung

Tóm tắt

LayerLink thực chất là một "cáp định vị trực tiếp" mà:

  • Kết nối hai widget ở các phần khác nhau của cây
  • Tự động cập nhật vị trí trong quá trình thay đổi bố cục
  • Cho phép các mẫu UI nâng cao như popup theo dõi
  • Sử dụng hệ thống lớp ghép của Flutter để tối ưu hóa hiệu suất

Thực hành tốt nhất

  • Đảm bảo kiểm tra kỹ các thuộc tính của LayerLink để tránh các vấn đề không mong muốn.
  • Sử dụng LayerLink trong các tình huống cần thiết để tăng trải nghiệm người dùng.

Các cạm bẫy thường gặp

  • Sử dụng LayerLink trong các tình huống không cần thiết có thể gây ra hiệu suất kém.
  • Quên kiểm tra tính khả dụng của widget nguồn có thể dẫn đến lỗi.

Mẹo hiệu suất

  • Hạn chế sử dụng các widget nặng bên trong CompositedTransformFollower để giảm thiểu tải.
  • Nên thử nghiệm hiệu suất của ứng dụng sau khi tích hợp LayerLink để đảm bảo không có sự suy giảm.

Phần hỏi đáp

1. LayerLink có thể sử dụng trong các widget nào?
LayerLink có thể sử dụng trong bất kỳ widget nào cần kết nối với một widget khác trong cây.

2. Có cần thiết phải sử dụng LayerLink cho tất cả các popup?
Không, chỉ nên sử dụng khi cần duy trì vị trí tương đối giữa các widget.

3. LayerLink có tương thích với tất cả các phiên bản Flutter không?
Có, LayerLink hoạt động tốt trên tất cả các phiên bản Flutter hiện tại.

Kết luận

Hy vọng bài viết này đã giúp bạn hiểu rõ hơn về LayerLink và cách kết nối hai widget trong Flutter. Nếu bạn thấy bài viết hữu ích, hãy chia sẻ với cộng đồng và thử áp dụng LayerLink trong dự án của bạn nhé!

Gợi ý câu hỏi phỏng vấn
Không có dữ liệu

Không có dữ liệu

Bài viết được đề xuất
Bài viết cùng tác giả

Bình luận

Chưa có bình luận nào

Chưa có bình luận nào