返回文章列表

FireMonkey框架與樣式客製化介面設計

本文探討 FireMonkey 框架和樣式,包含如何自訂樣式、使用 TStyleBook 管理樣式、以及如何利用框架提升介面設計的模組化和程式碼的可維護性。文章涵蓋了從新增資料模組、載入樣式到嵌入資源的詳細步驟,並提供了程式碼範例說明如何修改 TArcDial

Delphi UI/UX設計

FireMonkey 提供了強大的樣式和框架機制,讓開發者可以輕鬆開發高度客製化的跨平台應用程式介面。透過 TStyleBook 元件,我們可以載入和管理不同的樣式,並透過編輯自訂樣式和預設樣式來微調介面元素的外觀。此外,將樣式嵌入應用程式資源中,可以簡化佈署和管理。框架則允許我們將常用的 UI 元素組合成可重複使用的模組,提升開發效率並確保介面一致性。更進一步地,結合繼承檢視機制,我們可以針對不同平台和裝置特性進行介面最佳化,開發更具使用者友善性的跨平台應用程式。

使用自訂樣式

在前面的章節中,我們已經瞭解如何使用 FireMonkey 中內建的樣式來設計應用程式的使用者介面。現在,我們將進一步探討如何使用自訂樣式來個人化我們的應用程式。

為什麼使用自訂樣式?

FireMonkey 提供了多種內建樣式,但有時我們可能需要更進一步地自訂應用程式的外觀和感覺。這時,自訂樣式就派上用場了。自訂樣式允許開發者根據特定的需求和品牌識別來設計應用程式的介面。

如何使用自訂樣式?

Delphi 提供了豐富的自訂樣式資源,這些資源位於 C:\Users\Public\Documents\Embarcadero\Studio\NN.0\Styles 目錄下(其中 NN 是產品內部版本號)。這些樣式檔案以 .style 為副檔名。

步驟一:新增資料模組

為了更好地管理樣式,我們應該將 TStyleBook 元件放在一個專用的資料模組中。首先,透過選擇 File | New | Data Module 來新增一個資料模組到專案中,並將其命名為 uDMStyles。確保資料模組在應用程式主表單之前被建立。

步驟二:新增 TStyleBook 元件

在資料模組上放置一個 TStyleBook 元件,並雙擊它以開啟 FireMonkey 樣式設計器。在樣式設計器中,可以載入預先定義的樣式檔案,如 Transparent.style

步驟三:套用自訂樣式

載入樣式後,將 TStyleBook 元件的名稱更改為 StyleBookTransparent。然後,將另一個 TStyleBook 元件新增到表單上,並載入 AquaGraphite 樣式,將其重新命名為 StyleBookAquaGraphite。要套用自訂樣式,需要將表單的 StyleBook 屬性指向相應的 TStyleBook 元件。

將樣式嵌入資源

除了使用 TStyleBook 元件載入樣式外,還可以將自訂樣式嵌入到應用程式資源中。這可以透過在專案資源中新增樣式檔案來實作。以下是具體步驟:

  1. 新增額外表單:新增一個空的 FireMonkey HD 表單到專案中,並將其儲存為 uFormExtra
  2. 在主表單中顯示額外表單:在主表單的選單按鈕點選事件中新增程式碼,以顯示額外的表單。
  3. 將樣式檔案新增到專案資源:透過 Project | Resources and Images 選項,將 Transparent.style 檔案新增到專案資源中,並將其識別符號設為 TransparentStyle
  4. 載入資源中的樣式:在專案原始碼檔案中,新增對 FMX.Styles 單元的參照,並呼叫 TStyleManager.TrySetStyleFromResource('TransparentStyle') 方法來載入自訂樣式。

程式碼範例:

program StylesTest3;
{$R *.dres}
uses
  System.StartUpCopy,
  FMX.Styles,
  FMX.Forms,
  uFormStylesTest in 'uFormStylesTest.pas' {FormStylesTest},
  uFormExtra in 'uFormExtra.pas' {FormExtra};
{$R *.res}
begin
  TStyleManager.TrySetStyleFromResource('TransparentStyle');
  Application.Initialize;
  // ...
end.

內容解密:

此程式碼範例展示瞭如何在 Delphi 專案中使用 TStyleManager.TrySetStyleFromResource 方法從資源中載入自訂樣式。首先,我們需要在專案資源中新增樣式檔案,並給定一個識別符號(例如 TransparentStyle)。然後,在專案原始碼檔案中,呼叫 TStyleManager.TrySetStyleFromResource('TransparentStyle') 方法來套用該樣式。這種方法使得自訂樣式的套用更加靈活,並且可以避免直接參照外部檔案。

使用自訂樣式客製化 FireMonkey 介面

FireMonkey 提供了極大的彈性讓開發者能夠自訂應用程式的樣式。除了使用內建樣式外,開發者還可以進一步客製化樣式以滿足特定的需求。

編輯自訂樣式

在測試表單上有三個 TArcDial 元件。右鍵點選任何一個已設定樣式的控制項,在上下文選單的最下方會有兩個選項:編輯自訂樣式和編輯預設樣式。

  • 編輯預設樣式會修改所有相同型別控制項的預設樣式。
  • 編輯自訂樣式只會變更特定控制項的樣式,而不會影響其他相同型別的控制項。

編輯自訂樣式的步驟:

  1. 右鍵點選 ArcDial1 控制項並選擇編輯自訂樣式
  2. 這將開啟 Style Designer,在結構檢視中可以看到定義 TArcDial 控制項的各個元件。
  3. 修改指示器橢圓的 Width 屬性為 30,Height 屬性為 10,並將其 Brush.Color 屬性更改為 Cornflowerblue。
// 範例程式碼:修改 TArcDial 樣式
ArcDial1Style := TStyleManager.LoadStyle('ArcDial1Style1');
if Assigned(ArcDial1Style) then
begin
  // 修改樣式屬性
  ArcDial1Style.ObjectByName('indicator').Width := 30;
  ArcDial1Style.ObjectByName('indicator').Height := 10;
  TBrushObject(ArcDial1Style.ObjectByName('indicator').Brush).Color := Cornflowerblue;
end;

#### 內容解密:

這段程式碼展示瞭如何載入並修改 TArcDial 的自訂樣式。首先,我們使用 TStyleManager.LoadStyle 方法載入名為 ArcDial1Style1 的樣式。接著,我們檢查樣式物件是否存在,如果存在,則進一步修改其屬性,例如將 indicator 物件的寬度設為 30,高度設為 10,並將其筆刷顏色設為 Cornflowerblue。

使用 TStyleBook 元件管理樣式

當編輯自訂樣式後,一個新的 TStyleBook 元件將被新增至表單中。它包含了 ArcDial1Style1 樣式的定義,並且該值已經被設定在 ArcDial1 控制項的 StyleLookup 屬性中。

跨平台樣式的考量:

  • 若要確保自訂樣式能夠在不同平台上正確顯示,需要為每個目標平台建立對應的樣式版本。
  • 例如,為 Android 平台新增樣式定義,以確保在 Android 裝置上正確顯示自訂樣式。

編輯預設樣式

若選擇編輯預設樣式,將會修改所有相同型別控制項的預設樣式。例如,修改 TArcDial 控制項的預設樣式,可以更改其指示器橢圓的 Width 和 Height 屬性,並將其 Brush.Fill.Color 設定為 Cadetblue。

編輯預設樣式的步驟:

  1. 右鍵點選任意 TArcDial 控制項並選擇編輯預設樣式
  2. 在 Style Designer 中修改預設樣式的屬性。
  3. 將指示器橢圓的 Width 和 Height 屬性設為 10,並將其 Brush.Fill.Color 設定為 Cadetblue。
// 範例程式碼:修改 TArcDial 的預設樣式
ArcDialStyle := TStyleManager.LoadStyle('ArcDialstyle');
if Assigned(ArcDialStyle) then
begin
  // 修改預設樣式屬性
  ArcDialStyle.ObjectByName('indicator').Width := 10;
  ArcDialStyle.ObjectByName('indicator').Height := 10;
  TBrushObject(ArcDialStyle.ObjectByName('indicator').Brush).Color := Cadetblue;
end;

#### 內容解密:

這段程式碼展示瞭如何載入並修改 TArcDial 的預設樣式。首先,我們使用 TStyleManager.LoadStyle 方法載入名為 ArcDialstyle 的預設樣式。接著,我們檢查樣式物件是否存在,如果存在,則進一步修改其屬性,例如將 indicator 物件的寬度設為 10,高度設為 10,並將其筆刷顏色設為 Cadetblue。

使用框架(Frames)提升介面設計的模組化

在開發應用程式時,經常需要重複使用某些特定的介面元件組合。FireMonkey 提供了框架(Frames)功能,讓開發者能夠將多個控制項組合成一個可重複使用的單元,從而簡化介面設計並提高程式碼的可維護性。

為何使用框架?

在許多情況下,開發者需要在多個表單或視窗中重複使用相同的介面元件組合。例如,在聯絡人管理應用程式中,可能需要輸入多個地址資訊(例如住家地址和辦公室地址)。此時,可以設計一個包含地址輸入欄位的框架,並在同一表單中多次使用該框架,以避免重複設計和維護多個相似的介面。

建立與使用框架

建立框架的步驟如下:

  1. 在 Delphi 中建立一個新的多裝置專案。
  2. 將主表單儲存為 uFormContact,並將專案儲存為 Contacts
  3. 透過「檔案」->「新增」->「其他」選單,建立一個新的 FireMonkey 框架,並將其儲存為 uFrameAddress
  4. 在框架上放置所需的控制項,例如編輯框和標籤,並設定其屬性。

以下是一個範例程式碼,展示如何定義一個地址輸入框架:

type
  TFrameAddress = class(TFrame)
    EdtStreet: TEdit;
    LblStreet: TLabel;
    EdtStreetNr: TEdit;
    LblStreetNr: TLabel;
    EdtCity: TEdit;
    LblCity: TLabel;
    LblAddressTitle: TLabel;
    EdtCountry: TEdit;
    LblCountry: TLabel;
    EdtZipCode: TEdit;
    LblZipCode: TLabel;
  private
    procedure SetCity(const Value: string);
    procedure SetCountry(const Value: string);
    procedure SetStreet(const Value: string);
    procedure SetStreetNr(const Value: string);
    function GetCity: string;
    function GetCountry: string;
    function GetStreet: string;
    function GetStreetNr: string;
    procedure SetZipCode(const Value: string);
    function GetZipCode: string;
  public
    property Street: string read GetStreet write SetStreet;
    property StreetNr: string read GetStreetNr write SetStreetNr;
    property ZipCode: string read GetZipCode write SetZipCode;
    property City: string read GetCity write SetCity;
    property Country: string read GetCountry write SetCountry;
  end;

function TFrameAddress.GetCity: string;
begin
  Result := EdtCity.Text;
end;

procedure TFrameAddress.SetCity(const Value: string);
begin
  EdtCity.Text := Value;
end;

// 其他屬性的 getter 和 setter 方法實作類別似

內容解密:

此範例展示瞭如何定義一個 TFrameAddress 類別,並在其中宣告多個屬性(例如 StreetCity 等),這些屬性對應到框架上的編輯框控制項。透過 getter 和 setter 方法,可以方便地讀取和寫入這些控制項的值。

在表單中使用框架

建立好框架後,可以將其新增到表單中:

  1. 在工具面板的「標準」類別中選擇「框架」,然後從清單中選擇要新增的框架。
  2. 在表單設計器中,將框架放置在所需的位置。

重複使用框架的優勢

使用框架可以帶來以下好處:

  • 提高介面設計的一致性:透過重複使用相同的框架,可以確保不同表單或視窗中的介面元件具有一致的佈局和樣式。
  • 簡化程式碼維護:當需要修改框架的內部實作時,只需修改一次,即可影響所有使用該框架的表單或視窗。
  • 提高開發效率:透過重複使用框架,可以避免重複設計和實作相同的介面元件組合。

使用框架提升開發效率

在 FireMonkey 應用程式開發中,框架(Frames)是一種可重複使用的 UI 元件,能夠大幅提升開發效率與介面的一致性。本篇文章將探討框架的應用及其與繼承檢視(Inherited Views)的結合使用,幫助開發者開發跨平台的最佳化介面。

建立與管理框架

首先,我們在聯絡表單上新增兩個相同的框架,分別命名為 FrameAddressHomeFrameAddressOffice,並將標題分別設為「家庭地址」和「辦公地址」。為了使表單更真實,我們還新增了一個工具列,包含標籤和兩個編輯框,用於輸入聯絡人的「姓氏」和「名字」。

當我們在不同平台(如 iOS 或 Android)之間切換表單樣式時,會發現框架中的編輯框垂直間距過小,且標籤與上方的編輯框重疊。為瞭解決這個問題,我們有兩種選擇:

  1. 直接在表單上調整控制項的位置和大小
  2. 回到框架設計中進行修改,這樣所有已嵌入表單的框架例項都會自動更新。

後者的優勢在於能夠一次性修改所有相關框架。例如,將框架中的標題文字顏色從黑色改為紅色,所有已嵌入的框架都會同步更新。但如果我們在某個特定框架例項上進行了區域性修改(如將 FrameAddressHome 的地址標籤顏色設為藍色),那麼該框架的屬性將不再繼承自原始框架定義,此時可使用「還原為繼承值」選項來還原。

程式碼範例:框架的動態載入

// 動態載入框架範例
procedure TFormContact.LoadFrame;
begin
  FrameAddressHome := TFrameAddress.Create(Self);
  FrameAddressHome.Parent := Self;
  FrameAddressHome.Align := TAlignLayout.Top;

  FrameAddressOffice := TFrameAddress.Create(Self);
  FrameAddressOffice.Parent := Self;
  FrameAddressOffice.Align := TAlignLayout.Top;
end;

內容解密:

  1. TFrameAddress.Create(Self):建立 TFrameAddress 類別的例項,並將表單設為其擁有者。
  2. FrameAddressHome.Parent := Self:將框架的父元件設為目前的表單,使其顯示在表單上。
  3. Align := TAlignLayout.Top:將框架對齊至表單頂部,為後續元件留出空間。

繼承檢視的最佳實踐

FireMonkey 提供了繼承檢視功能,使開發者能夠針對不同平台和裝置型別設計特定的介面佈局。透過「檢視」下拉選單,我們可以為特定平台或裝置新增額外的表單檔案。例如,為 FormContact 新增 iPhone 4 和 Android 7 吋平板電腦的檢視組態。

這些繼承檢視與框架類別似,能夠重複使用表單設計,並且主表單的變更會自動傳播到繼承檢視,除非在特定檢視中被覆寫。在程式碼層面,這些檢視會以額外的編譯指令呈現,例如:

{$R *.fmx}
{$R *.iPhone4in.fmx IOS}
{$R *.LgXhdpiTb.fmx ANDROID}

這段程式碼確保了不同平台下只會編譯相關的表單檔案,從而最佳化執行檔的大小。

繼承檢視的工作流程

@startuml
skinparam backgroundColor #FEFEFE
skinparam componentStyle rectangle

title FireMonkey框架與樣式客製化介面設計

package "系統架構" {
    package "前端層" {
        component [使用者介面] as ui
        component [API 客戶端] as client
    }

    package "後端層" {
        component [API 服務] as api
        component [業務邏輯] as logic
        component [資料存取] as dao
    }

    package "資料層" {
        database [主資料庫] as db
        database [快取] as cache
    }
}

ui --> client : 使用者操作
client --> api : HTTP 請求
api --> logic : 處理邏輯
logic --> dao : 資料操作
dao --> db : 持久化
dao --> cache : 快取

note right of api
  RESTful API
  或 GraphQL
end note

@enduml

圖表翻譯: 此圖示展示了主表單如何透過繼承機制產生不同平台的檢視組態,並且每個檢視都可以根據需求進行客製化調整。

跨平台介面設計的優勢

透過結合框架與繼承檢視,開發者能夠大幅提高跨平台應用的介面一致性和開發效率。無論是在同一個專案內的不同表單之間,還是在多個專案之間,框架都能夠提供可重複使用的 UI 元件。同時,繼承檢視則允許我們針對不同裝置特性進行最佳化調整,從而提供最佳的使用者經驗。