原文 Visual Studio跨平台开发实战(3) - Xamarin iOS多页面应用程式开发
前言
在前一篇教学中, 我们学会如何使用Visual Studio 搭配Xcode 进行iOS基本控制项的操作. 但都是属于单一画面的应用程式. 这次我们要来练习如何透过Navigation Controller来建立多页面的iOS应用程式.
![clip_image002 clip_image002](http://files.dotblogs.com.tw/taihon64/1308/VisualStudio3XamariniOS_204C/clip_image002_thumb.jpg?x-oss-process=image/resize,w_1400/format,webp)
设定专案及画面
1. 开启Xamarin Studio 并建立新专案, 专案类型为iOS=>iPhone=>空白专案, 专案名称为02-Navigation.
2. 在专案中添加3个iPhone View Controller 的档案, 档案名称如下:
- HomeScreen
Level1Screen
Level2Screen
新增后档案结构如下图所示:
![](http://files.dotblogs.com.tw/taihon64/1308/2013825104752634.png?x-oss-process=image/resize,w_1400/format,webp)
3. 双击HomeScreen.xib 以开启Xcode.
4. 点选编辑区的HomeScreen, 并在右边的Attributes Inpsctor将Top Bar变更为”Navigation Bar”
![](http://files.dotblogs.com.tw/taihon64/1308/2013825104819649.png?x-oss-process=image/resize,w_1400/format,webp)
5. 在Object Library中拖拉一个Button至画面中并将文字改为”Go to Level 1 Screen”
![](http://files.dotblogs.com.tw/taihon64/1308/2013825104833337.png?x-oss-process=image/resize,w_1400/format,webp)
6. 为Button建立一个Outlet并命名为”btnToLv1”. 之后请关闭Xcode
![](http://files.dotblogs.com.tw/taihon64/1308/2013825104849134.png?x-oss-process=image/resize,w_1400/format,webp)
7. 在Visual Studio 中开启此专案, 在专案属性中设定应用程式名称及版本等资讯, 并开启” AppDelegate.cs” 档. 在FinishedLaunching事件中加入以下程式码:
01 |
<span class = "notranslate" onmouseover= "_tipon(this)" onmouseout= "_tipoff()" ><span class = "google-src-text" style= "direction: ltr; text-align: left" > |
03 |
<span class = "notranslate" onmouseover= "_tipon(this)" onmouseout= "_tipoff()" ><span class = "google-src-text" style= "direction: ltr; text-align: left" >var rootNavigationController = new UINavigationController();</span> var rootNavigationController = new UINavigationController();</span> |
05 |
<span class = "notranslate" onmouseover= "_tipon(this)" onmouseout= "_tipoff()" ><span class = "google-src-text" style= "direction: ltr; text-align: left" > |
07 |
<span class = "notranslate" onmouseover= "_tipon(this)" onmouseout= "_tipoff()" ><span class = "google-src-text" style= "direction: ltr; text-align: left" >HomeScreen home = new HomeScreen();</span> HomeScreen home = new HomeScreen();</span> |
09 |
<span class = "notranslate" onmouseover= "_tipon(this)" onmouseout= "_tipoff()" ><span class = "google-src-text" style= "direction: ltr; text-align: left" > |
11 |
<span class = "notranslate" onmouseover= "_tipon(this)" onmouseout= "_tipoff()" ><span class = "google-src-text" style= "direction: ltr; text-align: left" >rootNavigationController.PushViewController(home, false );</span> rootNavigationController.PushViewController(home, false );</span> |
13 |
<span class = "notranslate" onmouseover= "_tipon(this)" onmouseout= "_tipoff()" ><span class = "google-src-text" style= "direction: ltr; text-align: left" > |
15 |
<span class = "notranslate" onmouseover= "_tipon(this)" onmouseout= "_tipoff()" ><span class = "google-src-text" style= "direction: ltr; text-align: left" > this .window.RootViewController = rootNavigationController;</span> this .window.RootViewController = rootNavigationController;</span> |
完成后的FinishedLaunching方法如下图所示:
![](http://files.dotblogs.com.tw/taihon64/1308/201382510508759.jpg?x-oss-process=image/resize,w_1400/format,webp)
在上面的程式码中, 我们先初始化Window, UINavigationController以及HomeScreen物件. 接着透过PushViewController方法将HomeScreen加入到NavigationController. 然后将rootNavigationController指定到Window.RootViewController属性. 最后则是显示Window.
8. 开启HomeScreen.cs, 在建构子中设定主画面的标题
1 |
<span class = "notranslate" onmouseover= "_tipon(this)" onmouseout= "_tipoff()" ><span class = "google-src-text" style= "direction: ltr; text-align: left" > public HomeScreen()</span> public HomeScreen()</span> |
3 |
<span class = "notranslate" onmouseover= "_tipon(this)" onmouseout= "_tipoff()" ><span class = "google-src-text" style= "direction: ltr; text-align: left" >: base ( "HomeScreen" , null )</span> : base ( "HomeScreen" , null )</span> |
5 |
<span class = "notranslate" onmouseover= "_tipon(this)" onmouseout= "_tipoff()" ><span class = "google-src-text" style= "direction: ltr; text-align: left" >{</span> {</span> |
7 |
<span class = "notranslate" onmouseover= "_tipon(this)" onmouseout= "_tipoff()" ><span class = "google-src-text" style= "direction: ltr; text-align: left" > this .Title = "我是主畫面" ;</span> this .Title = "我是主画面" ;</span> |
9 |
<span class = "notranslate" onmouseover= "_tipon(this)" onmouseout= "_tipoff()" ><span class = "google-src-text" style= "direction: ltr; text-align: left" >}</span> }</span> |
9. 执行专案后的结果如下:
![](http://files.dotblogs.com.tw/taihon64/1308/2013825105257993.png?x-oss-process=image/resize,w_1400/format,webp)
载入Level 1 Screen
1. 我们要在点击主页面上的button后载入Level1Screen. 因此我们开启HomeScreen.cs. 在类别下先宣告Level1Screen物件.
1 |
<span class = "notranslate" onmouseover= "_tipon(this)" onmouseout= "_tipoff()" ><span class = "google-src-text" style= "direction: ltr; text-align: left" > |
3 |
<span class = "notranslate" onmouseover= "_tipon(this)" onmouseout= "_tipoff()" ><span class = "google-src-text" style= "direction: ltr; text-align: left" >Level1Screen lv1scr;</span> Level1Screen lv1scr;</span> |
在ViewDidLoad事件中, 加入btnToLv1的touchupinside事件处理, 程式码如下:
01 |
<span class = "notranslate" onmouseover= "_tipon(this)" onmouseout= "_tipoff()" ><span class = "google-src-text" style= "direction: ltr; text-align: left" > |
03 |
<span class = "notranslate" onmouseover= "_tipon(this)" onmouseout= "_tipoff()" ><span class = "google-src-text" style= "direction: ltr; text-align: left" > |
05 |
<span class = "notranslate" onmouseover= "_tipon(this)" onmouseout= "_tipoff()" ><span class = "google-src-text" style= "direction: ltr; text-align: left" > this .btnToLv1.TouchUpInside += (sender, e) =>{</span> this .btnToLv1.TouchUpInside += (sender, e) =>{</span> |
07 |
<span class = "notranslate" onmouseover= "_tipon(this)" onmouseout= "_tipoff()" ><span class = "google-src-text" style= "direction: ltr; text-align: left" > if ( this .lv1scr == null ) { this .lv1scr = new Level1Screen(); }</span> if ( this .lv1scr == null ) { this .lv1scr = new Level1Screen(); }</span> |
09 |
<span class = "notranslate" onmouseover= "_tipon(this)" onmouseout= "_tipoff()" ><span class = "google-src-text" style= "direction: ltr; text-align: left" > this .NavigationController.PushViewController(lv1scr, true );</span> this .NavigationController.PushViewController(lv1scr, true );</span> |
11 |
<span class = "notranslate" onmouseover= "_tipon(this)" onmouseout= "_tipoff()" ><span class = "google-src-text" style= "direction: ltr; text-align: left" >};</span> };</span> |
在上述程式码中, 我们同样透过PushViewController方法将Level1Screen加入到Navigation控制项.
2. 执行专案并在主画面中点击按钮以载入Level 1 Screen. 您会看到空白画面被载入, 且NavigationBar左边的按钮会显示上一个页面的Title
![](http://files.dotblogs.com.tw/taihon64/1308/201382510547837.png?x-oss-process=image/resize,w_1400/format,webp)
新增NavigationBar右边的按钮载入Level 2 Screen
在前一个练习, 我们载入了Level 1 Screen, NavigationBar左边是回到上一个页面, 在这个练习中, 我们要在NavigationBar中新增右边的按钮, 并透过按钮来载入Level 2 Screen.
1. 开启level1screen.cs, 并在类别下加入Level2Screen的宣告
1 |
<span class = "notranslate" onmouseover= "_tipon(this)" onmouseout= "_tipoff()" ><span class = "google-src-text" style= "direction: ltr; text-align: left" > |
3 |
<span class = "notranslate" onmouseover= "_tipon(this)" onmouseout= "_tipoff()" ><span class = "google-src-text" style= "direction: ltr; text-align: left" >Level2Screen lv2scr;</span> Level2Screen lv2scr;</span> |
2. 在level1screen.cs的ViewDidLoad事件中, 加入以下程式码:
1 |
<span class = "notranslate" onmouseover= "_tipon(this)" onmouseout= "_tipoff()" ><span class = "google-src-text" style= "direction: ltr; text-align: left" > |
3 |
<span class = "notranslate" onmouseover= "_tipon(this)" onmouseout= "_tipoff()" ><span class = "google-src-text" style= "direction: ltr; text-align: left" >{</span> {</span> |
5 |
<span class = "notranslate" onmouseover= "_tipon(this)" onmouseout= "_tipoff()" ><span class = "google-src-text" style= "direction: ltr; text-align: left" > if ( this .lv2scr == null ) { this .lv2scr = new Level2Screen(); }</span> if ( this .lv2scr == null ) { this .lv2scr = new Level2Screen(); }</span> |
7 |
<span class = "notranslate" onmouseover= "_tipon(this)" onmouseout= "_tipoff()" ><span class = "google-src-text" style= "direction: ltr; text-align: left" > this .NavigationController.PushViewController(lv2scr, true );</span> this .NavigationController.PushViewController(lv2scr, true );</span> |
9 |
<span class = "notranslate" onmouseover= "_tipon(this)" onmouseout= "_tipoff()" ><span class = "google-src-text" style= "direction: ltr; text-align: left" >}), true );</span> }), true );</span> |
我们透过SetRightBarButtonItem方法, 新增一个UIBarButtonItem, 在这里我们使用系统内建的Edit项目. 您也可以使用自订的图示或文字来建立. 并在第2个参数, 直接透过Lambda Expression 来建立按钮按下去的处理. 我们同样透过PushViewController方法将Level 2 Screen载入.
3. 执行专案的结果如下:
![](http://files.dotblogs.com.tw/taihon64/1308/2013825105514228.png?x-oss-process=image/resize,w_1400/format,webp)
按下Level 1 右边的”Edit”按钮, 便会载入Level 2 Screen. 因为我们没有设定Level 1 Screen的Title, 因此在Level 2 Screen左边的按钮会显示预设的”Back”
![](http://files.dotblogs.com.tw/taihon64/1308/2013825105545274.png?x-oss-process=image/resize,w_1400/format,webp)
客制NavigationBar左边的按钮
在目前的练习中, NavigationBar左边按钮的显示文字为上一个画面的Title, 若没有设定Title则会显示Back. 接下来我们来客制Level 1 Screen左边的按钮文字, 方法如下:
1. 开启level1screen.cs, 在ViewDidLoad事件中, 新增以下程式码:
1 |
<span class = "notranslate" onmouseover= "_tipon(this)" onmouseout= "_tipoff()" ><span class = "google-src-text" style= "direction: ltr; text-align: left" > |
3 |
<span class = "notranslate" onmouseover= "_tipon(this)" onmouseout= "_tipoff()" ><span class = "google-src-text" style= "direction: ltr; text-align: left" >(sender, e) =></span> (sender, e) =></span> |
5 |
<span class = "notranslate" onmouseover= "_tipon(this)" onmouseout= "_tipoff()" ><span class = "google-src-text" style= "direction: ltr; text-align: left" >{</span> {</span> |
7 |
<span class = "notranslate" onmouseover= "_tipon(this)" onmouseout= "_tipoff()" ><span class = "google-src-text" style= "direction: ltr; text-align: left" > this .NavigationController.PopViewControllerAnimated( true );</span> this .NavigationController.PopViewControllerAnimated( true );</span> |
9 |
<span class = "notranslate" onmouseover= "_tipon(this)" onmouseout= "_tipoff()" ><span class = "google-src-text" style= "direction: ltr; text-align: left" >}), true );</span> }), true );</span> |
由上述的程式码可知, 我们同样是呼叫SetLeftBarButtonItem (刚刚是SetRightBarButtonItem)的方式, 新增一个按钮来取代预设的按钮. 然后输入自订的文字”回到主画面”.
2. 执行专案的结果如下:
![](http://files.dotblogs.com.tw/taihon64/1308/2013825105653993.png?x-oss-process=image/resize,w_1400/format,webp)
可以对照一下先前的执行结果, NavigationBar左边按钮的文字已经取代为我们自订的文字了.
隐藏主画面的NavigationBar
如果不想在主画面中也显示NavigationBar, 可以透过在HomeScreen.cs中新增ViewWillAppear及ViewWillDisappear事件处理来将主画面中的NavigationBar隐藏起来, 程式码如下:
01 |
<span class = "notranslate" onmouseover= "_tipon(this)" onmouseout= "_tipoff()" ><span class = "google-src-text" style= "direction: ltr; text-align: left" > |
03 |
<span class = "notranslate" onmouseover= "_tipon(this)" onmouseout= "_tipoff()" ><span class = "google-src-text" style= "direction: ltr; text-align: left" > base .ViewWillAppear(animated);</span> base .ViewWillAppear(animated);</span> |
05 |
<span class = "notranslate" onmouseover= "_tipon(this)" onmouseout= "_tipoff()" ><span class = "google-src-text" style= "direction: ltr; text-align: left" > this .NavigationController.SetNavigationBarHidden( true , true );</span> this .NavigationController.SetNavigationBarHidden( true , true );</span> |
07 |
<span class = "notranslate" onmouseover= "_tipon(this)" onmouseout= "_tipoff()" ><span class = "google-src-text" style= "direction: ltr; text-align: left" >}</span> }</span> |
09 |
<span class = "notranslate" onmouseover= "_tipon(this)" onmouseout= "_tipoff()" ><span class = "google-src-text" style= "direction: ltr; text-align: left" > public override void ViewWillDisappear( bool animated) {</span> public override void ViewWillDisappear( bool animated) {</span> |
11 |
<span class = "notranslate" onmouseover= "_tipon(this)" onmouseout= "_tipoff()" ><span class = "google-src-text" style= "direction: ltr; text-align: left" > base .ViewWillDisappear(animated);</span> base .ViewWillDisappear(animated);</span> |
13 |
<span class = "notranslate" onmouseover= "_tipon(this)" onmouseout= "_tipoff()" ><span class = "google-src-text" style= "direction: ltr; text-align: left" > this .NavigationController.SetNavigationBarHidden( false , true );</span> this .NavigationController.SetNavigationBarHidden( false , true );</span> |
15 |
<span class = "notranslate" onmouseover= "_tipon(this)" onmouseout= "_tipoff()" ><span class = "google-src-text" style= "direction: ltr; text-align: left" >}</span> }</span> |
执行结果如下:
![](http://files.dotblogs.com.tw/taihon64/1308/2013825105618931.png?x-oss-process=image/resize,w_1400/format,webp)
结语
本篇文章说明如何透过Navigation controller来建立多页面的iOS 应用程式. 在iOS中还有其他建立多页面应用程式的方法, 例如Tab控制项可以透过画面下方的页签来切换不同画面. Storyboard 可以透过Interface Builder来建立应用程式的多个画面以及画面之间的连结. 有兴趣的朋友可以参考以下文章:
Using XCode, Interface Builder, and Storyboards
http://docs.xamarin.com/guides/ios/user_interface/tables/part_5_-_using_xcode,_interface_builder,_and_storyboards
Creating Tabbed Applications
http://docs.xamarin.com/guides/ios/user_interface/creating_tabbed_applications
范例程式码下载: Lab02-Navigation.zip
本文同时刊载于昕力资讯网站 ,转载请注明出处!