使用者登入
在這一章節,您需要完成一個應用程式,其共有兩個頁面;當使用者開啟這個應用程式之後,首先會看到一個使用者要輸入帳號與密碼的頁面,在這個頁面中,當使用者輸入密碼的時候,必須要有 * 遮罩,避免其他人看到輸入的密碼,接著按下登入按鈕後,當輸入的帳號與密碼符合規定,則會進入到首頁頁面。
在進入到首頁頁面之後,若使用者按下回上一頁按鈕,是無法再度回到登入頁面,而是會直接結束這個應用程式的執行。
在這個範例中,也會加入使用 Font Awesome 功能,讓您可以在 核心PCL 內的 XAML,使用
字型圖示
功能來顯示更加豐富的視覺圖片。建立使用者登入方案
- 首先,開啟您的 Visual Studio 2015
- 接著透過 Visual Studio 2015 功能表,選擇這些項目
檔案
>新增
>專案
準備新增一個專案。 - 接著,Visual Studio 2015 會顯示
新增專案
對話窗,請在這個對話窗上,進行選擇Visual C#
>Cross-Platform
>Blank Xaml App (Xamarin.Forms Portable)
- 接著,在最下方的
名稱
文字輸入盒處,輸入XamarinLogin
這個名稱,最後使用滑鼠右擊右下方的確定
按鈕。 - 當專案建立到一半,若您的開發環境還沒有建置與設定完成 Mac 電腦與 Xamarin Studio for Mac 系統,此時會看到
Xamarin Mac Agent Instructions
對話窗出現,這個對話窗是要提醒您進行與 Mac 電腦連線設定,這是因為,您無法在 Windows 作業系統進行 iOS 相關應用程式的建立與設計工作,而是需要透過 Mac 電腦安裝的 XCode 來協助您完成這些 iOS 應用程式的建立工作。不過,這不影響您繼續開發 Xamarin.Forms 的應用程式,只不過此時,您無法編譯與執行 iOS 的應用程式。 - 接著會看到
新的通用Windows專案
對話視窗,此時,您只需要按下確定
按鈕即可,此時,專案精靈會繼續完成相關平台的專案建立工作。 - 最後,整個新的 Xamarin.Forms 專案就建立完成了。
登入頁面
建立登入頁面
首先,要來建立一個登入頁面,先在方案總管內,找到 核心PCL 專案,在核心PCL 專案節點上,使用滑鼠右擊該節點,接著再彈出功能表中,選擇
加入
> 新增項目
在
加入新項目 - XamarinLogin
對話窗中,點擊 Visual C#
> Cross-Platform
> Forms Xaml Page
在下方名稱欄位右方的文字輸入盒中,輸入
LoginPage
,最後,右擊 新增
按鈕,完成新增登入頁面的工作。
在 核心PCL 專案內,找到
App.xaml
這個節點,展開該節點,會看到 App.xaml.cs
這個節點,使用滑鼠雙擊該 App.xaml.cs
這個節點,打開這個檔案。
在
App.xaml.cs
的建構式內,您會看到這個 Xamarin.Forms 應用程式,一旦啟動之後,會先開啟XamarinLogin.MainPage
這個頁面,作為該應用程式的起始顯示畫面,也就是整體 核心PCL 的進入點。 public App()
{
InitializeComponent();
MainPage = new XamarinLogin.MainPage();
}
由於,這個應用程式在啟動之後,會先要求使用者輸入帳號密碼,在驗證正確之後,才會進入到主畫面,所以,在此,需要修正該應用程式啟動之後,第一個顯示的畫面,必須為
LoginPage
頁面。
不過,因為當使用者輸入完成帳號與密碼之後,將會切換到 MainPage 頁面,因此,在這需要將第一個顯示頁面物件,放入
NavigationPage
建構式的參數內,產出出一個 NavigationPage
,再將其設定到App.MainPage
屬性上。 public App()
{
InitializeComponent();
var rootPage = new NavigationPage(new LoginPage());
MainPage = rootPage;
}
接著,需要修改登入頁面的視覺畫面與商業邏輯,請打開 核心PCL 專案內,剛剛新建立的
LoginPage.xaml
這個檔案。但當您在進行 XAML 宣告定義修改的時候,IntelliSense 沒有作用的話,請先重新編譯XamarinLogin
這個 核心PCL 專案。
在
LoginPage.xaml
頁面中的 ContentPage
頁面,使用到的 Title
這個屬性,定義了這個頁面的名稱。
在這個
LoginPage.xaml
頁面定義中,使用到一個 Grid
版面配置控制項,逐一將各個要顯示的控制項,透過 Grid.Row
這個附加屬性 (Attached Properties),指定控制項要放在 Grid 的哪個位置。若再Grid
版面配置控制巷內的任何控制項,沒有使用附加屬性來指定要放在 Grid 版面配置的哪個地方,則會預設使用Grid.Row="0" Grid.Column="0"
。
<Label Text="歡迎來到 Xamarin.Forms"
FontSize="40"
Grid.Row="0"
HorizontalTextAlignment="Center"
/>
上述的 Label 控制項,使用到了
HorizontalTextAlignment
,用來設定這個控制項要顯示的文字,需要置中顯示。<Entry Placeholder="請輸入密碼"
x:Name="entryPassword"
Grid.Row="4"
IsPassword="True" />
上述的
Entry
控制項,使用了 IsPassword="True"
屬性值,定義該文字輸入盒所輸入的任何文字,會使用遮罩來替換,避免所輸入的密碼,被他人看到。x:Name="entryPassword"
這個 x:Name
的延伸屬性用法,是要讓 Code Behind 的 C# 程式碼,可以存取這個控制項,亦即使用 entryPassword
這個變數名稱,就可以存取到這個控制項。
底下為修改 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"
x:Class="XamarinLogin.LoginPage"
Title="使用者登入"
>
<Grid
HorizontalOptions="FillAndExpand" VerticalOptions="Center"
Padding="30,0"
>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Label Text="歡迎來到 Xamarin.Forms"
FontSize="40"
Grid.Row="0"
HorizontalTextAlignment="Center"
/>
<Label Text="帳號"
Grid.Row="1"
/>
<Entry Placeholder="請輸入帳號"
x:Name="entryAccount"
Grid.Row="2"
HorizontalOptions="FillAndExpand"
/>
<Label Text="密碼"
Grid.Row="3"/>
<Entry Placeholder="請輸入密碼"
x:Name="entryPassword"
Grid.Row="4"
IsPassword="True" />
<Button Text="登入"
x:Name="buttonLogin"
Grid.Row="5"
HorizontalOptions="FillAndExpand"
/>
</Grid>
</ContentPage>
在
LoginPage.xaml.cs
Code Behind 程式碼內,首先看到建構式內,有呼叫NavigationPage.SetBackButtonTitle
這個方法,其目的是在於告知 NavigationPage
,當切換到別的頁面時候,需要設定 導航列 (Navigation Bar)
的返回按鈕旁的文字要顯示的內容。
其中,也在建構式中,定義了
buttonLogin
按鈕的點擊事件,當使用者點擊了登入按鈕,這個時候,會透過頁面內擁有 Navigation
屬性(這個屬性是 INavigation
類型),將要顯示的首頁物件,推到INavigation.NavigationStack
內,並且顯示這個頁面。
對於 Xamarin.Forms 系統而言,當要顯示一個新的頁面,就會將該新的頁面物件儲存到
INavigation.NavigationStack
內,採用的資料結構是屬於 Stack 堆疊
型式;當要從新的頁面返回到原先的頁面,Xamarin.Forms 系統會從 INavigation.NavigationStack
資料結構內,將正在顯示的頁面物件移除,並且還原到最初的頁面。
所以,當要切換到新的頁面與要返回到原先頁面,可以使用下列方法:
- 切換到新頁面 Navigation.PushAsync(NextPage)
- 回到原先頁面 Navigation.PopAsync()
底下為
LoginPage.xaml.cs
Code Behind 的程式碼using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Xamarin.Forms;
namespace XamarinLogin
{
public partial class LoginPage : ContentPage
{
public LoginPage()
{
InitializeComponent();
NavigationPage.SetBackButtonTitle(this, "回登入頁面");
buttonLogin.Clicked += ButtonLogin_Clicked;
}
private async void ButtonLogin_Clicked(object sender, EventArgs e)
{
// 切換到主頁面
var NextPage = new MainPage();
await Navigation.PushAsync(NextPage);
}
}
}
修改首頁頁面
在
MainPage.xaml
檔案中,只有在 ContentPage
物件內的 Title
屬性內,指定了這個頁面的名稱。<?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:XamarinLogin"
x:Class="XamarinLogin.MainPage"
Title="應用首頁"
>
<Label Text="Welcome to Xamarin Forms!"
VerticalOptions="Center"
HorizontalOptions="Center" />
</ContentPage>
在
MainPage.xaml.cs
Code Behind 檔案中,也只有在建構式方法內,使用NavigationPage.SetBackButtonTitle
方法定義了回上一頁按鈕要顯示的名稱。using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Xamarin.Forms;
namespace XamarinLogin
{
public partial class MainPage : ContentPage
{
public MainPage()
{
InitializeComponent();
NavigationPage.SetBackButtonTitle(this, "回到首頁");
}
}
}
執行察看結果
接下來看看分別在 Android 與 iOS 這兩個平台上,這個應用程式的執行結果。
Android 系統
- 請使用滑鼠右擊方案總管內的
XamarinLogin.Droid
專案節點,選擇設定為起始專案
項目。 - 確認建置組態是
Debug
與有指定相關模擬器,此就可以按下 F5 開始執行 - 執行結果畫面按下了 登入 按鈕,就會進入到首頁
iOS 系統
- 請使用滑鼠右擊方案總管內的
XamarinLogin.iOS
專案節點,選擇設定為起始專案
項目。 - 確認建置組態是
Debug
與有指定相關模擬器,此就可以按下 F5 開始執行 - 執行結果畫面按下了 登入 按鈕,就會進入到首頁
存在問題
當在 Android 平台上,進入到應用首頁頁面之後,若點擊了左上角的 應用首頁 文字旁的箭頭,則,這個應用程式會回到 使用者登入 的頁面中。
當在 iOS 平台上,進入到應用首頁頁面之後,若點擊了左上角的 回到登入頁面 區域,則,這個應用程式會回到 使用者登入 的頁面中。
這樣的操作流程,當然是不正確的,因為,一旦使用者登入進系統之後,除非選擇了登出作業,否則,應該是不能夠再度使用螢幕上的返回按鈕,或者手機的實體返回按鈕,讓這個應用程式,回到登入頁面上。因此,接下來,就來修正此一問題,當使用者成功能入之後,接著切換到應用程式首頁內,要清除
INavigation.NavigationStack
內的登入頁面資料,這樣,使用者就無法透過螢幕按鈕或者手機實體按鈕,再度回到 登入頁面了。修正登入成功後,無法回到登入頁面
切換到首頁時候,清空導航堆疊
打開 核心PCL 專案內的
LoginPage.xaml.cs
檔案,新增一個方法 ClearStackTo()
,並且在按鈕點擊事件內,當切換到應用首頁頁面之後,呼叫這個方法。
這個方法
ClearStackTo()
運作原理相當的簡單,那就是,它會嘗試移除任何在 NavigationStack
內的任何頁面,只會保留最後一個。要移除 NavigationStack
內的項目,使用了 Navigation.RemovePage(page);
方法,進行移除 NavigationStack
內的項目。using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Xamarin.Forms;
namespace XamarinLogin
{
public partial class LoginPage : ContentPage
{
public LoginPage()
{
InitializeComponent();
NavigationPage.SetBackButtonTitle(this, "回登入頁面");
buttonLogin.Clicked += ButtonLogin_Clicked;
}
private async void ButtonLogin_Clicked(object sender, EventArgs e)
{
// 切換到主頁面
var NextPage = new MainPage();
await Navigation.PushAsync(NextPage);
ClearStackTo();
}
private void ClearStackTo()
{
var stack = Navigation.NavigationStack;
while (stack.Count > 1)
{
var page = stack.First();
if (page != null)
{
Navigation.RemovePage(page);
}
else
{
break;
}
}
}
}
}
接著,打開
MainPage.xaml.cs
檔案,將內容修正如下所示:
其中,在建構式內,加入此方法呼叫
NavigationPage.SetHasBackButton
,目的在於要將回上一頁按鈕隱藏起來。using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Xamarin.Forms;
namespace XamarinLogin
{
public partial class MainPage : ContentPage
{
public MainPage()
{
InitializeComponent();
NavigationPage.SetHasBackButton(this, false);
NavigationPage.SetBackButtonTitle(this, "回到首頁");
}
}
}
執行結果
Android 系統
- 請使用滑鼠右擊方案總管內的
XamarinLogin.Droid
專案節點,選擇設定為起始專案
項目。 - 確認建置組態是
Debug
與有指定相關模擬器,此就可以按下 F5 開始執行 - 執行結果畫面按下了 登入 按鈕,就會進入到首頁
iOS 系統
- 請使用滑鼠右擊方案總管內的
XamarinLogin.iOS
專案節點,選擇設定為起始專案
項目。 - 確認建置組態是
Debug
與有指定相關模擬器,此就可以按下 F5 開始執行 - 執行結果畫面按下了 登入 按鈕,就會進入到首頁
進階應用 Font Awesome
底下的步驟,將會分別說明如何設定 Android 與 iOS 類型專案,使其可以使用 Font Awesome 字體圖示。並且也會修正登入頁面,在 XAML 宣告定義中,使用 Font Awesome字體圖示。
下載 Font Awesome 字型檔案與安裝
先打開瀏覽器,進入到 Font Awesome 官網 http://fontawesome.io/,在官網首頁,會看到下載連結,點擊該連結,下載 Font Awesome的壓縮檔案。
打開 Font Awesome 壓縮檔案後,將內容解壓縮到您的硬碟上,請將底下範例圖片中的
font-awesome-4.6.3\fonts\fontawesome-webfont.ttf
檔案,改名成為 font-awesome-4.6.3\fonts\fontawesome.ttf
(之後通稱這個檔案為 fontawesome.ttf
)
使用檔案總管,將這個
fontawesome.ttf
檔案,拖拉到 XamarinLogin.Droid
專案內的 Assets
資料夾內。
使用檔案總管,將這個
fontawesome.ttf
檔案,拖拉到 XamarinLogin.iOS
專案內的 Resources
資料夾內。
想要在 Android 與 iOS 系統內使用 Font Awesome 提供的字體圖示,做法並不一樣,底下分別就兩個平台的做法進行說明。
修正 核心PCL 的登入頁面
在
核心PCL
專案內,開啟 LoginPage.xaml
檔案,將這個檔案的 XAML 定義修改成如下定義。
這個新修訂的
LoginPage.xaml
檔案,將 Grid 修改成為二維的網格狀,因為,需要在第一個 Column 中,放置 Font Awesome 的字型圖示。
當要顯示 Font Awesome 字型圖示,只需要將要顯示的 Font Awesome 相對應的 Unicode 碼,寫道
Label.Text
內,如下列範例所示。不過,為了要能夠讓不同平台可以顯這這個 Font Awesome 字型圖示,建議也要加入這個定義 FontFamily="FontAwesome"
。<Label Text=""
FontSize="25"
FontFamily="FontAwesome"
Grid.Row="1" Grid.Column="0"
/>
LoginPage.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"
x:Class="XamarinLogin.LoginPage"
Title="使用者登入"
>
<Grid
HorizontalOptions="FillAndExpand" VerticalOptions="Center"
Padding="30,0"
>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="30" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Label Text="歡迎來到 Xamarin.Forms"
FontSize="40"
Grid.Row="0" Grid.ColumnSpan="2"
HorizontalTextAlignment="Center"
/>
<Label Text=""
FontSize="25"
FontFamily="FontAwesome"
Grid.Row="1" Grid.Column="0"
/>
<Entry Placeholder="請輸入帳號"
x:Name="entryAccount"
Grid.Row="1" Grid.Column="1"
HorizontalOptions="FillAndExpand"
/>
<Label Text=""
FontSize="25"
FontFamily="FontAwesome"
Grid.Row="2" Grid.Column="0"/>
<Entry Placeholder="請輸入密碼"
x:Name="entryPassword"
Grid.Row="2" Grid.Column="1"
IsPassword="True" />
<Button Text="登入"
x:Name="buttonLogin"
Grid.Row="3" Grid.ColumnSpan="2"
HorizontalOptions="FillAndExpand"
/>
</Grid>
</ContentPage>
Android 專案部分
請在
XamarinLogin.Droid
專案內,建立一個名為 Renderers
資料夾,並且在此資料夾內,建立一個類別檔案 AwesomeRenderer.cs
。該類別檔案的內容如下所示:using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Android.App;
using Android.Content;
using Android.OS;
using Android.Runtime;
using Android.Views;
using Android.Widget;
using Xamarin.Forms.Platform.Android;
using Xamarin.Forms;
using Android.Graphics;
using XamarinLogin.Droid.Renderers;
[assembly: ExportRenderer(typeof(Label), typeof(AwesomeLabelRenderer))]
[assembly: ExportRenderer(typeof(Xamarin.Forms.Button), typeof(AwesomeButtonRenderer))]
namespace XamarinLogin.Droid.Renderers
{
public class AwesomeLabelRenderer : LabelRenderer
{
protected override void OnElementChanged(ElementChangedEventArgs<Label> e)
{
base.OnElementChanged(e);
AwesomeUtil.CheckAndSetTypeFace(Control);
}
}
public class AwesomeButtonRenderer : ButtonRenderer
{
protected override void OnElementChanged(ElementChangedEventArgs<Xamarin.Forms.Button> e)
{
base.OnElementChanged(e);
AwesomeUtil.CheckAndSetTypeFace(Control);
}
}
internal static class AwesomeUtil
{
public static void CheckAndSetTypeFace(TextView view)
{
if (view.Text.Length == 0) return;
var text = view.Text;
if (text.Length > 1 || text[0] < 0xf000)
{
return;
}
var font = Typeface.CreateFromAsset(Xamarin.Forms.Forms.Context.ApplicationContext.Assets, "fontawesome.ttf");
view.Typeface = font;
}
}
}
iOS 專案部分
在
XamarinLogin.iOS
專案中,使用滑鼠右擊 Info.plist
檔案,在彈出功能表中,選擇 開啟方式
,再出現 開啟方式 - Info.plist
對話窗後,請選擇 XML(文字)編輯器
,接著,點擊 確定
按鈕。
此時,Visual Studio 會開啟 XML 編輯器,請參考下兩圖,加入底下 XML 宣告到 Info.plist 檔案內。
<key>UIAppFonts</key>
<array>
<string>fontawesome.ttf</string>
</array> </dict>
- Info.plist尚未修改前的內容截圖
- Info.plist尚未修改後的內容截圖
Font Awesome 的執行結果
底下分別展示出這兩個平台的執行成果。