XAML in Xamarin.Forms 基礎篇 電子書

XAML in Xamarin.Forms 基礎篇 電子書
XAML in Xamarin.Forms 基礎篇 電子書

Xamarin.Forms 快速入門 電子書

Xamarin.Forms 快速入門 電子書
Xamarin.Forms 快速入門 電子書

2017/01/31

Xamarin FAQ 2017.01 當月問答集綜合版

Xamarin.Forms 1-001 : 如何取得 Prism 的容器 Container 物件

問題

當您需要使用 Prism 功能,進行相依性服務的註冊與解析功能的時候,需要取得 Prism 的容器 Container 物件,那麼,在不同的組件 (Assembly)中(原生專案或者核心 PCL 專案),要如何取得這個容器物件呢?

解答

想要取得 Prism 的容器物件,可以使用底下程式碼
IUnityContainer myContainer = (App.Current as PrismApplication).Container;
這樣就可以取得 IUnityContainer 的容器物件,透過這個物件,您可以輕鬆的進行注入您所想要的相依性物件到您現在的類別方法內。

Xamarin.Forms 1-002 : 如何不透過建構式注入的方式,取得特定介面的實作物件

問題

當我們在使用 Prism 相依性服務注入功能的時候,通常會使用建構式注入方式,取的介面的實作物件,但有些時候,我們希望直接透過容器來取得這個實作物件,那麼,該如何做到呢?

解答

當您已經取得了 Prism 的容器物件,例如,該容器儲存在 myContainer 這個物件內,您可以使用 myContainer.Resolve<IMyInterface>(); 這樣的方式,取得介面 IMyInterface 的實作物件到 fooObject內。
IMyInterface fooObject = myContainer.Resolve<IMyInterface>();

Xamarin FAQ 1-003 : 如何使用容器註冊介面與實作物件

問題

在 Xamarin.Forms 內,若您使用了 Prism Template Pack 來建立一個檢視 (View),此時,Visua Studio 除了幫您建立一個 XAML 檢視頁面之外,還會幫您一併在 ViewModels 資料夾下也建立一個檢視模型,有些時候,想要在核心 PCL 專案內或只者原生專案內,註冊一個介面與其實作類別,那麼該怎麼做呢?

解答

這個時候,您需要先取得 Prism 的容器 Container,接著使用該容器提供的 RegisterType 方法,不過,需要將介面與實作類別型別使用泛型方式傳入進去,這樣就完成了註冊的工作。
經過這樣的註冊程序,若要透過相依性服務取得實作的物件,則是具備了短暫(transient)生命週期(lifetime);也就是,每進行注入解析動作,就會產生一個不同的物件出來。
myContainer.RegisterType<IMyClass, MyClass>();

Xamarin FAQ 1-004 : 如何從PCL來同步呼叫原生專案內實作方法

問題

在進行 Xamarin.Forms 專案開發的時候,必定會使用這這樣的需求,那就是有些功能在核心 PCL 專案內是無法使用的,需要在原生專案內實作出這些功能,並且,在每個不同平台的原生專案內,又需要使用不同原生專案支援的類別庫,來完成這些功能需求。這個時候,您可以使用 Prism 的相依性服務機制,在每個不同平台來實作出這些功能,透過相依性服務注入機制,在檢視模型 (ViewModels)內,使用建構式注入的方式,取得這些實作物件,如此,就可以在核心 PCL 專案內呼叫這些原生專案獨有的功能了。

解答

要解決這樣的需求,請依照底下的步驟進行操作。
  • 首先,在核心 PCL 專案內,產生一個介面 (Interface),在這個介面內宣告出共用的方法。在底下,定義了一個介面,裡面有個方法 GetPlatformName,我們期望能夠在核心 PCL 專案內呼叫這個方法,就可以知道當時是在哪個平台作業系統上執行。
    public interface INatvieAssyFile
    {
        /// <summary>
        /// 取得作業系統版本名稱
        /// </summary>
        /// <returns></returns>
        string GetPlatformName();
    }
  • 接著,您需要在每個原生平台(Android, iOS, UWP)專案中,產生一個類別,並且實作出這個介面功能。在底下的範例中,我們產生了一個 NatvieAssyFile類別,並且實作了介面 INatvieAssyFile的功能;因為這個類別是定義在 iOS 專案內,所以方法 GetPlatformName() 就僅會回傳 iOS 這個字串。
    如此,當這個 Xamarin.Forms 的專案在 iOS 系統下運行的時候,並且程式在核心 PCL 專案內執行呼叫 GetPlatformName()方法,就會得到了 iOS 這個字串;當然,您需要其他原生專案內也實作出同樣的類別,並且回傳當時作業系統的文字。
  • 另外,您需要在 namespace 前面,宣告這個類別可以具備相依性服務注入的能力,在這個範例中,使用了這樣的語法 [assembly: Xamarin.Forms.Dependency(typeof(NatvieAssyFile))]。加入了這行,您就可以在核心 PCL 專案內,使用建構式注入的方式,取得這個實作物件了。
[assembly: Xamarin.Forms.Dependency(typeof(NatvieAssyFile))]
namespace XFFiles.iOS.Services
{
    class NatvieAssyFile : INatvieAssyFile
    {
        public string GetPlatformName()
        {
            return "iOS";
        }
    }
}
  • 最後,我們來看如何在核心 PCL 專案內,取得這個注入物件;要做到取得注入物件,請參考底下步驟:
    • 宣告一個 INatvieAssyFile 介面變數,用來持有注入後的實作物件。
    • 在檢視模型的建構式中,加入這個引數 INatvieAssyFile natvieAssyFile
    • 在檢視模型的建構式裡面,將剛剛注入進來的物件,設定讓欄位變數可以持有這個傳入的物件。
        private readonly INavigationService _navigationService;
        private readonly INatvieAssyFile _natvieAssyFile;
        #endregion

        #region Constructor 建構式
        public MainPageViewModel(INavigationService navigationService, INatvieAssyFile natvieAssyFile)
        {

            _navigationService = navigationService;
            _natvieAssyFile = natvieAssyFile;
            ...
        }

Xamarin FAQ 1-005 : 如何在原生專案使用 Prism 事件聚合器 (Event Aggregator)來非同步呼叫核心 PCL 專案內方法

問題

有時候,當程式碼已經轉移到原生專案組件內執行了,此時,您要用非同步的使用核心 PCL 專案內的某個方法,例如,呼叫核心 PCL 專案內的某個方法,使用導航物件進行頁面導航的工作,這個要如何做到呢?

解答

要解決這樣的需求,請依照底下的步驟進行操作。
  • 請先取得這個應用程式的 Prism 容器 ( Container ),請使用底下方法取得 Prism 容器
            // 取得 Prism 相依性服務使用到的容器
            IUnityContainer fooContainer = (XFoAuth2.App.Current as PrismApplication).Container;
  • 接著,解析出這事件聚合器 (Event Aggregator)介面的實作物件,一旦您取得了這個實作物件,您就可以使用 Prism 的事件訂閱或者發佈事件功能。
            // 取得 IAccountStore 介面實際實作的類別物件
            var fooIEventAggregator = fooContainer.Resolve<IEventAggregator>();
  • 在底下的範例中,會根據 e.IsAuthenticated 的值內容,使用 Prism 的事件聚合器 (Event Aggregator),送出不同的事件訊息給核心 PCL 專案的訂閱者。
            if (e.IsAuthenticated)
            {
                fooIEventAggregator.GetEvent<AuthEvent>().Publish(AuthEventEnum.身分驗證成功);
            }
            else
            {
                fooIEventAggregator.GetEvent<AuthEvent>().Publish(AuthEventEnum.身分驗證失敗);
            }
  • 在核心 PCL 專案內,使用了 Prism 的事件聚合器 (Event Aggregator)訂閱了這個事件,一旦非同步收到這個訊息,就會回到上一頁頁面。
        public oAuthPageViewModel(INavigationService navigationService, IEventAggregator eventAggregator)
        {

            _eventAggregator = eventAggregator;
            _navigationService = navigationService;

            // 訂閱使用者認證結果通知事件,認證成功之後,會收到 Success
            fooSubscriptionToken = _eventAggregator.GetEvent<AuthEvent>().Subscribe(async x =>
              {
                  await _navigationService.GoBackAsync();
              });
        }

Xamarin FAQ 1-06 : 那些 Android SDK 套件需要使用 Android SDK Manager 來安裝呢?

問題

很多人在進行 Android 專案開發的時候,往往會遇到一些奇怪的問題,甚至在要建置專案的時候,就會產生相當多的錯誤訊息,如 Android.Support.V4.Widget.DrawerLayout.AddDrawerListener;其實,很多時候,這是您的 Android SDK Manager 並沒有安裝與設定完全。

解答

  • 請先安裝 Java JDK 1.8 以上的版本到您的電腦上
  • 在 Visual Studio 2015 中,點選功能表 工具 > 選項 > Xamarin > Android Settings
  • 請設定 Java Development Kit Location 這個欄位,指向您 JDK 1.8 版本安裝的位置,例如: C:\Program Files\Java\jdk1.8.0_102
  • 在 Visual Studio 2015 中,點選功能表 工具 > Android > Android SDK Manager
  • 在 Android SDK Manager 請確認底下項目已經確實有安裝且安裝到最新版本
    • Tools > Android SDK Tools
    • Tools > Android SDK Platform-tools
    • Tools > Android SDK Builder-tools ( 這裡僅需要安裝最新版本,舊的本版可以移除,不會有影響)
    • 每個 Android 版本內的 SDK Platform 項目要安裝 ( 在這裡建議把 Android 4.4.2 (API 19) 以上的各 Android 版本內的 SDK Platform 都安裝起來 )
    • Extras > Android Support Repository
    • Extras > Google USB Driver

Xamarin FAQ 1-007 : 如何清除導航堆疊 (Navigation Stack)

問題

根據當時應用程式的操作流程,會需要轉跳到某個頁面,此時,螢幕上不會有回上一頁的導航按鈕出現,必且,手機的實體回上一頁按鍵,當您按下之後,這個應用程式就會直些回到手機桌面,並不會跳到之前來的頁面。最經典的使用案例那就是,使用者可以在應用程式的任何地方,點選 登出 功能選項,接著,應用程式就會跳到 登入 頁面上,此時,這個頁面就會成為這個應用程式的首頁,因為導航堆疊已經被清空了,所以,當按下實體按鍵的回上一頁按鈕,此時,應用程式也就回到背景模式,手機桌面也就出現了。

解答

想要解決這個問題,可以使用底下程式碼
        public YourConstructor(INavigationService navigationService)
        {
            _navigationService = navigationService;
            登出Command = new DelegateCommand(() =>
            {
                await _navigationService.NavigateAsync("xf:///MDPage/NaviPage/LoginPage");
            });
        }|
在這個範例程式碼中,當您需要導航到 登入 頁面的時候 (LoginPage),請使用絕對路徑的 URI 來表示,而不要使用相對路徑,例如:await _navigationService.NavigateAsync("LoginPage");,如此,當切換到 登入 頁面之後,應用程式的導航堆疊也就清空了。

Xamarin FAQ 1-08 : 在巢狀虛擬化的虛擬機器中執行 Hyper-V

問題

若您需要在 Hyper-V 內,再度開啟一個 Hyper-V 的 VM,例如,在您的 Hyper-V VM 內,建立另外一個 Win10 系統並且安裝的 Visual Studio 2015 與 Xamarin Toolkit,此時,若您想要在 VM 內開啟 Visual Studio,接著進行 Xamarin.Forms 的專案開發與在模擬器上測試;這個時候,您就需要使用巢狀虛擬化的功能,否則,您的 Android 模擬器就會開不起來。

解答

  • 請開啟 命令提示字元 視窗
  • 輸入 powershell 並且按下 Enter,進入到 powershell
  • 輸入 Set-VMProcessor -VMName "你的虛擬機器名稱" -ExposeVirtualizationExtensions $true

Xamarin FAQ 1-09 : 開發 Xamarin.Forms 建議的開發配備

問題

開發跨平台的原生應用程式 (Native App),勢必要考慮到各種行動裝置的開發與測試情境,採用模擬器來測試原生應用程式是最常見的作法。當您選擇 Xamarin.Forms 來建置 App 時,最讓人頭疼的就是架設好完整的開發環境,然而跨平台的 App 會牽涉到許多平台上的限制,對於軟硬體配備的選擇就是一門大學問,那麼想要開發 Xamarin.Forms 的應用程式,要如何準備相關的軟硬體環境呢?

解答

Xamarin FAQ 1-10 : Visual Studio Emulator for Android 疑難排解

問題

當您使用 Visual Studio 開發 Android 應用程式的時候,往往會遇到 Visual Studio Emulator for Android 無法啟動、啟動後無法正常運作、無法進行除錯、一執行程式就閃退、無法抓到模擬器、無法正常下載新的模擬器、無法使用 Google Play 服務等等,造成剛開始想要學習開發 Xamarin.Forms 的開發者莫大的困擾,那要如何解決這些問題呢?

解答

Microsoft 微軟已經幫您準備好了這些相關問題的解答,請參考這篇文章 Visual Studio Emulator for Android 疑難排解 與 Visual Studio 2015 Android 模擬器

Xamarin FAQ 1-11 : 如何指定顯示頁面每次都要執行的工作

問題

往往當需要顯示一個新的頁面的時候,可能會接收來自其他頁面所傳送出來的參數並且根據這些參數進行準備這個頁面要顯示的資料,但是,很多時候,要準備的資料可能會來自於檔案系統內的檔案、網路上的 Web API等等,這些進行頁面資料初始化的動作時候,很多需要滿多的時間來進行執行,如何進行這樣的工作設計呢?

解答

很多人會把頁面資料初始化的工作,都放在建構式內,但是,這樣會產生一個問題,那就是當這個頁面物件要建立起來的時候,會花費較多的時間,這將會導致當要切換到新頁面的時候,可能需要等候一段時間,才能夠看到新的頁面出現,這樣的設計方式,會造成使用者以為應用程式有嚴重延遲特性,這是一個不是很好的設計方式。
有人會在建構式內放入 await 的非同步的呼叫方法,這樣的作法不被 C# 所允許的。
在這裡有兩個方式可以來處理這樣的情況,在底下的方法都是透過事件呼叫的方式來處理,因此,您可以在這裡使用 Async / Await 的非同步呼叫方法。
  • 使用每個頁面檢視的 call behind OnAppearing() 方法
        protected override void OnAppearing()
        {
            base.OnAppearing();
        }
  • 另外一種作法,那就是在檢視模型 ViewModel 內的 OnNavigatedFrom / OnNavigatedTo,如此,
        public void OnNavigatedFrom(NavigationParameters parameters)
        {
        }

        public void OnNavigatedTo(NavigationParameters parameters)
        {
            Init();
        }

Xamarin FAQ 1-12 : 使用簡單的方式來保存應用程式的狀態

問題

開發一個行動裝置應用程式,一定會用到這樣的需求,那就是需要把應用程式執行的某些狀態,儲存到手機永久儲存體中,等到下次應用程式再度啟動時候,需要把當時的狀態從手機中的永久儲存體讀取出來,並且重新記錄到應用程式內的 .NET 物件內。

解答

在 Xamarin.Fomrs 應用程式中,有個 Application 類別有個靜態物件,表示 Xamarin.Forms 這個應用程式的當時的應用程式物件,您可以透過 Application.Current 取得正在執行的 Application 類別物件。
在 Application 實例物件中,有個 Properties 屬性,這個屬性的型別是 IDictionary<string, object>,因此,您可以將任何型態的物件值儲存到 Application.Current.Properties 這個實例中。一旦,您將系統內的某個物件加入到 Application.Current.Properties 這個實例內,系統會自動將其儲存到行動裝置內的永久儲存體內。
不過,您需要特別注意到一件事情,Properties 這個字典型別,僅僅能夠序列化基本類型(Primitive Type.aspx))的物件,所以,不太建議使用 Properties 來儲存太複雜的物件內容。

Xamarin FAQ 1-13 : 如何從父頁面傳遞物件到子頁面

問題

在進行導航頁面型態的應用程式開發的時候,經常會處理,當開啟一個新網頁的時候,需要傳遞一些物件到新頁面內,讓新頁面根據傳遞進來的物件,做出不同的處理動作。

解答

在導航物件的 NavigateAsync 方法內,可以接受 NavigationParameters 物件,這個物件的型別為 Dictionary<string, object>,因此,您可以透過 NavigationParameters 物件傳遞很多的物件到新(子)頁面內。
底下為 NavigateAsync 的方法簽章 Method Signature
        //
        // 摘要:
        //     Initiates navigation to the target specified by the name.
        //
        // 參數:
        //   name:
        //     The name of the target to navigate to.
        //
        //   parameters:
        //     The navigation parameters
        //
        //   useModalNavigation:
        //     If true uses PopModalAsync, if false uses PopAsync
        //
        //   animated:
        //     If true the transition is animated, if false there is no animation on transition.
        Task NavigateAsync(string name, NavigationParameters parameters = null, bool? useModalNavigation = default(bool?), bool animated = true);

Xamarin FAQ 1-14 : 如何從子頁面傳遞物件到父頁面

問題

當在一個子頁面是從父頁面導航過來的,不過,往往會有機會遇到這樣的情況,當從子頁面返回到父頁面的時候,需要把子頁面的一些狀態或者物件,傳回到父頁面中;所以,當回到父頁面的時候,就可以更新到最新的狀態。

解答

在使用 Prism 設計框架工具,我們可以使用事件聚合器 (Event Aggregator)來解決這樣的問題,在父頁面中,使用事件聚合器來訂閱這類事件,當在子頁面要回到父頁面的時候,可以透過事件聚合器發佈一個訊息,讓父頁面可以來處理。

Xamarin FAQ 1-15 : 究竟甚麼是 Prism

問題

在這份 Xamarin FAQ 問答集文件中,相關的解決方案,都會使用 Prism 框架下所提供的解決方法,不過,甚麼是 Prism呢?

解答

Prism 是個可以用於 Xamarin.Forms 的 MVVM 框架 (framework),這套框架當初是由微軟開發與維護的,不過,現在已經開放原始碼了。透過了 Prism 框架,已經協助您把許多 MVVM 設計模式 (Design Pattern)好用的機制製作出來了,只要您遵從 Prism 的規範,就可以很容易地開發出一個精簡、有效、方便管理的以 MVVM 為基礎的應用程式。另外,Prism 也把許多 Xamarin.Forms 本身的缺陷,進行改善了,您可以透過 Prism 所提供的 導航機制 / 對話窗 / 訊息聚合器等相關功能,大幅提升整體應用程式的開發效能與縮短開發時間。
Xamarin-跨平台手機應用程式設計入門-粉絲團

Xamarin FAQ 1-16 : 如何在 XAML 中,使用與存取靜態資源

問題

當我們在進行宣告 XAML 個控制項標記屬性的時候,希望能夠擁有 CSS 這樣特性的功能,也就是可以把許多共同屬性的設定值,例如,顏色設定,集中定義在某個地方,這樣,就可以在 XAML 內的各個控制項參考這個顏色宣告。如此,當要變更這些參考到的控制項的顏色,就可以直接修改這個宣告顏色的地方進行修改,但是,要怎麼做到這樣的功能呢?

解答

要了要簡化與集中管理 XAML 中各控制項的屬性設定,您可以在 ContentPage 內的 Resources 屬性內,定義 ResourceDictionary,在 ResourceDictionary裡面,您可以透過 XAML 標記來宣告產生一些物件,讓整個頁面可以相關控制項與版面控制可以參考這個物件。
在底下的範例中,我們在 ResourceDictionary 內,宣告了一個 lSize 的物件,它的型態為 x:Double (也就是 .NET 裡面的 double 型別),並且設定其值為 30。另外,宣告另外一個物件為 lTest,它的型態為 x:String ,設定這個物件的值為 "我是 Xamarin.Forms"。
所以,只要在宣告 ResourceDictionary 節點之下的任何子節點,都可透過 StaticResource 這個延伸標記宣告方法,參考之前宣告的物件;例如,當要指定 Label 控制項的 FontSize 這個屬性值,就可以使用 {StaticResource lSize}這樣的用法,指定這個 Label 控制項的 FontSize 屬性值為 30。
<ContentPage.Resources>
    <ResourceDictionary>
      <x:Double x:Key="lSize">30</x:Double>
      <x:String x:Key="lText">我是 Xamarin.Forms</x:String>
    </ResourceDictionary>
  </ContentPage.Resources>
  <ContentPage.Content>
    <Grid>
      <Label Text="{StaticResource lText}"
             Grid.Row="0" Grid.Column="0"
             FontSize="{StaticResource lSize}"
             VerticalOptions="Center"
             HorizontalOptions="Center" />
    </Grid>
  </ContentPage.Content>
Xamarin-跨平台手機應用程式設計入門-粉絲團

Xamarin FAQ 1-17 : 如何在 XAML 中,使用與存取 .NET 靜態屬性

問題

當您想要使用 .NET 的靜態屬性,來集中管理 XAML 中會參考到的物件,那麼,在 XAML 中,是要如何參考這個 .NET 中的靜態屬性值呢?

解答

  • 首先,您需要在 .NET 中,定義一個靜態類別,和裡面的靜態屬性。
  • 在 XAML 裡面,為了要能夠參考到這個 .NET 中的靜態屬性,您需要宣告一個新的命名空間 ( namespace )。
    在底下的範例中,使用了 xmlns 這個關鍵字,宣告了一個新的命名空間 xmlns:local="clr-namespace:App1" 叫做 local。
    當您要參考這個新的命名空間內了某個靜態屬性,例如,Label 這個控制項的 Font 這個屬性,它的字體大小值需要參考到 .NET 靜態屬性 AppConstants.TitleFont,這個時候,您可以使用 x:Static這個延伸擴充標記來參考其他物件屬性。
    Font="{x:Static local:AppConstants.TitleFont}" 在這個範例中,使用了 x:Static 配合了指定 AppConstants.TitleFont屬性值,是定義在 local 命名空間。
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             xmlns:local="clr-namespace:App1"
             xmlns:sys="clr-namespace:System;assembly=mscorlib"
             x:Class="App1.MainPage">

  <Label Text="Hello, XAML!"
         VerticalOptions="{x:Static LayoutOptions.Start}"
         HorizontalTextAlignment="{x:Static TextAlignment.Center}"
         TextColor="{x:Static Color.Aqua}"
         BackgroundColor="{x:Static local:AppConstants.ForegroundColor}"
         Font="{x:Static local:AppConstants.TitleFont}"
         />
</ContentPage>
Xamarin-跨平台手機應用程式設計入門-粉絲團

Xamarin FAQ 1-18 : 如何在 XAML 中,參考其他的控制項

問題

在進行 XAML 頁面設計的時候,如何在某個控制項中的某個屬性,是參考來自於另外一個控制項的某個屬性,這該如何定義這樣的 XAML 宣告標記呢?

解答

以底下的 XAML 範例中,若您要參考某個控制項,您必須要先使用 x:Name 這個延伸宣告標記,定義這個控制項的可以存取名稱,當然,也可以在 Call behind 程式碼中,使用這個定義名稱,來存取這個控制項。
接著,您需要使用 x:Reference 這個延伸宣告標記,指出要參考的其他控制項,在底下範例中,第二個 Label 控制項的 Text 屬性,透過了指定另外一個控制項做為資料繫結的來源,並且指定了參考路徑指向 label這個控制項的 Text 屬性。
        <Label x:Name="label" Text="{Binding Title}" />
        <Label Text="{Binding Source={x:Reference label}, Path=Text}"/>
Xamarin-跨平台手機應用程式設計入門-粉絲團

Xamarin FAQ 1-19 : 如何製作類似 HTML 可連結文字標籤

問題

在 Xamarin.Forms 所提供的預設控制項中,並沒有看到類似 HTLM 可連結文字標籤效果的控制項,而且,從 Label 控制項中,也看不到有任何 點擊 Tap / Click 相關的事件可以使用;若想要在 Xamarin.Forms 的頁面中開發出這樣的控制項效果,是不是只能夠透過 Renderer 的方式來實現呢?

解答

其實,關於這樣的需求,不需要透過 Renderer 就可以做到;在每個控制項中,都會擁有一個 GestureRecognizers 屬性,您可以透過這個屬性,加入想要的手勢操作 XAML 物件,就可以偵測出使用者是否有點擊這個 Label 標籤控制項了。
以底下的 XAML 宣告標籤而言,我們在 Label.GestureRecognizers 屬性內,加入了一個 TapGestureRecognizer 物件,並且使用了 Command 屬性綁定了檢視模型 ViewModel 內的一個 ICommand的屬性,如此,您就可以在這個 ICommand 中來定義,當使用者點擊了這個文字標籤之後,需要做哪些相關的處理動作。
            <Label 
                Grid.Column="0"
                HorizontalOptions="Center" VerticalOptions="Center"
                Text="查看明細"
                TextColor="Blue"
                FontSize="14"
                   >
                <Label.GestureRecognizers>
                    <TapGestureRecognizer Command="{Binding 查看明細Command}"/>
                </Label.GestureRecognizers>
            </Label>
Xamarin-跨平台手機應用程式設計入門-粉絲團

Xamarin FAQ 1-20 : 如何在建置時期,就能夠發現到 XAML 語法上的錯誤

問題

原則上,當 Xamarin.Forms 應用程式在執行並且顯示一個頁面的時候,會動態的載入與分析 XAML 宣告標記檔案,並且產生出相關 .NET 物件,最後將這個頁面顯示在手機螢幕上;所以,若 XAML 的宣告標記內容若有任何錯誤,必須要等到執行時期才會發現到,當然,這個時候,您的應用程式就會造成閃退的現象,這對於使用者而言,並不是一個很好的體驗,那麼,要如何處理,才能夠讓 Visual Studio 可以在建置時期的時候,就能夠指出 XAML 檔案哪裡寫得有問題,並且可以提升整體應用程式的執行效能。

解答

請在您的核心 PCL 專案內,找到 Properties 節點,並且展開這個節點,此時,您會看到有個項目,AssemblyInfo.cs 檔案,使用滑鼠雙擊這個檔案,請在這個檔案的最後,加入底下程式碼。
[assembly: XamlCompilation(XamlCompilationOptions.Compile)]
Xamarin-跨平台手機應用程式設計入門-粉絲團

Xamarin FAQ 1-21 : 關於 Android 的自動加入權限設定問題

問題

當在進行行動裝置應用程式開發的時候,若您的應用程式需要使用到裝置中的硬體等相關功能,此時,您需要手動修改 AndroidManifest.xml 檔案,並且,您需要知道這些權限的名稱並且填入到這個檔案內,有沒有甚麼更加簡單的方法來處理這樣的問題。

解答

  • 您可以打開 Android 原生專案內的內容,在 Android 原生專案中,說擊 Properties 這個節點,並且找到 Android Manifest 葉面,您將會看到下方有 Required permissions 清單,您可以在這裡勾選您需要用到的權限。
  • 現在,越來越多的 Xamarin.Forms 套件,當您加入到 Xamarin.Forms 專案內後,一旦您建置 Release 模式的 APK 檔案,這些套件會用到的權限便會自動加入到 AndroidManifest.xml 檔案內。若您擔心是否需要用到的權限是否有加入到 AndroidManifest.xml 檔案內,可以參考底下的說明:
    假設這個專案是 XFTakePhoto,您可以打開這個專案下的目錄 XFTakePhoto\XFTakePhoto\XFTakePhoto.Droid\obj\Release\android 查看這個檔案 AndroidManifest.xml
    您將會看到這個拍照應用程式,自動加入了這些權限 android.permission.INTERNET / android.permission.WRITE_EXTERNAL_STORAGE / android.permission.READ_EXTERNAL_STORAGE / android.hardware.camera / android.hardware.camera.autofocus
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android" android:installLocation="auto" package="XFTakePhoto.Droid" android:versionCode="1" android:versionName="1">
  <!--suppress UsesMinSdkAttributes-->
  <uses-sdk android:minSdkVersion="19" />
  <uses-permission android:name="android.permission.INTERNET" />
  <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
  <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
  <uses-feature android:name="android.hardware.camera" android:required="false" />
  <uses-feature android:name="android.hardware.camera.autofocus" android:required="false" />
  <application android:label="XFTakePhoto.Droid" android:theme="@style/MyTheme" android:icon="@drawable/icon" android:name="md5a568f8c57b5f8a80d01f31a0c4f56c56.MainApplication" android:allowBackup="true">
    <activity android:configChanges="orientation|screenSize" android:icon="@drawable/icon" android:label="XFTakePhoto" android:name="md5a568f8c57b5f8a80d01f31a0c4f56c56.MainActivity">
      <intent-filter>
        <action android:name="android.intent.action.MAIN" />
        <category android:name="android.intent.category.LAUNCHER" />
      </intent-filter>
    </activity>
    <activity android:configChanges="orientation|screenSize" android:name="md5a3e164e78ade0c22cefea770ddd0bc49.MediaPickerActivity" />
    <provider android:name="mono.MonoRuntimeProvider" android:exported="false" android:initOrder="2147483647" android:authorities="XFTakePhoto.Droid.mono.MonoRuntimeProvider.__mono_init__" />
  </application>
</manifest>
Xamarin-跨平台手機應用程式設計入門-粉絲團

Xamarin FAQ 1-22 : 為什麼在核心 PCL 專案內無法使用 HttpClient 這個類別呢?

問題

當您需要在 Xamarin.Forms 專案中,提供可以存取 Web API 的功能,當然,應該要使用 .NET 提供的 HttpClient 類別所產生的物件,就可以進行相關 Get / Post / Put / Delete 等 RESTful 操作,並且這個類別是提供了非同步方法來呼叫,不會造成使用者操作介面被凍結的問題;不過,若您在核心 PCL 專案內取使用 HttpClient 這個類別,卻發現到您是無法參考到這個物件,那麼,該如何解決此一問題呢?

解答

要解決此一問題,請在方案中滑鼠右擊,選擇 管理方案的 NuGET 套件 > 瀏覽 ,請在搜尋文字輸入盒中,輸入 Microsoft.Net.Http 這個套件名稱,接著,將這個套件安裝到所有的專案內。這個安裝動作除了會幫助您安裝 Microsoft.Net.Http 套件,還會幫助您安裝其他相依性 NuGet 套件,Microsoft.Bcl / Microsoft.Bcl.Build / Microsoft.NETCore.UniversalWindowsPlatform
Xamarin-跨平台手機應用程式設計入門-粉絲團

Xamarin FAQ 1-23 : 進行 iOS 專案除錯,得到 No installed provisioning profiles match the installed iOS signing identities.

問題

若您開發完成 Xamarin.Froms 專案,並且於 Android 平台下測試過,接著,您想要在 iOS 平台下執行這個應用程式,看看有沒有甚麼問題;當然,您會使用滑鼠右擊 iOS 原生專案,選擇 設定為起始專案,接著,二話不說,馬上建置這個 iOS 專案,很不幸的,您得到了這個錯誤訊息
No installed provisioning profiles match the installed iOS signing identities.
那麼,您該如何解決此一問題呢?

解答

請您確認 Visual Studio 2015 中的標準工具列上,關於 方案平台 的選項,是否為 iPhoneSimulator,若不是,請切換下拉選單,選擇 iPhoneSimulator 這個選項,接著,重新建置一次,就沒問題了。
Xamarin-跨平台手機應用程式設計入門-粉絲團

Xamarin FAQ 1-24 : 如何變更 iOS 應用程式的狀態列背景與文字顏色

問題

當您在規劃一個 Xamarin.Forms 的應用程式的時候,都會制訂一套配色規則,並且每個頁面與控制項,都會依照這套視覺設計規範,進行套版設計;可是,當您在 iOS 平台執行這個應用程式時候,卻發現到狀態列的背景與文字顏色似乎沒有地方可以修改,這該如何處理呢?

解答

您需要在 iOS 原生專案內找到這個應用程式的進入點
請開啟 AppDelegate.cs 檔案
在 AppDelegate 類別內,加入底下的宣告,其中,ExportedColors.AccentColor 與 ExportedColors.InverseTextColor 是定義在核心 PCL 專案內的一個 Color 類別的顏色物件。而 ToUIColor 是 Xamarin.Forms.Platform.iOS.ColorExtensions 類別內定義的延伸方法,使用這樣的方法來處理,可以將 Xamarin.Forms 內的顏色物件,轉換成為 Xamarin.iOS內的 UIColor 物件。這裡宣告了背景與文字顏色。
        public static UIColor AccentColor = ExportedColors.AccentColor.ToUIColor();
        public static UIColor TextColor = ExportedColors.InverseTextColor.ToUIColor();
在 FinishedLaunching 方法內,加入底下程式碼
這裡使用了原生 iOS 專案內的 UINavigationBar 類別,進行設定狀態列的背景與文字顏色。
            UINavigationBar.Appearance.BarTintColor = AccentColor;
            UINavigationBar.Appearance.TintColor = TextColor;
            UINavigationBar.Appearance.TitleTextAttributes = new UIStringAttributes
            {
                ForegroundColor = UIColor.White,
            };
Xamarin-跨平台手機應用程式設計入門-粉絲團

Xamarin FAQ 1-25 : 如何變更 Android 應用程式的狀態列背景與文字顏色

問題

當您在規劃一個 Xamarin.Forms 的應用程式的時候,都會制訂一套配色規則,並且每個頁面與控制項,都會依照這套視覺設計規範,進行套版設計;可是,當您在 Android 平台執行這個應用程式時候,卻發現到狀態列的背景與文字顏色似乎沒有地方可以修改,這該如何處理呢?

解答

您需要在 Android 原生專案內找到這個應用程式的進入點
請開啟 MainActivity.cs 檔案,找到 MainActivity 這個類別的定義處,在 MainActivity 的上方,加入了 Theme = "@style/MyTheme.Base" 這樣的宣告,表示這個應用程式要使用這個 XML 內定義的樣式配置定義。
    [Activity(Theme = "@style/MyTheme.Base", //Indicates the theme to use for this activity
        Label = "你的應用程式名稱",
               MainLauncher = true, //Set it as boot activity
        ScreenOrientation = ScreenOrientation.Portrait)]
    public class MainActivity : global::Xamarin.Forms.Platform.Android.FormsAppCompatActivity
    {
        ...
    }
接著,請在原生 Android 專案內,找到 Resources > values > styles.xml 檔案,將這個檔案置換成為底下內容,在這裡,您就會看到了 MyTheme.Base 的定義。
<resources>
  <style name="MyTheme" parent="MyTheme.Base">
  </style>
  <style name="MyTheme.Base" parent="Theme.AppCompat.Light.NoActionBar">
    <item name="colorPrimary">@color/primary</item>
    <item name="colorPrimaryDark">@color/primaryDark</item>
    <item name="colorAccent">@color/accent</item>
    <!--<item name="android:windowBackground">@color/window_background</item>-->

    <item name="android:windowBackground">@drawable/splash</item>
    <item name="android:windowNoTitle">true</item>
  </style>
</resources>
而在 MyTheme.Base 定義內,使用到許多的顏色定義,這個時候,請找到 Resources > values > colors.xml 檔案,將這個檔案置換成為底下內容,這裡就是定義 Android 應用程式狀態列的背景與文字顏色的地方。
<resources>
  <color name="primary">#223344</color>
  <color name="primaryDark">#aabbcc</color>
  <color name="accent">#998877</color>
  <color name="window_background">#168168</color>
</resources>
Xamarin-跨平台手機應用程式設計入門-粉絲團

Xamarin FAQ 1-26 : 如何變更 UWP 應用程式的狀態列背景與文字顏色

問題

當您在規劃一個 Xamarin.Forms 的應用程式的時候,都會制訂一套配色規則,並且每個頁面與控制項,都會依照這套視覺設計規範,進行套版設計;可是,當您在 UWP 平台執行這個應用程式時候,卻發現到狀態列的背景與文字顏色似乎沒有地方可以修改,這該如何處理呢?

解答

首先,請在原生 UWP 專案內,加入 擴充功能 的 Windows Desktop Extensions for the UWP / Windows Mobile Extensions for the UWP 的參考到您的專案內,如果您的 UWP 應用程式只需要在 Windows 下執行,後者可以不用加入;若您的 UWP 應用程式只需要在手機上執行,前者可以不用加入。
請在原生 UWP 專案內開啟 App.xaml.cs 檔案,將底下程式碼加入到 OnLaunched 方法內。
其中,要使用 ApiInformation.IsTypePresent 來判斷是平板模式還是手機模式,接著取得 Title 列 / 狀態列的物件,將您要設定背景與文字顏色設定到這些物件內即可。
//PC 平板模式的 TitleBar 客製化程式碼
if (ApiInformation.IsTypePresent("Windows.UI.ViewManagement.ApplicationView"))
{
    var titleBar = ApplicationView.GetForCurrentView().TitleBar;
    if (titleBar != null)
    {
        titleBar.ButtonBackgroundColor = Colors.DarkBlue;
        titleBar.ButtonForegroundColor = Colors.White;
        titleBar.BackgroundColor = Colors.Blue;
        titleBar.ForegroundColor = Colors.White;
    }
 }

//Mobile 模式的 Status 客製化程式碼
if (ApiInformation.IsTypePresent("Windows.UI.ViewManagement.StatusBar"))
{

    var statusBar = StatusBar.GetForCurrentView();
    if (statusBar != null)
    {
        statusBar.BackgroundOpacity = 1;
        statusBar.BackgroundColor = Colors.DarkBlue;
        statusBar.ForegroundColor = Colors.White;
    }
}
Xamarin-跨平台手機應用程式設計入門-粉絲團

Xamarin FAQ 1-27 : 不同系統平台下,導航頁面的返回按鈕文字問題

問題

在進行跨平台應用程式開發的時候,需要面臨到使用一套UI定義,便能夠在不同作業系統下來執行;不過,由於 Xamarin.Forms 採用原生平台控制項來顯示,因此,在 Xamarin.Forms 中同樣的 UI 控制項,可能會在不同作業系統下有著不同的表現。其中,導航工具列就其中一個。導航工具列在不同作業系統下到底呈現樣貌是怎麼樣,有甚麼要特別注意的地方呢?

解答

對於 Xamarin.Forms 中的導航頁面,在各個平台下呈現與操作方式都不太一樣,我們先來看看兩個比較簡單樣貌與操作的平台,那就是 Android & UWP
  • Android
    在下圖,是這個範例應用程式的首頁,由於這是個導航頁面,所以,在最上方有導航工具列。
    在 Android 平台下,第一個頁面的名稱(Title)會出現在左上方,在這個頁面中,我們實作了一個按鈕,當按下了這個按鈕,將會導航到第二個頁面。
    在下圖,為導航到第二個頁面的樣貌,同樣的,這個頁面的名稱(Title)會出現在左上方,不過,在頁面名稱的左邊,有個箭頭,那是回上一頁的按鈕,當您按下這個按鈕,就會回到上一個頁面,也就是上圖的首頁;當然,在 Android 平台下,您也可以使用實體回上一頁按鍵,按下這個按鍵,一樣可以回到上一頁。
  • UWP
    在下圖,是這個範例應用程式的首頁,由於這是個導航頁面,所以,在最上方有導航工具列。
    在 UWP 平台下,第一個頁面的名稱(Title)會出現在左上方,在這個頁面中,我們實作了一個按鈕,當按下了這個按鈕,將會導航到第二個頁面。
    在下圖,為導航到第二個頁面的樣貌,同樣的,這個頁面的名稱(Title)會出現在左上方,然而,在頁面名稱的左邊,並沒有如同 Android 平台的回上一頁箭頭,當您要回到上一個頁面,可以透過 UWP 手機中的實體回上一頁按鍵來回到上一頁。
  • iOS
    最為複雜的 iOS 平台,在 iOS 平台下,導航頁面的首頁如同下圖,該頁面的名稱(Title)是出現在螢幕的最上方的中間區域,,在這個頁面中,我們實作了一個按鈕,當按下了這個按鈕,將會導航到第二個頁面。
    預設來說,第二頁如同下圖,新頁面名稱依舊出現在螢幕最上方的中間區域,而在螢幕左上方,會如同 Android 平台,會有個回上一頁按鈕並緊接著上一頁的頁面名稱;不過,在這裡,您看到的是 < Back這樣的內容,會出現這樣是因為上一頁頁面名稱的文字過長,無法在完全顯示出來,因此,就會顯示 < Back 。
    像這樣的問題,可以有兩種解法,首先,就是要縮點第一個頁面名稱的長度,使其不會因為名稱文字過長,導致顯示不出來;在下圖中,我們將頁面名稱修改成為 多奇數位創意 ,僅僅六個中文字,這樣就可以在第二頁出現了首頁頁面的名稱。
    經過調整首頁頁面名稱長度僅有六個中文字,這樣,在第二頁面就會顯示如下圖。
    這樣做也是可能會遇到問題,那就是每支手機的螢幕解析度與尺寸規格都不盡相同,有時候六個中文字在 A 手機上可以完全顯示出來,可以在 B 裝置上可能會有無法顯示地問提。
    第二種作法則是比較安全的作法,那就是自行指定回上一頁按鈕文字的名稱,在這裡,我們希望第二頁的回上一頁文字要顯示 回去了,此時,您需要在第一個頁面,也就是首頁,的頁面建構式內,使用這個方法 NavigationPage.SetBackButtonTitle(this, "回去了");,便可以設定第二頁的回上一頁按鈕文字。
Xamarin-跨平台手機應用程式設計入門-粉絲團

Xamarin FAQ 1-28 : 不同系統平台下,導航頁面的返回按鈕文字問題2

問題

延續 Xamarin FAQ 1-28 問題,發現到在某些情況下,應用程式在 iOS 平台下執行的時候,會造成導航頁面的頁面說明文字無法置中對齊,而被擠向右方,這是甚麼情況?

解答

會發現這個問題是之前都是使用 iPhone 6 Plus iOS 9.3 Simulator 來進行測試,偶而發現到,當使用了 iPhone 6s iOS 9.3 這個 Simulator 來測試的時候,發現到這樣的問題。
下面四張圖片,分別為從首頁導航到第二頁的頁面截圖,從前面三個畫面截圖可以很清楚的看出,這個頁面的標題文字 這是第二頁 明顯的被往右推過去了,這將會造成使用者覺得這樣的設計十分奇怪;不過,我猜想這應該是 iOS 本身的一個問題,而不是 Xamarin.Forms 這裡的問題。最後一張圖則是我們想要的樣貌,這個頁面的標題是置中的,而且,上一頁的頁面標題則是適當的被截掉。
因此,我個人認為比較好的解決方案,還是要自行定義出回上一頁按鈕名稱,而不需要使用上一頁面的名稱來做為回上一頁按鈕的名稱。
這裡提供另外一個不需要使用 Call behind 的方法,那就是可以在 XAML 頁面中來定義這個回上一頁按鈕的名稱,不過,特別重要的是:回上一頁按鈕名稱,必須定義在上一頁的XAML中
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             xmlns:prism="clr-namespace:Prism.Mvvm;assembly=Prism.Forms"
             prism:ViewModelLocator.AutowireViewModel="True"
             x:Class="XFNavigationTitle.Views.MainPage"
             NavigationPage.BackButtonTitle="回去了"
             Title="{Binding PageTitle}">

    <StackLayout HorizontalOptions="Fill" VerticalOptions="Start"
                 Margin="20,20,20,20"
                 >
        <Label Text="{Binding Title}"
               Margin="0,0,0,30"/>

        <Label Text="這個頁面名稱" />
        <Entry Text="{Binding PageTitle}" />
        <Button Text="測試回上一頁文字" Command="{Binding 測試回上一頁文字Command}" />
    </StackLayout>
</ContentPage>
Xamarin-跨平台手機應用程式設計入門-粉絲團

Xamarin FAQ 1-29 : 如何客製導航抽屜的抽屜面板

問題

使用 Xamarin.Forms 開發一個導航抽屜頁面 ( MasterDetailPage ) ,您會發現到在 Android 平台下,當抽屜從左往右滑動出來,狀態列會被遮蓋掉,若想解決這類抽屜上的相關問題 ( 變更抽屜寬度、暫時隱藏狀態列 ),這些需求該如何處理呢?

解答

底下的螢幕截圖將會在 Android 平台下執行的結果,這裡範例專案中,一開始是提供一個 MasterDetailPage / NavigationPage / ContentPage,執行結果如下:
若沒有特別設定的情況下,當我們點選了左上方的漢堡按鈕,會推出一個面板,但是,這個面板會佔據調螢幕最上方的狀態列。
此時,若想要設計出這樣的效果,當導航抽屜推出來的時候,不要遮蔽掉最上方的狀態列,甚至上方的工具列的工具列,您可以在 MasterDetailPage.Master 這個屬性內的 ContentPage 來指定抽屜的上方要內縮一小段距離,這樣就不會把狀態列或者工具列給遮蔽掉了。例如,底下的 XAML 範例中,就是使用了 ContentPage.Padding 屬性來設定;經過這樣的設定,導航抽屜的顯示效果如下圖所示。
<?xml version="1.0" encoding="utf-8" ?>
<MasterDetailPage xmlns="http://xamarin.com/schemas/2014/forms"
                  xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
                  xmlns:prism="clr-namespace:Prism.Mvvm;assembly=Prism.Forms"
                  prism:ViewModelLocator.AutowireViewModel="True"
                  x:Class="XFMDStatusBar.Views.MDPadding">

    <MasterDetailPage.Master>
        <ContentPage 
            Title="Master" 
            BackgroundColor="Transparent"
            Padding="0,80,0,0">
            <Grid>
                <BoxView
                    Color="Pink"/>
                <Label Text="「多奇數位創意」是一群擁有理想與信念的網際網路資源整合團隊,致力於達成「數位創意服務」的願景,追求不斷的卓越創新是我們的信念"
                       HorizontalOptions="Center" VerticalOptions="Center"
                       Margin="20"
                       TextColor="White"
                       />
            </Grid>
        </ContentPage>
    </MasterDetailPage.Master>

</MasterDetailPage>
接下來的需求那就是想要做到導航抽屜面板寬度不要這麼寬,此時,您可以參考底下的 XAML 宣告;此時,我們的最上方的工具列與狀態列不用被遮蔽掉的需求,可以在 ContentPage 內的 Grid 控制巷內,設定 Padding 的屬性值,定義上方內縮值。至於寬度上,同樣可以在 Grid 控制項上設定右側內縮,此時,這樣的執行效果會如下圖所示。
<?xml version="1.0" encoding="utf-8" ?>
<local:MyMD xmlns="http://xamarin.com/schemas/2014/forms"
                  xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
                  xmlns:prism="clr-namespace:Prism.Mvvm;assembly=Prism.Forms"
                  xmlns:local="clr-namespace:XFMDStatusBar"
                  prism:ViewModelLocator.AutowireViewModel="True"
                  x:Class="XFMDStatusBar.Views.MDRenderer">

    <MasterDetailPage.Master>
        <ContentPage 
            Title="Master" 
            BackgroundColor="Transparent">
            <Grid
                Margin="0,55,150,0"
                >
                <BoxView
                    Color="Yellow"/>
                <Label Text="「多奇數位創意」是一群擁有理想與信念的網際網路資源整合團隊,致力於達成「數位創意服務」的願景,追求不斷的卓越創新是我們的信念"
                       HorizontalOptions="Center" VerticalOptions="Center"
                       Margin="10"
                       TextColor="Black"
                       />
            </Grid>
        </ContentPage>
    </MasterDetailPage.Master>

</local:MyMD>
不過,在這個範例中您可以發現到,這個 XAML 頁面的根項目是 local:MyMD,不過,這個項目是個客製化控制項,這個類別是繼承 MasterDetailPage 類別,並且在 Android 平台下宣告一個 Renderer ,讓這個導航抽屜頁面執行的時候,是沒有狀態列;像是這樣的需求就可以透過底下程式碼來做到。
[assembly: ExportRenderer(typeof(MyMD), typeof(MyMDRenderer))]
namespace XFMDStatusBar.Droid
{
    public class MyMDRenderer : MasterDetailPageRenderer
    {
        public override void AddView(Android.Views.View child)
        {
            child.GetType().GetRuntimeProperty("TopPadding").SetValue(child, 0);
            var padding = child.GetType().GetRuntimeProperty("TopPadding").GetValue(child);

            base.AddView(child);
        }
    }
}
Xamarin-跨平台手機應用程式設計入門-粉絲團

Xamarin FAQ 1-30 : 如何確認我的開發環境可以順利進行 Xamarin.Forms 專案開發

問題

當要進行 Xamarin.Forms 專案開發的時候,最為重要,也是第一次接觸並想要利用 Xamarin 來開發跨平台應用程式的朋友最為頭痛的問題,那就是我的開發環境無法進行 Xamarin.Forms 的應用程式開發。不過,要解決無法順利進行 Xamarin.Forms的應用程式開發上的問題,您需要有一套SOP來逐步檢測問題發生在哪裡。

解答

在這裡,請您依照底下的程序進行操作。若您無法按照底下說明來進行下去,請將當時遇到的問題、錯誤訊息、螢幕截圖等相關情況,提列出來,以便進行分析問題在哪裡。

建立練習專案

在這裡先確認您是否可以順利的使用 Prism Template Pack 專案樣板來建立一個 Xamarin.Forms 的專案。
  1. 首先,開啟您的 Visual Studio 2015
  2. 接著透過 Visual Studio 2015 功能表,選擇這些項目 檔案 > 新增 > 專案 準備新增一個專案。
  3. 接著,Visual Studio 2015 會顯示 新增專案 對話窗,請在這個對話窗上,進行選擇 Visual C# > Prism > Prism Unity App (Xamarin.Forms)
  4. 接著,在最下方的 名稱 文字輸入盒處,輸入 XFSample 這個名稱,最後使用滑鼠右擊右下方的 確定按鈕。
  5. 當出現 PRISM PROJECT WIZARD 對話窗之後,請勾選 ANDROIDiOSUWP 這三個平台選項,並且點選 CREATE PROJECT 按鈕。
  6. 接著會看到 新的通用 Windows 專案 對話視窗,此時,您只需要按下 確定 按鈕即可,此時,專案精靈會繼續完成相關平台的專案建立工作。
  7. 最後,整個新的 Xamarin.Forms 專案就建立完成了。

Android 平台執行結果

  • 滑鼠右擊 原生 Android 專案
  • 選擇 設定為起始專案
  • 選擇您要執行的目的裝置或者模擬器
  • 按下 F5 開始進行偵錯
  • 此時您應該可以看到螢幕上看到這個文字 Hello from Xamarin.Forms and Prism

iOS 平台執行結果

  • 滑鼠右擊 原生 iOS 專案
  • 選擇 設定為起始專案
  • 選擇您要執行的目的裝置或者模擬器
  • 按下 F5 開始進行偵錯
  • 此時您應該可以看到螢幕上看到這個文字 Hello from Xamarin.Forms and Prism

UWP 平台執行結果

  • 滑鼠右擊 原生 UWP 專案
  • 選擇 設定為起始專案
  • 選擇您要執行的目的裝置或者模擬器
  • 按下 F5 開始進行偵錯
  • 此時您應該可以看到螢幕上看到這個文字 Hello from Xamarin.Forms and Prism
    +
Xamarin-跨平台手機應用程式設計入門-粉絲團

Xamarin FAQ 1-30 : 如何確認我的開發環境可以順利進行 Xamarin.Forms 專案開發

問題

當要進行 Xamarin.Forms 專案開發的時候,最為重要,也是第一次接觸並想要利用 Xamarin 來開發跨平台應用程式的朋友最為頭痛的問題,那就是我的開發環境無法進行 Xamarin.Forms 的應用程式開發。不過,要解決無法順利進行 Xamarin.Forms的應用程式開發上的問題,您需要有一套SOP來逐步檢測問題發生在哪裡。

解答

在這裡,請您依照底下的程序進行操作。若您無法按照底下說明來進行下去,請將當時遇到的問題、錯誤訊息、螢幕截圖等相關情況,提列出來,以便進行分析問題在哪裡。

建立練習專案

在這裡先確認您是否可以順利的使用 Prism Template Pack 專案樣板來建立一個 Xamarin.Forms 的專案。
  1. 首先,開啟您的 Visual Studio 2015
  2. 接著透過 Visual Studio 2015 功能表,選擇這些項目 檔案 > 新增 > 專案 準備新增一個專案。
  3. 接著,Visual Studio 2015 會顯示 新增專案 對話窗,請在這個對話窗上,進行選擇 Visual C# > Prism > Prism Unity App (Xamarin.Forms)
  4. 接著,在最下方的 名稱 文字輸入盒處,輸入 XFSample 這個名稱,最後使用滑鼠右擊右下方的 確定按鈕。
  5. 當出現 PRISM PROJECT WIZARD 對話窗之後,請勾選 ANDROIDiOSUWP 這三個平台選項,並且點選 CREATE PROJECT 按鈕。
  6. 接著會看到 新的通用 Windows 專案 對話視窗,此時,您只需要按下 確定 按鈕即可,此時,專案精靈會繼續完成相關平台的專案建立工作。
  7. 最後,整個新的 Xamarin.Forms 專案就建立完成了。

Android 平台執行結果

  • 滑鼠右擊 原生 Android 專案
  • 選擇 設定為起始專案
  • 選擇您要執行的目的裝置或者模擬器
  • 按下 F5 開始進行偵錯
  • 此時您應該可以看到螢幕上看到這個文字 Hello from Xamarin.Forms and Prism

iOS 平台執行結果

  • 滑鼠右擊 原生 iOS 專案
  • 選擇 設定為起始專案
  • 選擇您要執行的目的裝置或者模擬器
  • 按下 F5 開始進行偵錯
  • 此時您應該可以看到螢幕上看到這個文字 Hello from Xamarin.Forms and Prism

UWP 平台執行結果

  • 滑鼠右擊 原生 UWP 專案
  • 選擇 設定為起始專案
  • 選擇您要執行的目的裝置或者模擬器
  • 按下 F5 開始進行偵錯
  • 此時您應該可以看到螢幕上看到這個文字 Hello from Xamarin.Forms and Prism

2017/01/30

Xamarin FAQ 1-29 : 如何客製導航抽屜的抽屜面板

問題

使用 Xamarin.Forms 開發一個導航抽屜頁面 ( MasterDetailPage ) ,您會發現到在 Android 平台下,當抽屜從左往右滑動出來,狀態列會被遮蓋掉,若想解決這類抽屜上的相關問題 ( 變更抽屜寬度、暫時隱藏狀態列 ),這些需求該如何處理呢?

解答

底下的螢幕截圖將會在 Android 平台下執行的結果,這裡範例專案中,一開始是提供一個 MasterDetailPage / NavigationPage / ContentPage,執行結果如下:
若沒有特別設定的情況下,當我們點選了左上方的漢堡按鈕,會推出一個面板,但是,這個面板會佔據調螢幕最上方的狀態列。
此時,若想要設計出這樣的效果,當導航抽屜推出來的時候,不要遮蔽掉最上方的狀態列,甚至上方的工具列的工具列,您可以在 MasterDetailPage.Master 這個屬性內的 ContentPage 來指定抽屜的上方要內縮一小段距離,這樣就不會把狀態列或者工具列給遮蔽掉了。例如,底下的 XAML 範例中,就是使用了 ContentPage.Padding 屬性來設定;經過這樣的設定,導航抽屜的顯示效果如下圖所示。
<?xml version="1.0" encoding="utf-8" ?>
<MasterDetailPage xmlns="http://xamarin.com/schemas/2014/forms"
                  xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
                  xmlns:prism="clr-namespace:Prism.Mvvm;assembly=Prism.Forms"
                  prism:ViewModelLocator.AutowireViewModel="True"
                  x:Class="XFMDStatusBar.Views.MDPadding">

    <MasterDetailPage.Master>
        <ContentPage 
            Title="Master" 
            BackgroundColor="Transparent"
            Padding="0,80,0,0">
            <Grid>
                <BoxView
                    Color="Pink"/>
                <Label Text="「多奇數位創意」是一群擁有理想與信念的網際網路資源整合團隊,致力於達成「數位創意服務」的願景,追求不斷的卓越創新是我們的信念"
                       HorizontalOptions="Center" VerticalOptions="Center"
                       Margin="20"
                       TextColor="White"
                       />
            </Grid>
        </ContentPage>
    </MasterDetailPage.Master>

</MasterDetailPage>
接下來的需求那就是想要做到導航抽屜面板寬度不要這麼寬,此時,您可以參考底下的 XAML 宣告;此時,我們的最上方的工具列與狀態列不用被遮蔽掉的需求,可以在 ContentPage 內的 Grid 控制巷內,設定 Padding 的屬性值,定義上方內縮值。至於寬度上,同樣可以在 Grid 控制項上設定右側內縮,此時,這樣的執行效果會如下圖所示。
<?xml version="1.0" encoding="utf-8" ?>
<local:MyMD xmlns="http://xamarin.com/schemas/2014/forms"
                  xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
                  xmlns:prism="clr-namespace:Prism.Mvvm;assembly=Prism.Forms"
                  xmlns:local="clr-namespace:XFMDStatusBar"
                  prism:ViewModelLocator.AutowireViewModel="True"
                  x:Class="XFMDStatusBar.Views.MDRenderer">

    <MasterDetailPage.Master>
        <ContentPage 
            Title="Master" 
            BackgroundColor="Transparent">
            <Grid
                Margin="0,55,150,0"
                >
                <BoxView
                    Color="Yellow"/>
                <Label Text="「多奇數位創意」是一群擁有理想與信念的網際網路資源整合團隊,致力於達成「數位創意服務」的願景,追求不斷的卓越創新是我們的信念"
                       HorizontalOptions="Center" VerticalOptions="Center"
                       Margin="10"
                       TextColor="Black"
                       />
            </Grid>
        </ContentPage>
    </MasterDetailPage.Master>

</local:MyMD>
不過,在這個範例中您可以發現到,這個 XAML 頁面的根項目是 local:MyMD,不過,這個項目是個客製化控制項,這個類別是繼承 MasterDetailPage 類別,並且在 Android 平台下宣告一個 Renderer ,讓這個導航抽屜頁面執行的時候,是沒有狀態列;像是這樣的需求就可以透過底下程式碼來做到。
[assembly: ExportRenderer(typeof(MyMD), typeof(MyMDRenderer))]
namespace XFMDStatusBar.Droid
{
    public class MyMDRenderer : MasterDetailPageRenderer
    {
        public override void AddView(Android.Views.View child)
        {
            child.GetType().GetRuntimeProperty("TopPadding").SetValue(child, 0);
            var padding = child.GetType().GetRuntimeProperty("TopPadding").GetValue(child);

            base.AddView(child);
        }
    }
}