XAML in Xamarin.Forms 基礎篇 電子書

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

Xamarin.Forms 快速入門 電子書

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

2017/06/09

UML 表示說明

UML是一種開放的方法,用於說明、可視化、構建和編寫一個正在開發的、物件導向的、軟體密集系統的製品的開放方法。更多資訊可以參考 UML
底下的 UML 示意圖片使用 PowerPoint 製作出來,因為,在 PowerPoint 內無法做出空心箭頭的線條,因此,所有的空心箭頭,將會以實心箭頭來表示。

類別 / 抽象類別 / 介面

共需分三塊,上層,標示出 類別 / 抽象類別 / <> 介面的名稱。
中間區域,則是用來標示狀態,通常可以標示 Property 屬性。
最後一塊區域,則是說明其可以使用方法。

繼承

這裡是用來標示兩個實體間的 is-a 的關係
類別的繼承,使用實體線段與實心箭頭的線段將其連接起來。
而介面的實作部分,則是使用虛線與實心箭頭的線段將其連接起來。

組合

這裡是用來標示兩個實體間的 has-a 的關係
使用虛線與開放箭頭的線段將其連接起來。

程式碼片段

一個範例

請示著解讀底下的 UML 是在表示甚麼樣的關係呢?

2017/06/06

Xamarin.Android 各種封存屬性測試

在這篇 Xamarin 筆記中,將會針對 https://github.com/vulcanlee/XamarinHandsOnLab/tree/master/XFTask 專案,測試不同的專案選項,所封存的 apk 檔案大小。
在這裡,所有的測試都是在 Release 建置,並且使用專案屬性的這四種設定選項。而且,另種測試結果的 APK 檔案,將會可以從這裡取得 https://github.com/vulcanlee/XamarinHandsOnLabBuild
  • 連結器
  • 將組譯碼組合成機器碼
  • AOT 編譯
  • 使用 LLVM 最佳化編譯器
我們進行了六種組合模式的 Xamarin.Android APK 檔案的封存,得到這些模式下所產生的 APK 檔案大小。從底下的測試結果,我們看到了,只要當我們把可以產生原生碼的功能( 將組譯碼組合成機器碼 / 使用 LLVM 最佳化編譯器) 功能開啟之後,在這個測試專案下,我們可以看得出,所得到的 APK 檔案就會變得比較大。
模式APK大小
模式151.5 MB
模式223.3 MB
模式3126 MB
模式463.9 MB
模式5132 MB
模式664.3 MB
當我們沒有開啟 將組譯碼組合成機器碼 模式,這個專案內的所有組件將會存在於 APK 檔案內的 assemblies目錄下,底下將是模式1的 APK 檔案架構。
模式11
我們可以切換到 assemblies 目錄下,並且以組件檔案大小作排列,我們看到,最大的檔案那就是 Mono.Android.dll 這個組件,大小為 21.5 MB
模式12
可是,當我們查看模式2 (連結器:僅限 SDK 組譯碼) 的狀態下的 APK 檔案,切換到 assemblies 目錄下,並且以組件檔案大小作排列,我們看到,最大的檔案那就是 mscorlib.dll 這個組件,大小為 2.10 MB
所以,我們知道,當啟用了連結器模式,我們所產生的 APK 檔案大小將會明顯的小了許多,而且,就如同 Xamarin 官方文件對於連結器的說明文件描述一下,連結器會將這個專案內,沒有用到的類別、方法等等,從組件中移除,這樣將會使得您的 APK 檔案大幅瘦身下來。
模式21
至於要使用哪種專案屬性模式,來建置您的最終封存的檔案,就取決於您的決定了。

模式1

連結器:無
將組譯碼組合成機器碼:無選取
AOT 編譯:無選取
使用 LLVM 最佳化編譯器:無選取

模式2

連結器:僅限 SDK 組譯碼
將組譯碼組合成機器碼:無選取
AOT 編譯:無選取
使用 LLVM 最佳化編譯器:無選取

模式3

連結器:無
將組譯碼組合成機器碼:選取
AOT 編譯:選取
使用 LLVM 最佳化編譯器:選取

模式4

連結器:僅限 SDK 組譯碼
將組譯碼組合成機器碼:選取
AOT 編譯:選取
使用 LLVM 最佳化編譯器:選取

模式5

連結器:無
將組譯碼組合成機器碼:無選取
AOT 編譯:選取
使用 LLVM 最佳化編譯器:選取

模式6

連結器:僅限 SDK 組譯碼
將組譯碼組合成機器碼:無選取
AOT 編譯:選取
使用 LLVM 最佳化編譯器:選取

2017/06/02

升級到 Windows 10 Creators Update後,Visual Studio for Android Emulator 無法上網了

今天中午,我的電腦終於收到了 Windows 10 Creators Update 的升級推播通知,並且要求我要立即重新開機,這個時候,當然是要進行升級更新;當系統重新開機,花費了一些時間將 Windows 10 Creators Update 安裝完成後,當然是要繼續進行手頭上的工作。
可是,悲慘的問題來了,當我準備要進行剛剛開發到一半的 Xamarin.Forms 專案,繼續進行除錯的時候,此時模擬器啟動之後,出現了底下對話窗:
The emulator requires an Internet connection to start. Do you want to configure the emulator to connect to the Internet?
Your computer might lose network connectivity while these changes are applied. This might affect existing network operations.
詢問是否要上網
我立馬反應的點下了  這個按鈕,可是,當模擬器啟動之後,卻發現到所啟動的 Android 模擬器,無法連接上網路。
詢問是否要上網
若您也發生了這樣的問題,可以參考底下步驟來解決此一問題。
  • 請先關閉所有開啟的 Visual Studio for Android Emulator 模擬器
  • 開啟 Hyper-V 管理員
  • 從虛擬機器的清單中,找到您的 Android 模擬器
    在這裡,我選擇的是 VS Emulator 5.2-inch Marshmallow XXHDPI Phone 這個虛擬機器
    虛擬機器設定
  • 我們從這個模擬器的虛擬機器設定內容上,看到了一個問題,那就是這個虛擬機器原本是要有兩張網卡連接到這個虛擬機器上的,可是,現在只剩下一張網卡,而且,這張網卡卻是連接到內部網路之用的網卡;也就是說,要連接到 Internet 上的那張網卡不見了。
    Android虛擬機器設定內容
  • 請您參考上圖,點選數字1 的標示處:新增硬體
  • 在右半部區域,點選 網路介面卡
  • 接著點選 新增 按鈕
  • 接著,這台虛擬機器多了一個新硬體,就是剛剛加入的 網路介面卡
  • 請點選這張新的 網路介面卡,然後,在右半部的 虛擬交換器 下拉選單中,選擇您可以上 Inetnet 的網卡。
  • 完成後,請點選 確定 按鈕
    加入一張新的虛擬網卡
  • 最後,請重新啟動您的 Visual Studio for Android Emulator 模擬器
  • 一樣會出現系圖對話窗,請點選  按鈕
    詢問是否要上網
  • 當模擬器出現的時候,您會在右上角狀態列區域,看到這個模擬器已經連接上網路了,而且打開瀏覽器,確認是可以讀取到網路上的網站網頁內容。
詢問是否要上網

Hyper-V 升級更新

2017/05/20

Pull 所有目錄的 Git Repository

因為工作需要,所以,使用了兩台電腦,可是,之前經常要把這兩台電腦上的 Git Repository 做同步,都是使用手動方式,一個目錄一個目錄的下 Pull 命令。
今天正好有空,根據網路上找到的參考資訊,修改成我自己需要的同步 Script。
我的狀況是,我都會把 Repositories 都放在同一個目錄下,透過底下的 PowerShell Script,便可以逐一針對每個目錄,執行 Pull 命令,對我來說,真的節省了太多時間了。
$git = $env:programfiles+"\Git\cmd\git.exe";
Write-Host $git
if (!$git) {
  Write-Host "Something went wrong. Please enter the path to git.cmd or git.exe:";
  $git = Read-Host;
  Set-Variable -Name git -Value $git;
}
ls -name -Exclude *.* | foreach {Write-Host $_;cd .\$_ ; & $git pull origin master  2> $null ; cd ..}
Write-Host "Done.";
cmd /c pause | out-null

2017/05/16

使用 Iconize 在螢幕上顯示字體圖示

若想要在您的 Xamarin.Forms 應用程式中顯示出字體圖示,例如, Font Awesome,在以往,您都需要每個專案內做關於這個字體的設定,並且需要根據平台需求,產生一個客製化的控制項。如今,想要做到這件事情,不再需要這麼麻煩的程序了,您只需要使用 Iconize Plugin 這個套件,就可以做到了。
在這篇文章中,將會測試如何在三個平台 Android/iOS/UWP,透過 Iconize Plugin 的幫助,設計出一個輸入帳號與密碼的頁面。
感謝 acaliaro 寫的這篇文章 How to create a nice rouded icon ,讓我可以順利測試出如何使用 Iconize 這個套件的使用方式。

安裝與設定相關套件

進行 Iconize 相關套件的安裝

在這裡,我們已經使用 Prism Template Pack 建立起一個支援 Android/iOS/UWP 的 Xamarin.Forms 方案,我們首先要做的事情,就是要安裝 Iconize Plugin 相關套件。
首先,請將這兩個套件,安裝到所有的專案內 Xam.Plugin.Iconize / Xam.FormsPlugin.Iconize
接著,可以依據您的喜好或者需求,選擇適合您的字體圖示,安裝相對應的套件
在這裡,我將會使用 Xam.Plugin.Iconize.FontAwesome 這個 Font Awesome 字型圖示作為展示範例,因此,請在您的方案中,除了核心PCL專案除外,各個原生專案都要安裝 Xam.Plugin.Iconize.FontAwesome這個套件。
若您在安裝相關自行套件 (Xam.Plugin.Iconize.FontAwesome)的時候,有勾選核心PCL專案,則會出現這個錯誤訊息: 無法安裝封裝 'Xam.Plugin.Iconize.FontAwesome 1.0.10'。您正嘗試將此封裝安裝到以 '.NETPortable,Version=v4.5,Profile=Profile259' 為目標的專案,但該封裝不包含任何與架構相容的組件參考或內容檔。如需詳細資訊,請連絡封裝作者。
這個時候,請取消核心PCL專案,勾選其他原生專案,重新安裝這個套件即可。
若想要進一步了解這些字體圖示有哪些內容,可以參考

進行 Iconize 的原生專案初始化設定

Android 專案的設定

請在 Android 原生專案內,打開 MainActivity.cs,找到 OnCreate 方法,將程式碼置換如下:
其中,使用 .With(new Plugin.Iconize.Fonts.FontAwesomeModule()) 方法來指定需要載入的字型圖示模組;而 FormsPlugin.Iconize.Droid.IconControls.Init 則是用來進行 Xamarin.Forms 需要用到的控制項初始化。
        protected override void OnCreate(Bundle bundle)
        {
            TabLayoutResource = Resource.Layout.tabs;
            ToolbarResource = Resource.Layout.toolbar;

            base.OnCreate(bundle);

            #region 進行 Iconize 套件的初始化
            Plugin.Iconize.Iconize
                .With(new Plugin.Iconize.Fonts.FontAwesomeModule());
            FormsPlugin.Iconize.Droid.IconControls.Init(Resource.Layout.toolbar, Resource.Layout.tabs);
            #endregion

            global::Xamarin.Forms.Forms.Init(this, bundle);
            LoadApplication(new App(new AndroidInitializer()));
        }
您可以一次安裝多個字體套件,這個時候,僅需要連續呼叫 With 方法即可,類似這樣:
            Plugin.Iconize.Iconize
                      .With(new Plugin.Iconize.Fonts.FontAwesomeModule())
                      .With(new Plugin.Iconize.Fonts.IoniconsModule());

iOS 專案的設定

請在 iOS 原生專案內,打開 AppDelegate.cs,找到 FinishedLaunching 方法,將程式碼置換如下:
其中,使用 .With(new Plugin.Iconize.Fonts.FontAwesomeModule()) 方法來指定需要載入的字型圖示模組;而 FormsPlugin.Iconize.iOS.IconControls 則是用來進行 Xamarin.Forms 需要用到的控制項初始化。
        public override bool FinishedLaunching(UIApplication app, NSDictionary options)
        {
            #region 進行 Iconize 套件的初始化
            Plugin.Iconize.Iconize
                .With(new Plugin.Iconize.Fonts.FontAwesomeModule());
            FormsPlugin.Iconize.iOS.IconControls.Init();
            #endregion

            global::Xamarin.Forms.Forms.Init();
            LoadApplication(new App(new iOSInitializer()));

            return base.FinishedLaunching(app, options);
        }
另外,我們還需要修正 `Info.plist' 檔案內容,在這個檔案內,需要加入底下宣告。
  <key>UIAppFonts</key>
  <array>
    <string>iconize-fontawesome.ttf</string>
    <string>iconize-material.ttf</string>
    <string>iconize-meteocons.ttf</string>
    <string>iconize-typicons.ttf</string>
  </array>

UWP 專案的設定

請在 UWP 原生專案內,打開 App.xaml.cs,找到 OnLaunched 方法,將程式碼置換如下:
其中,使用 .With(new Plugin.Iconize.Fonts.FontAwesomeModule()) 方法來指定需要載入的字型圖示模組;而 FormsPlugin.Iconize.UWP.IconControls 則是用來進行 Xamarin.Forms 需要用到的控制項初始化。
        protected override void OnLaunched(LaunchActivatedEventArgs e)
        {

#if DEBUG
            if (System.Diagnostics.Debugger.IsAttached)
            {
                this.DebugSettings.EnableFrameRateCounter = true;
            }
#endif

            Frame rootFrame = Window.Current.Content as Frame;

            // Do not repeat app initialization when the Window already has content,
            // just ensure that the window is active
            if (rootFrame == null)
            {
                // Create a Frame to act as the navigation context and navigate to the first page
                rootFrame = new Frame();

                rootFrame.NavigationFailed += OnNavigationFailed;

                #region 進行 Iconize 套件的初始化
                Plugin.Iconize.Iconize
                    .With(new Plugin.Iconize.Fonts.FontAwesomeModule());
                FormsPlugin.Iconize.UWP.IconControls.Init();
                #endregion


                Xamarin.Forms.Forms.Init(e);

                if (e.PreviousExecutionState == ApplicationExecutionState.Terminated)
                {
                    //TODO: Load state from previously suspended application
                }

                // Place the frame in the current Window
                Window.Current.Content = rootFrame;
            }

            if (rootFrame.Content == null)
            {
                // When the navigation stack isn't restored navigate to the first page,
                // configuring the new page by passing required information as a navigation
                // parameter
                rootFrame.Navigate(typeof(MainPage), e.Arguments);
            }
            // Ensure the current window is active
            Window.Current.Activate();
        }

Xamarin.Forms 的測試頁面

在這個範例中,我們需要設計一個使用者登入頁面,裡面需要讓使用者輸入帳號與密碼。我們利用 Grid Layout 將螢幕切割成四塊區域。
在核心PCL專案中,我們使用 MainPage 做為測試頁面;因為在這個頁面內,需要使用 Iconize 所提供的 IconLabel 控制項,因此,需要先加入可以參考到這個控制項的命名空間,我們需要在 ContentPage 內,加入 xmlns:iconize="clr-namespace:FormsPlugin.Iconize;assembly=FormsPlugin.Iconize" 這樣的宣告,如此,在這個頁面內,就可以使用 iconize 前置詞,之後就可以引用 Iconize 所提供的控制項。
當我們需要顯示 Font Awesome 字型圖示的時候,就可以使用這樣的方式 <iconize:IconLabel Text="fa-user" TextColor="Blue" /> 顯示出一個藍色使用者圖示在螢幕上。至於 Text 屬性內的文字,您可以在 Font Awesome 網站中,找到不同圖示所代表的文字。
<?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"
             xmlns:iconize="clr-namespace:FormsPlugin.Iconize;assembly=FormsPlugin.Iconize"
             prism:ViewModelLocator.AutowireViewModel="True"
             x:Class="XFIconize.Views.MainPage"
             Title="使用者登入">

    <Grid
        Margin="30"
        HorizontalOptions="Fill" VerticalOptions="Center"
        >
        <Grid.RowDefinitions>
            <RowDefinition Height="*"/>
            <RowDefinition Height="*"/>
        </Grid.RowDefinitions>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="100"/>
            <ColumnDefinition Width="*"/>
        </Grid.ColumnDefinitions>

        <iconize:IconLabel
            Grid.Row="0" Grid.Column="0"
            HorizontalOptions="Center" VerticalOptions="Center"
            FontSize="60"
            Text="fa-user" TextColor="Blue" />
        <Entry
            Grid.Row="0" Grid.Column="1"
            HorizontalOptions="Fill" VerticalOptions="Center"
            Placeholder="請輸入帳號"/>

        <iconize:IconLabel
            Grid.Row="1" Grid.Column="0"
            HorizontalOptions="Center" VerticalOptions="Center"
            FontSize="60"
            Text="fa-keyboard-o" TextColor="Blue" />
        <Entry
            Grid.Row="1" Grid.Column="1"
            HorizontalOptions="Fill" VerticalOptions="Center"
            Placeholder="請輸入密碼"/>
    </Grid>
</ContentPage>

進行測試

Android

底下是我們在 Android 平台下執行結果螢幕截圖
Iconize Android

iOS

底下是我們在 iOS 平台下執行結果螢幕截圖
Iconize Android

UWP : Windows 10 Mobile

底下是我們在 UWP 平台下執行結果螢幕截圖
Iconize Android

範例專案原始碼