Xamarin.Forms Navigation介绍

一个常规的App是由多个Page组成的,出现多个Page就会涉及页面跳转问题。Xamarin.Forms页面之间的跳转通过Navigation Stack管理Page,如页面A跳转到页面B时,会将B压入栈定,此时页面B成为活动页面,执行Back操作时,页面B从栈定推出使页面A重新变为活动页面。
每个应用程序都有一个特殊页作为应用程序的入口(main page, or the home page, or the start page),Xamarin.Forms中由App的MainPage属性设置。

INavigation介绍

Xamarin.Forms中页面分为Modal pages(模态页面) 和 modeless pages(非模态页面),跳转到一个新的页面可以通过PushAsyncPushModalAsync两个方法实现,两个方法均传入一个Page对象作为参数。同样提供了PopAsyncPopModalAsync两个方法返回前一个页面。PushAsync和PopAsync是对非模态页面的操作,PushModalAsync和PopModalAsync操作的是模态页面。PopToRootAsync方法表示回到导航栈低页面。RemovePage方法从导航栈中删除一个页面。InserPageBefore方法将一个page插入到指定page之前。通过这些方法操作Navigation Stack可以在不同Page间跳转。

关于PopXXX和Push方法定义返回Task类型介绍参考(涉及的OnDisappearing和OnAppearing不在本文不再说明):
http://www.cnblogs.com/qiandi/p/5598742.html

当我们调用PushAsync方法时必须修改App的MainPage属性为NavigationPage对象,否则报如下异常,使用NavigationPage时不必在为iOS单独设置Page的Padding属性解决页面和状态栏遮盖问题。

PopXXX和PushXXX提供的bool类型参数重载方法设置为true增加页面跳转动画。

INavigation定义

INavigation还定义了两个IReadOnlyList<Page>类型属性ModalStackNavigationStack,NavigationStack表示非模态页面的集合,PushAsync和PopAsync会改变NavigationStack的内容,ModalStack表示模态页面的集合PushModalAsync和PopModalAsync会改变ModalStack的内容,这两个属性不能直接修改,且提供了类似堆栈的功能。这两个集合不能混合跳转,非模态页面可以导航到模态页面但是模态页面不能导航到非模态页面。
如果用MainPage = new NavigationPage(new Page0());初始化App的MainPage属性运行应用程序,此时IOS平台中ModalStack为空,Android和Windows平台ModalStack包含一个元素(MainPage对应NavigationPage实例)。三个平台中的NavigationStack集合包均含一个Page0的实例。

《Creating Mobile Apps with Xamarin.Forms》中示例截图

这些方法均定义在INavigation中,VisualElement提供了一个INavigation类型只读属性Navigation,可以通过调用Navigation的方法实现跳转。

页面中调用代码Navigation.PushAsync(new ModelessPage(), true);

Programmers familiar with Android architecture are sometimes curious how Xamarin.Forms page navigation integrates with the aspect of Android application architecture known as the activity. A Xamarin.Forms application running on an Android device comprises only one activity, and the page navigation is built on top of that. A ContentPage is a Xamarin.Forms object; it is not an Android activity, or a fragment of an activity.
前面提到的参考链接有说明,什么意思自己看看吧!!!


NavigationPage介绍

NavigationPage的作用就是导航管理页面。

NavigationPage提供的属性

  • BarBackgroundColor - 获取、设置NavigationPage顶部导航栏的背景色(iOS、Android、Windows 平台有效)。
  • BarTextColor - 获取、设置NavigationPage顶部导航栏显示文本颜色(iOS、Windows平台有效)。

不同平台效果:

  • CurrentPage - 获取Navigation Stack最顶部页面,不管当前显示页面是模态页面还是非模态页面,CurrentPage都表示NavigationStack集合中的最后一项。

when a modal page is active, CurrentPage continues to indicate the last modeless page that was active before navigation to a modal page

NavigationPage提供的BindableProperty

  • HasBackButtonProperty - 是否显示非模态页面导航栏的返回按钮(iOS、Android起作用)
    C#设置NavigationPage.SetHasBackButton(this, false);
    XAML设置NavigationPage.HasBackButton="False"
  • HasNavigationBarProperty - 是否显示导航栏
  • BackButtonTitleProperty - 设置返回按钮的文本(仅iOS平台)
  • TitleIconProperty - 设置导航栏上显示图标(iOS平台Icon代替Title,Android修改左侧图标显示,Windows 无效)
官方图片!!!

屏蔽Android、Windows Mobile 返回按键

Android和Windows Phone会包含一个返回键,返回键提供类似PopAsync或PopModalAsync的工能,程序中要屏蔽返回键的功能需要重写Page的OnBackButtonPressed方法。OnBackButtonPressed方法返回true值,程序不处理返回按键。

protected override bool OnBackButtonPressed()
{
    //return base.OnBackButtonPressed();
    return true;
}

Page还定义了SendBackButtonPressed方法,用来模拟返回按钮被按下。调用该方法与Android按下返回键功能类似。

官方电子书中提到“Although this works on iOS and Android, it currently does not work on the Windows Runtime platforms.”这个方法只对iOS和Android有效,Windows Runtime platforms不能正常工作。 实际测试iOS无效,Android正常,Windows 无法测试。

页面间传值

一个应用程序会包含多个页面,把数据从一个页面传到另一个页面该怎么做?

构造函数传值

页面跳转的PushXXX方法传入Page页面实例作为参数,可以通过Page页面的构造函数传入数据,如Navigation.PushModalAsync(new DataPage(label.Text));,在DataPage重载的构造函数中在处理接收的数据。

属性方法传值

根据页面的属性或调用方法传值。如:

构造函数传值是单向的不能传递返回数据,通过属性传值可以从当前页面向前一个页面传值。应从NavigationStack集合中取得前一个页面实例。

var stack = (App.Current.MainPage as NavigationPage).Navigation.NavigationStack;

int lastIndex = stack.Count - 1;
navigationPage homePage = stack[lastIndex] as navigationPage;

if (homePage == null)
{
    homePage = stack[lastIndex - 1] as navigationPage;
}

homePage.SetText(Value + "页面返回数据了");

从模态页面跳转到非模态页面和模态页面跳转到模态页面两种情况,跳转前的页面在NavigationStack中有不同的位置。如果是非模态页面跳转到非模态页面?又要从ModalStack中获取前一个页面实例,所以通过属性和方法传值不推荐!!!

Messaging Center传值

MessagingCenter是一个静态类,提供了Subscribe、Unsubscribe和Send三个公开的方法。Subscribe订阅接收的消息信息,参数、发送者类型等。Unsubscribe取消订阅,不在接收消息。Send发送指定类型消息。

Messaging Center传值示例:

数据接收页面增加消息订阅代码:

MessagingCenter.Subscribe<navigationPage, string>(this, "Value", (arg1, arg2) =>
        {
            label.Text = arg2;
        });

Subscribe包含两个范型参数,第一个为消息发送者类型,第二个为传递数据类型。Subscribe包含三个参数,第一个为消息接收者,第二个参数为字符串类型消息标示,第三个参数是一个lambda表达式,表示接收到消息后的动作。

数据传递页面增加发送消息代码:

MessagingCenter.Send<navigationPage, string>(this, "Value", label.Text);

Send两个范型参数与Subscribe方法相同。Send包含三个参数,第一个参数为消息发送者,第二个参数为消息标示,第三个参数为传递的数据对象。
本示例Send方法应在PushAsync后执行。PushAsync执行前消息没有订阅,Send发送消息此时没有接收者。

不再接收消息时应该调用Unsubscribe取消指定消息的订阅,对资源回收释放。本示例取消订阅代码添加在Subscribe方法的lambda中。

MessagingCenter.Unsubscribe<navigationPage, string>(this, "Value");

Strictly speaking, however, unsubscribing shouldn’t be necessary because the MessagingCenter maintains WeakReference objects for subscribers。
MessagingCenter定义了一个Dictionary<Tuple<string, Type, Type>, List<Tuple<WeakReference, Action<object, object>>>>类型对象通过WeakReference管理subscribers,所以Unsubscribe方法不是必须的。

事件传值

WinForm中常用的传值形式,事件传值。推荐数据回传时使用。

Page1 跳转到Page2时,Page2添加事件定义:

public EventHandler<string> Value;

Page2 返回Page1 时,触发事件:

EventHandler<string> handler = Value;
if (handler != null)
{
    handler(this, "增加返回字符串");
}

Page1 跳转到Page2时,订阅Page2的事件:

var page = new Page2();
page.Value += (sender, e) =>
{
        label.Text = e;
};
Navigation.PushAsync(page);

传递复杂数据继承EventArgs实现传值

App Class传值

Xamarin.Forms应用程序会提供一个App类(继承Application)作为程序的入口,该对象在应用程序运行期间一直存在,可以借助App类实现不同页面之间数据传递。

修改App代码定义属性保存、获取数据。如:

获取App类实例可以通过(App)Application.Current)获取。或着直接定义static 属性,直接通过App.Value 传值。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 159,015评论 4 362
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,262评论 1 292
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,727评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,986评论 0 205
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,363评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,610评论 1 219
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,871评论 2 312
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,582评论 0 198
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,297评论 1 242
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,551评论 2 246
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,053评论 1 260
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,385评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,035评论 3 236
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,079评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,841评论 0 195
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,648评论 2 274
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,550评论 2 270

推荐阅读更多精彩内容