2017/8/28

Xamarin.Forms 教學系列文(二十四.壹)Page Navigation - 頁面導覽


學習目標
  • Navigation 頁面導覽
  • 導覽的頁面類型 Modaless & ModalPage
  • Navigation 的一些屬性

頁面導覽 在資訊界其實很常見,例如你正在看這篇教學所使用的瀏覽器,那左上角的上一頁,就是一種頁面導覽。

如果讓我們以程式的觀點來看待 頁面導覽 ,其實就是 實作堆疊(Stack)

當有新頁面出現時,就將此頁面 Push 進 Stack 並顯示他,
當要回到前一頁時,就 Pop 掉 Stack 第一筆,並顯示最上面一筆的頁面,

而這也是 Xamarin.Forms 實作 Navigation 的方法,
所以會看到 Navigation 類別提供了 Push Pop 的方法,甚至可以手動取得 Navigation Stack 來做進一步處理

導覽架構內一定有初始頁,我們通常稱作 Main page、Home page 或是 Start page。

而從 Main page 準備導覽時,下一頁的類型我們有兩種可以選擇:
  • Modeless page (有返回鈕) - 其實也就是正常的導覽頁面
  • Modal page (無返回鈕)

我們會從 Navigation 類別所提供的方法來做介紹,並用範例讓大家了解這兩種頁面類型的差異。 

Modeless & Modal 頁面

Navigation 提供兩種方法導覽至下一頁
  • Task PushAsync(Page page)
  • Task PushModalAsync(Page page)

返回也定義了兩個方法 (手動做返回時會寫)
  • Task<Page> PopAsync()
  • Task<Page> PopModalAsync()

//這邊用了非同步的 Task ,但不代表導覽的頁面是在另一個 Thread 執行,後面的章節會來探討這一部分

Modeless  Modal 這兩種頁面類型最大的差別在於
有沒有自動提供返回的按鈕!

為什麼需要無返回鈕的 Modal 頁?
通常用於強制使用者執行完某件事、或輸入完某些資料後,最後才用 Pop 方法導回頁面。

來看範例,
範例包含了三個頁面程式,分別為 MainPage, ModalPage ModelessPage
我們會在 MainPage 內加入兩個 Button,分別導向其他兩頁:

MainPage
public class MainPage : ContentPage
{
    public MainPage()
    {
        Title = "Main Page";

        Button gotoModelessButton = new Button
        {
            Text = "Go to Modeless Page",
            HorizontalOptions = LayoutOptions.Center,
            VerticalOptions = LayoutOptions.CenterAndExpand
        };

        //導覽至 ModelessPage
        gotoModelessButton.Clicked += async (sender, args) =>
        {
            await Navigation.PushAsync(new ModelessPage());
        };

        Button gotoModalButton = new Button
        {
            Text = "Go to Modal Page",
            HorizontalOptions = LayoutOptions.Center,
            VerticalOptions = LayoutOptions.CenterAndExpand
        };

        //導覽至 ModalPage
        gotoModalButton.Clicked += async (sender, args) => 
        {
            await Navigation.PushModalAsync(new ModalPage());
        };

        Content = new StackLayout
        {
            Children =
            {
                gotoModelessButton, gotoModalButton
            }
        };
    }
}

*非常重要如有用到 Navigation,App Class 的 MainPage 要改成這樣:
public class App : Application
{
    public App()
    {
        MainPage = new NavigationPage(new MainPage());
    } 
    …
 }

執行結果:
可以注意下 Title 設定的文字會出現在上方

接著點擊 Go to Modeless Page,會導向 ModelessPage
public class ModelessPage : ContentPage
{
    public ModelessPage()
    {
        Title = "Modeless Page";

        Button goBackButton = new Button
        {
            Text = "Back to Main",
            HorizontalOptions = LayoutOptions.Center,
            VerticalOptions = LayoutOptions.Center
        };

        goBackButton.Clicked += async (sender, args) =>
        {
            await Navigation.PopAsync();
        };

        Content = goBackButton;
    }
}

*你不一定要實作返回按鈕,Android 和 iOS 上方都已經有現成的返回鈕可以用了…
*Android 和 iOS 上方那一排稱作 Navigation bar

返回到 MainPage 後,讓我們點擊 Go to Modal Page:
public class ModalPage : ContentPage
{
    public ModalPage()
    {
        Title = "Modal Page";

        Button goBackButton = new Button
        {
            Text = "Back to Main",
            HorizontalOptions = LayoutOptions.Center,
            VerticalOptions = LayoutOptions.Center
        };

        goBackButton.Clicked += async (sender, args) =>
        {
            await Navigation.PopAsync();
        };

        Content = goBackButton;
    }
}

可以注意到 Modal 頁上方的 Navigation bar 不見了~ 連 Title 都沒出來~ 就是不會自動給返回鈕!


特別注意的規則,若要再次導覽時,:
  • Modeless page 可以再導向其他 Modeless 或 Modal 頁
  • Modal 只能再導到 Modal 頁

Navigation 的一些屬性

這邊介紹一些可以改變 Navigation bar 外觀的屬性,

例如設定背景色文字顏色
public class App : Application
{
    public App()
    {
        MainPage = new NavigationPage(new MainPage())
        {
            BarBackgroundColor = Color.Blue,
            BarTextColor = Color.Pink



除了在 App 內設定全域的屬性,

也可以在個別的 Page 內來做設定:

像是個別頁返回紐消失
public class ModelessPage : ContentPage
{
    public ModelessPage()
    {
        Title = "Modeless Page";
        NavigationPage.SetHasBackButton(this, false);
        … 
    }
}

XAML 寫法
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms" 
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" 
             x:Class="ModelessAndModal.ModelessPage" 
             Title="Modeless Page"
             NavigationPage.HasBackButton="False">
    …
</ContentPage>


還有其他屬性像是:

讓整條 bar 消失:
NavigationPage.SetHasNavigationBar(this, false);

設定返回鈕顯示的字:
NavigationPage.SetBackButtonTitle(this, "go back");

設定 Icon:
NavigationPage.SetTitleIcon(this, "ic_action_flash_on.png");


其實我一直很疑惑為什麼這本書要把 Navigation 放到 24 章,
在我學 Xamarin 的第一天起,我就一直很困惑要怎麼在 App 導向下一個頁面。

直到我讀到 24 章... 微軟你有想過 1 ~ 23 章很遙遠嗎...

好了抱怨完畢。


3 則留言:

  1. 請問一下,
    我在 Tabbed Page 裡做 page navigation,我的 tab bar會被蓋掉耶
    是有什麼地方要設定嗎??
    謝謝

    回覆刪除
    回覆
    1. 別理我,我解決了,雖然不是很確定改了什麼...
      謝謝

      刪除
    2. okok,正想問清楚問題哈哈

      刪除