Cách sử dụng ảnh 9-patch trong Flutter

13 tháng 1, 2025

Ảnh 9-patch (Nine-patch image) là một loại ảnh PNG đặc biệt, cho phép nhà phát triển giữ cho một số vùng của ảnh không bị biến dạng khi kéo giãn ảnh, từ đó tránh được tình trạng méo mó ảnh. Điều này rất hữu ích khi tạo các thành phần UI có thể co giãn (ví dụ: nền nút, thanh tiến trình, v.v.). Mặc dù Flutter không trực tiếp hỗ trợ định dạng gốc của ảnh 9-patch, chúng ta có thể sử dụng một số kỹ thuật để đạt được hiệu ứng tương tự.

Tạo ảnh 9-patch bằng 9 Patch Editor

Đầu tiên, bạn cần chuẩn bị một ảnh PNG. Sau đó, sử dụng công cụ 9 Patch Editor để tạo ảnh 9-patch của bạn. Công cụ này cho phép bạn chỉ định vùng có thể kéo giãn và vùng nội dung của ảnh. Các bước thực hiện cụ thể như sau:

  1. Truy cập trang web 9 Patch Editor.
  2. Tải lên ảnh PNG của bạn.
  3. Sử dụng trình chỉnh sửa của công cụ, chọn vùng có thể kéo giãn của ảnh (kéo mép trái và mép trên của ảnh).
  4. Chọn vùng nội dung của ảnh (kéo mép phải và mép dưới của ảnh, những vùng này sẽ không thay đổi khi kéo giãn).
  5. Tải xuống ảnh 9-patch đã tạo (hãy tải xuống các ảnh khác nhau tùy theo phương án của bạn).

Sử dụng ảnh 9-patch trong Flutter

Flutter không có cơ chế tải ảnh 9-patch trực tiếp. Chúng ta cần sử dụng các thư viện bên thứ ba hoặc sử dụng thuộc tính Image.centerSlice tích hợp sẵn của Flutter để mô phỏng hiệu ứng ảnh 9-patch.

Phương pháp 1: Sử dụng thư viện bên thứ ba

Hiện nay có một số thư viện bên thứ ba của Flutter có thể giúp bạn tải và hiển thị ảnh 9-patch, ví dụ như ninepatch_imagenine_patch.

Sử dụng thư viện ninepatch_image

Bạn cần thêm dependency vào file pubspec.yaml:

dependencies:
  ninepatch_image: ^0.0.4

Đặt ảnh PNG vào thư mục assets của dự án Flutter và khai báo trong file pubspec.yaml:

flutter:
  assets:
    - assets/my_image.9.png

Sau đó, bạn có thể sử dụng widget NinePatchImage để hiển thị ảnh 9-patch của mình:

NinePatchImage(
  imageProvider: AssetImage("assets/my_image.9.png"),
  child: Text( "Lorem Ipsum is simply dummy text of the printing "))

Để biết chi tiết cách sử dụng, vui lòng tham khảo tài liệu của ninepatch_image.

Sử dụng thư viện nine_patch

Bạn cần thêm dependency vào file pubspec.yaml:

dependencies:
  nine_patch: ^1.0.0

Bạn cần tạo một file JSON chứa thông tin ảnh 9-patch trong thư mục assets và đặt ảnh gốc vào thư mục assets.

assets/TextBox_Side.9.jsonassets/2.0x/TextBox_Side.png
(không có viền 1 pixel)
{
  "stretch": {
    "x": 118,
    "y": 40,
    "width": 121,
    "height": 60
  },
  "contents": {
    "x": 19,
    "y": 18,
    "width": 248,
    "height": 101
  },
  "dimensions": {
    "x": 285,
    "y": 167
  },
  "name": "TextBox_Side.png",
  "scale": 2
}

Ảnh ví dụ 9-patch có tên TextBox_Side.png

stretch là vùng có thể kéo giãn của ảnh, contents là vùng nội dung của ảnh, dimensions là kích thước của ảnh. Bạn có thể xem thông tin này trong công cụ 9 Patch Editor hoặc sử dụng công cụ nine_patcher để tạo thông tin này.

Sau đó, bạn có thể sử dụng widget NinePatchImage để hiển thị ảnh 9-patch của mình:

import 'package:nine_patch/nine_patch.dart';

...

// Tạo một widget NinePatchImage mới
NinePatchImage.fromAssetMetadata(
    name: "my_image.9.json",
)

Hãy nhớ thay thế assets/my_image.9.json bằng đường dẫn file JSON ảnh 9-patch của bạn.

Để biết chi tiết cách sử dụng, vui lòng tham khảo tài liệu của nine_patch.

Phương pháp 2: Sử dụng Image.centerSlice

Nếu bạn không muốn sử dụng thư viện bên thứ ba, bạn có thể sử dụng thuộc tính Image.centerSlice tích hợp sẵn của Flutter để mô phỏng hiệu ứng ảnh 9-patch. Bạn cần chỉ định thủ công vùng có thể kéo giãn của ảnh:

Image.asset(
  'assets/my_image.png',
  width: 200,
  height: 100,
  centerSlice: Rect.fromLTWH(20, 20, 160, 60), // Chỉ định thủ công vùng có thể kéo giãn
),

Lưu ý: Ảnh phải sử dụng ảnh gốc hoặc ảnh đã được biên dịch.

Bạn cần điều chỉnh giá trị của thuộc tính centerSlice thủ công dựa trên ảnh của bạn. Bạn có thể xem thông tin này trong công cụ 9 Patch Editor.

Tổng kết

Mặc dù Flutter không trực tiếp hỗ trợ ảnh 9-patch, nhưng chúng ta có thể đạt được hiệu quả tương tự bằng cách sử dụng thư viện bên thứ ba hoặc thuộc tính Image.centerSlice. Nên sử dụng thư viện ninepatch_image vì nó dễ sử dụng hơn. Nếu bạn cần các tính năng linh hoạt và mạnh mẽ hơn, bạn có thể cân nhắc sử dụng nine_patch. Nếu bạn không muốn thêm thư viện bên thứ ba, bạn có thể sử dụng phương pháp Image.centerSlice, nhưng nó có các tính năng hạn chế và bạn cần chỉ định vùng có thể kéo giãn thủ công. Việc lựa chọn phương pháp nào phụ thuộc vào nhu cầu cụ thể và độ phức tạp của dự án của bạn.