日前在 Xamarin Asia Developers 社群 認識的朋友突然問起 Xamarin.Forms 在 macOS 上的支援與開發效果,雖然 Xamarin 早在 2015 年時就已開始支援使用 Xamarin.Native 撰寫 OS X 的應用 (相關發佈參考: https://releases.xamarin.com/),而在 Xamarin.Forms 早在 2.5.x 時也開始預覽支援 macOS 的開發。只是說來慚愧,自我開始接觸 Xamarin 以來都沒有嘗試著去測試 macOS 的 App,所以藉此熱心的社群朋友發問的機會,就來實際測試看看 Xamarin.Forms 在 macOS 的開發。
(圖多慎入...)
首先,本文的是要介紹撰寫 macOS 上的應用程式,因此會是在 Mac 上使用 Visual Studio for Mac 來做為展示的開發工具。
(目前我也沒找到在 Windows 上使用 Visual Studio 直接開發 macOS 應用的方式,有知道的人也請告訴我。)
確認在該 Mac 機器上的開發環境中有安裝 Xamarin.Mac 的 SDK。
另外,目前為止 Xamarin.Forms 的專案範本沒有預設建立 Xamarin.Mac for Xamarin.Forms 的部分,所以我們要透過建立 Xamarin.Forms 的專案以及建立 Xamarin.Mac 的專案,然後透過修改 Xamarin.Mac 專案建立的資訊,來使用 Xamarin.Forms 的部分。
首先,自行選擇專案範本中的跨平台應用程式,建立一個 Xamarin.Forms 的方案。
新增專案的部分處理應用程式的名稱,同時會看到這個部分目前只有 Android 與 iOS 的平台,完成後點選下一步。
設定專案名稱後點選建立。
通常預設建立好的專案範本的 Nuget 套件都需要再更新,請在各個專案當中點選更新。
確定方案中的三個專案都更新 Nuget 完成。
接著在解決方案中,新增一個新的專案。
這個專案我們選擇 Cocoa 應用程式,注意平台是 Mac 的應用程式,完成後點選下一步。
在這邊一樣設定應用程式名稱,並且可以調整停駐項目的名稱,他會出現在 macOS 的 Dock 上的顯示,完成後點選下一步。
另外,為了在整個方案當中容易辨識這個是 macOS 的專案,專案的名稱命名上多了 .macOS,完成後點選建立。
建立完成後的方案顯示。
確定完成後,先將這個 macOS 的專案設為起始專案。
這樣在 Visual Studio for Mac 的執行上就會顯示為 macOS 這個專案應用為預設執行的專案。
接著,由於我們要將 Xamarin.Forms 接入 macOS 的專案當中,所以原本的 macOS 的 Native UI 設計要改成使用 Xamarin.Forms 的處理,下面的步驟就是要來做這些調整。
打開專案中的 info.plist 檔案,並且點選"來源"。
找到 NSMainStoryboardFile 這個 Key-Value,並且刪除。
刪除後的狀況。
接著再找到 Main.storyboard 檔案,刪除。
確認"刪除"。
找到 ViewController.cs,刪除。
確認"刪除"。
接著確定一下 macOS 的專案狀況。
嘗試建置此專案是否能建置成功,如果在這邊就編譯失敗了,那就要回頭檢查是不是有刪錯檔案。
看到顯示"建置成功",再繼續作後面的動作。
在這個 macOS 專案當中新增 Xamarin.Forms 的 Nuget 套件。
在新增封裝這個視窗當中搜尋 "Xamarin.Forms"。
確定是 Xamarin.Forms 的 Nuget 套件,勾選並點選新增封裝。
"接受" Nuget 套件的授權條款。
完成安裝,會看到專案的封裝底下多了 Xamarin.Forms 的顯示。
接著打開 macOS 專案底下的 Main.cs。
並在 Main 方法當中用程式碼設定其 Delegate 的屬性的值為 AppDelegate 所生成的物件。
重頭戲來了,打開 macOS 專案當中的 AppDelegate.cs 這個檔案,如果熟悉 iOS 開發的朋友應該對此不陌生,會看到相當類似的一些生命週期的事件方法。
我們要再繼續修改這個 AppDelegate 的設計,將其繼承鏈中的上層類別改為 FormsApplicationDelegate 類別(來自於 Xamarin.Forms.Platform.MacOS 的命名空間當中),並且實作其需複寫的屬性。
以下為設定一個 macOS 上初始視窗的程式碼。
大致上若曾經在 Windows 上寫過一些視窗應用的話,其實概念上也都差不多,畫出一個矩形作為要呈現的視窗畫布,然後再繼續設定視窗本身的一些屬性值。只是使用的 API 換成 macOS 所設計的 API。
接著在 DidFinishLaunching 這個生命週期的事件方法中,呼叫 Forms 的初始化,並且將這個專案當中的 Xamarin.Forms 的 App 物件產生載入。
在這 macOS 專案中不知道 Xamarin.Forms 中的 App 類別是正常的,因為我們是後來才新建此 macOS 專案的,所以還需要另外手動編輯參考引用 Xamarin.Forms 的專案。
確定參考引用沒問題。
試著建置這個 macOS 專案。
如果到這邊都建置成功,就可以繼續下一步,若有問題,請回頭檢查是否有寫錯。
建置成功後,可以試著執行此應用程式。
跑起來會如下畫面,注意在 Dock 上的應用程式名稱的設定,跟我們之前在建立專案的時候的設定是一樣的。
如果沒什麼問題,接下來的動作就大致上是 Xamarin.Forms 的編輯與設計了,不多贅述。只是比較特別的是這裡的事件方法 Visual Studio for Mac 會詢問要放在程式碼的哪個位置,在 Visual Studio 是沒有這樣問,不要嚇到以為有問題。
新增事件處理常式的方法。
回到 XAML 檔調整事件方法名稱。
調整事件方法名稱的一致性,並且在這邊撰寫其方法的很簡單的一段執行程式,透過 Xamarin.Forms 所設計的警示彈跳 API 方法來實驗正確性。
再次回到 XAML 檔案,調整一下按鈕的文字顏色跟背景顏色。
修改完後執行此應用程式。
點選執行起來的應用程式上按鈕。
看到 macOS 的預設視窗警示訊息。
在這邊提醒一下,比較熟習 Windows 設計的朋友,在 macOS 中,按下紅色x並不會真的關閉應用,只會將此應用縮到最小,繼續保留其應用程式的執行。
若要真的關閉,可以透過 Visual Studio for Mac 的停止偵錯的動作。
或是在 Dock 上呼叫應用程式選單,點選"強制結束"。另外,當然在 macOS 上也有類似 Windows 工作管理員強制應用結束的方式,在這邊就不展示了。
而用 Xamarin.Forms 做為開發的好處是如果切換到 iOS 專案就可以直接執行測試。
選擇要測試的 iOS 模擬器。
執行此應用程式。
App 在 iOS 平台上跑起來的效果,點選按鈕看看。
iOS 平台上的警示訊息出現。
以上就是將 Xamarin.macOS 改成使用 Xamarin.Forms 的 UI 元件來執行 App,想當然 UI 的設計既然在同一個 Xamairn.Forms 的專案上設計出來,後續必有一定程度上需要在各平台執行時的客製化需求的出現。這時候就得仰賴 Xamarin.Forms 的各種技巧 CustomRenderer、DependencyService、OnPlatforms ...等的運用,這就不再此篇文章的介紹中討論了。
若有需要可參考我放在 GitHub 上的範例程式碼:
https://github.com/JamestsaiTW/macOS-Xamarin.Forms
I'm a Microsoft MVP - Developer Technologies (From 2015 ~).
I focus on the following topics: Xamarin Technology, Azure, Mobile DevOps, and Microsoft EM+S.
If you want to know more about them, welcome to my website:
https://jamestsai.tw
本部落格文章之圖片相關後製處理皆透過 Techsmith 公司 所贊助其授權使用之 "Snagit" 與 "Snagit Editor" 軟體製作。