如何在 Flutter 中使用點 9 圖

2025年1月13日

點 9 圖(Nine-patch image)是一種特殊的 PNG 圖像,它允許開發者在拉伸圖像時保持圖像的某些區域不變形,從而避免圖像失真。這在建立可縮放的 UI 元素(例如按鈕背景、進度條等)時非常有用。雖然 Flutter 本身並不直接支援點 9 圖的原生格式,但我們可以透過一些技巧來實現類似的效果。

使用 9 Patch Editor 建立點 9 圖

首先,你需要準備一張 PNG 圖片。然後,使用 9 Patch Editor 工具來建立你的點 9 圖。該工具允許你指定圖像的可拉伸區域和內容區域。具體操作步驟如下:

  1. 前往 9 Patch Editor 的網站。
  2. 上傳你的 PNG 圖片。
  3. 使用工具提供的編輯器,選擇圖像的可拉伸區域(拖動圖像的左邊緣和上邊緣)。
  4. 選擇圖像的內容區域(拖動圖像的右邊緣和下邊緣,這些區域在拉伸時保持不變)。
  5. 下載生成的點 9 圖(請根據您的方案下載不同的圖像)。

在 Flutter 中使用點 9 圖

Flutter 沒有直接載入點 9 圖的機制。我們需要借助第三方函式庫或者使用 Flutter 內建的 Image.centerSlice 屬性來模擬點 9 圖的效果。

方法一:使用第三方函式庫

目前有一些 Flutter 的第三方函式庫可以幫助你載入和渲染點 9 圖,例如 ninepatch_imagenine_patch

使用 ninepatch_image 函式庫

你需要在 pubspec.yaml 檔案中新增依賴:

dependencies:
  ninepatch_image: ^0.0.4

將 PNG 圖片放在你的 Flutter 專案的 assets 資料夾中,並在 pubspec.yaml 檔案中宣告:

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

然後,你可以使用 NinePatchImage 小部件來顯示你的點 9 圖:

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

詳細的使用方法,請參考 ninepatch_image 的文件。

使用 nine_patch 函式庫

你需要在 pubspec.yaml 檔案中新增依賴:

dependencies:
  nine_patch: ^1.0.0

你需要在 assets 資料夾中建立一個儲存點 9 圖資訊的 JSON 檔案並將原圖放在 assets 資料夾中。

assets/TextBox_Side.9.jsonassets/2.0x/TextBox_Side.png
(without the 1 pixel border)
{
  "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
}

Example nine-patch PNG file named TextBox_Side.png

stretch 是圖像的可拉伸區域,contents 是圖像的內容區域,dimensions 是圖像的尺寸。您可以在 9 Patch Editor 工具中查看這些資訊或者使用 nine_patcher 工具來產生這些資訊。

然後,你可以使用 NinePatchImage 小部件來顯示你的點 9 圖:

import 'package:nine_patch/nine_patch.dart';

...

// Create a new NinePatchImage widget
NinePatchImage.fromAssetMetadata(
    name: "my_image.9.json",
)

記住將 assets/my_image.9.json 替換成你的點 9 圖的 JSON 檔案路徑。

詳細的使用方法,請參考 nine_patch 的文件。

方法二:使用 Image.centerSlice

如果你不想使用第三方函式庫,可以使用 Flutter 內建的 Image.centerSlice 屬性來模擬點 9 圖的效果。 你需要手動指定圖像的可拉伸區域:

Image.asset(
  'assets/my_image.png',
  width: 200,
  height: 100,
  centerSlice: Rect.fromLTWH(20, 20, 160, 60), // 手動指定可拉伸區域
),

注意:圖片要使用原圖編譯後的圖片

你需要根據你的圖片手動調整 centerSlice 屬性的值。你可以在 9 Patch Editor 工具中查看這些資訊。

總結

雖然 Flutter 沒有直接支援點 9 圖,但我們可以透過使用第三方函式庫或 Image.centerSlice 屬性來實現類似的效果。推薦使用 ninepatch_image 函式庫,它使用起來更簡單。如果你需要要更靈活和強大的功能,可以考慮使用 nine_patch。如果你不想引入第三方函式庫,則可以使用 Image.centerSlice 方法,但功能有限,需要手動指定可拉伸區域。選擇哪種方法取決於你的具體需求和專案複雜度。