IOS開發入門(11)-導航控制器(1)

IOS開發入門(11)-導航控制器I:層級結構和標籤

前言:(直接從書上抄的)

  大多數應用程序是由主視圖導出多個屏幕,並且通常情況下實現屏幕切換的方法還不止一種。我們需要一種方式來實現用戶在應用程序內來回移動,以及讓用戶知道他們所在的具體部分提供的功能之間的切換。

  在iPhone設備上,大多數使用導航控制器的應用程序可以分爲兩種。一種使用簡單的主視圖來導航一系列展示或多或少、漸進的細節場景。通訊錄、筆記和設置就是不錯的示例。其他的,比如鬧鐘和音樂,則有許多主視圖,各自擁有不同的功能,設置擁有自己的內容層次。

  iOS提供控制器來管理每種內容之間的導航。UINavigationController用於在各種層次結構的信息之間上下移動,而UITabBarController則處理多個主視圖之間的切換。

  本節就是介紹這兩種方法怎麼使用。

1 導航控制器

  我們來看一下設置是長啥樣的吧,下圖展示的是setting方法應用程序中的某個局部的層級結構

這裏寫圖片描述

  在iPhone上,這是常見的組織內容的方式。該方式優雅地解決了如何在狹小空間內顯示大量內容的問題。setting允許修改iPhone和setting內部各種應用程序的數以百計的設置選項。採用層次結構的方式來“摺疊”內容,能夠很好地應用兩種屏幕尺寸,以及很好地複合人們通常善於分類和分組的情況。

  那些擁有帶層次結構的內容的應用程序,工作方式一般基本相同。在屏幕層級的頂部,會有內容概述,然後就是多個帶更多細節的屏幕。setting應用程序就是不錯的示例。在頂層,一開始是setting應用的所有相關的分類,然後是能夠持續向下深入,直到到達特定設置的細節。

  UINavigationController正是爲了處理這種類型的導航而設。他跟蹤客戶,就像它位於導航中不同屏幕的層次結構,並提供默認的控件返回。該控制器通過將所有內容都嵌入它內部來實現這一點。

這裏寫圖片描述

  上圖顯示了導航控制器的一部分。頂部是導航欄。導航欄通常會用在上下文中或展開的當前路徑。標題通常爲用戶正在觀看的內容。正如我們很快就會看到的一樣,在導航路徑中,左手邊的後退按鈕能夠讓用戶返回上一節。在導航欄上,用戶可以自定義按鈕

  位於底部的是一個可選的工具欄,是另一處讓我們設置空間的地方,上面放了一個操作按鈕。我們的視圖控制器位於灰色地帶。而在當前場景的某個地方,需要提供一個方法來打開下一級詳細頁面。例如,在Add/View場景中的Edit按鈕

  當使用導航控制器時,一開始可以將它連接到第一個場景或根場景(一個視圖控制器)。當導航控制器打開時,他就會打開根場景。正如我們將其關聯到一個新的場景(視圖控制器),導航控制器會將它放在當前路徑上,並顯示該場景。

  在視圖控制器的堆棧中,根視圖位於底部,路徑通常也會被記錄。

介紹一下導航控制類

  所有的導航功能都通過5個主要類來提供:

  • UINavigationController爲當前導航堆棧協調所有的組件。除了管理導航堆棧和所有磚廠(transition)之外,它有指向導航欄和可選工具欄的引用
  • UINavigationBar是位於屏幕頂部的導航欄視圖。UINavigationController用它顯示當前場景的標題和一個按鈕,如果需要的話,它可以用於返回前一個界面。它可以獨立地使用,但是不推薦這樣做
  • UINavigationItem管理層次結構中某個特定視圖控制器的UINavigationBar。它有如下各項的屬性:設置標題,顯示、添加和隱藏工具欄按鈕,包括Back按鈕
  • UIBarButtonItem提供了一個對象來管理導航和工具欄上的按鈕。從系統提供按鈕(如Done(完成)、Cancel(取消)和到文本按鈕的操作(action)等),可以創建出任意按鈕。Button Item既不是UIButton,也不是視圖(View)類型。它們是管理項,可以顯示用戶界面中的東西。可以將UIButton放在Button Item(按鈕項)裏面
  • UIToolbar管理一個可選的工具欄,通常位於屏幕的底部。其擁有方法與屬性來設置Button Item(按鈕項)和外觀,以及一種方式來指定其位置是在屏幕的頂部還是底部

      UINavigationItem使用當前視圖控制器的title屬性來設置文本。更改title會改變文本。之前在本地化的場景標題我們見過這個操作。

      下圖顯示了在CarValet應用程序的Add/View場景中與導航控制器相關的對象

這裏寫圖片描述

  導航控制器管理Add/View場景以及其他場景。每個被管理的場景有一個UINavigationItem,用於設置導航欄的內容以及標題。Add/View場景的標題欄也有一個工具欄按鈕,以顯示car images場景。

  觀看上圖的圈圈,這是一個特殊的關聯標識符(segue identifier),是爲第一個控制器或根視圖控制器而設。不想push segue,着開起來想一條兩端都有一個圓的線。根場景是導航控制器展示的第一個場景。故事版中的另一個鏈接顯示了場景之間的導航路徑。例如在Add/View於Edit場景之間存在一個鏈接。因爲無處可去只有返回,Edit場景就是一個葉節點,如同第一張圖的葉節點。

添加工具欄

  (從書上抄了那麼多字真是類,覺得還是介紹一下比較好),現在開始幹正事。

  首先我們要把圖標添加到項目的資產庫中。我們需要圖標,可以
在這裏下載,但是那需要自己找;也可以在這裏我的github下載。最好是從我的github上下載吧。

  好了,圖標下載完了,要添加到資產庫中,如下圖操作方式

這裏寫圖片描述

  選+之後,會跳出一個目錄,到最下面找到Import,點完import,選中要導入的文件就行啦

這裏寫圖片描述

這裏寫圖片描述

  • 現在圖標加進去了,我們要加底部工具欄了,打開故事面板

這裏寫圖片描述

  • 添加完工具欄,放置按鈕

這裏寫圖片描述

這裏寫圖片描述

  • 選擇左邊的按鈕,Image設置爲sign_out;右邊那個按鈕,Image設置爲sign_in;中間的按鈕,title改爲Edit。

  • 刪除原來的Previous、Next和Edit按鈕,

  • 將我們之前添加的左右箭頭通過下圖方法設置關聯,左箭頭選擇previousCar,右箭頭選擇nextCar

這裏寫圖片描述

1

  • 當我們刪除Edit按鈕時,也刪除了到Edit場景的關聯(segue),我們要將它恢復,將它拉到Edit場景,選擇push,並設置標識符爲Editsegue,與之前的Edit按鈕所用的關聯名稱一樣

      然後運行程序你可能會發現下面的導航欄沒有出現,那麼在ViewController.m中的viewDidLoad方法中,添加self.navigationController.toolbarHidden = NO;使他正好位於[super viewDidLoad];下面,這時候就出現了,但是點開其他的例如car images,下面也出現了導航欄,這顯然不是我們想要的,在Edit等場景裏面也是這個情況。可以在他們各自的viewDidLoad方法中添加self.navigationController.toolbarHidden = YES;,這樣就默認爲隱藏了。然而還有個問題,當我們從其他場景退出返回到Add/View場景時,導航欄消失了,他也是被隱藏了,那我們就換個地方,在ViewController.m中的viewWillAppear方法中,添加self.navigationController.toolbarHidden = NO;,這樣每次加載的時候,就自動設置回去了。這樣就設置完成啦。

這裏寫圖片描述

(PS,顏色是我後來弄的,到這步按鈕顏色應該是藍色的,導航欄應該是白色的,而且沒有About)

基於消息的導航

到目前爲止,我們已經使用segue在場景之間進行導航,包括使用特使的exit segue。我們擁有一些控制器可以傳遞數據並能使用prepareForSegue:方法修改行爲。藉助於UINavigationController的屬性和消息,可以擁有完全控制權。可以實現如下類似行爲:將新的視圖控制器推給堆棧(push),彈出(pop)當前視圖控制器,彈出根視圖控制器之上的所有控制器,獲取當前導航堆棧中的控制器數組,甚至重新排列視圖控制器數組。

可以使用基於代碼的消息,爲CarValet應用程序添加一個About場景,而不是在故事面板中添加,而是可以在單獨的用戶界面資源文件中創建界面。在Xcode中,這些文件是XIB文件

實現步驟如下:

  • 創建一個新的Cocoa Touch Class,命名爲AboutViewController,並選中“Also create XIB file”
  • 這時候多出了三個文件,將他們放到supporting files的上面
  • 打開AboutViewController.xib,這是IB文件,不支持任何腳本功能,如segue何連接。使用Attributes檢查器將視圖的頂部欄設置爲不透明的導航欄,發現導航欄不能編輯

這裏寫圖片描述

  • 使用Lable或其他,自行添加內容
  • 打開故事面板,添加一個About按鈕。位置看上面的圖。
  • 在ViewController.m中import AboutViewController.h
  • 將About拉到ViewController.h中創建action,名稱爲aboutCarValet
  • aboutCarValet方法代碼如下:
- (IBAction)aboutCarValet:(id)sender {
    AboutViewController *nextController;

    nextController = [[AboutViewController alloc]initWithNibName:@"AboutViewController"//1
                                                          bundle:[NSBundle mainBundle]];

    nextController.title = @"About CarValet";//2
    [self.navigationController pushViewController:nextController animated:YES];
}

註釋:

  1. 爲AboutViewController實例初始化next Controller視圖控制器。該調用用到了之前爲視圖控制器界面創建的XIB文件
  2. 設置About視圖的標題。尅本地化該字符串
  3. 告訴導航控制器將新的視圖控制器推到對戰中——也就是打開並轉場到該場景

運行結果:

這裏寫圖片描述

添加顏色

  我們在IB中,有時候會看到Tint(色調)選項。使用此選項是爲用戶體驗增加彩色主題的快速方法。需要注意的是,它與VIew區域中改變背景色是不同的。

  對UINavigationController來說,可以更改導航欄、工具欄和工具欄按鈕的色調。爲事物設置色調的工作由導航控制器進行管理,導航控制器會改變它管理的每個屏幕上該事物的顏色。

  打開故事面板,自行修改顏色。

這裏寫圖片描述

  可能會遇到工具欄色調不起作用,那麼我們可以用代碼實現,在ViewController.m中的viewDidLoad方法下,添加

UIColor *sky = [UIColor colorWithDisplayP3Red:102.0/255.0 green:204.0/255.0 blue:255.0/255.0 alpha:1.0];
    self.navigationController.toolbar.barTintColor = sky;

  這時候顏色就添加完啦,本程序還添加了其他顏色,配色方案如下

用戶界面元素 蘋果蠟筆顏色 RGB
工具欄 SKY R:102 G:204 B:255
標題 snow(white) R:255 G:255 B:255
按鈕 Mocha R:128 G:64 B:0

  但是我們上面的方法只能更改一個屏幕裏面的顏色,以下代碼是更改全部,在AppDelegate.m文件中

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
    // Override point for customization after application launch.
    UIColor *Mocha = [UIColor colorWithDisplayP3Red:128.0/255 green:64.0/255.0 blue:0/255.0 alpha:1.0];

    [[UIButton appearance]setTitleColor:Mocha forState:UIControlStateNormal];
    [[UIBarButtonItem appearance] setTintColor:Mocha];
    return YES;
}

  其中,最後兩行是通過appearance protocol協議修改按鈕,工具欄按鈕顏色。

  好了,導航控制器的使用就暫時介紹到這裏咯。

1 標籤欄控制器

  本想找clock程序作爲用例的,模擬器上竟然沒有。換成健康

這裏寫圖片描述

  看到下面的健康數據,今天,數據來源這些選項了吧,這些是標籤欄,每個欄對應不同的功能,而且有的欄裏面還有多個屏幕。

工具欄的工作原理

  使用UITabBarController時,每個功能區域或標籤欄都是根視圖,實際上,標籤欄控制器是應用程序真正的根視圖,簡單的畫一下。

這裏寫圖片描述

  標籤欄控制器使用如下三個主要類:

  • UITabBarController管理標籤欄選項卡中顯示的視圖控制器,並且還管理標籤欄的用戶交換,包括選擇處理選中。如果存在5個以上選項卡,那麼會展示More按鈕。它也管理對額外選項卡的訪問,並且管理選項卡的重新排序。
  • UITabBar是能呈現1至5個以上的選項卡的視圖。每個選項卡都代表應用程序中一個不同的根視圖。如果有5個以上的選項卡,那麼特殊的More標籤放置子在右邊
  • UITabBarIter是標籤欄的單個選項卡,包括兩個屬性分別用於標題和圖像,以及一個屬性用來自定義圖像在被選中時的行爲。

爲CarValet添加標籤欄

圖片什麼的之前已經導入了

  • 打開故事面板,選中下圖

這裏寫圖片描述

  • 選擇Editor|Embed In|Tab Bar Controller

這裏寫圖片描述

(PS,運行到這裏,標籤欄中應該是隻有一個圖標,圓形的還是方形的晚了)

  • 更換圖標

這裏寫圖片描述

  這時候是隻有一個選項卡的,我就不運行了。現在我們將car image場景添加爲第二個選項卡

  • 從Add/View場景中刪除Car Images按鈕
  • 從標籤欄拉到Car Images場景,從Relationship Segue類別中選擇視圖控制器。這是就添加上去了。
    這裏寫圖片描述

  • 更換圖標

這裏寫圖片描述

  • 這時候運行程序,下面有兩個選項卡了(PS我這是完整版,不要在意這些細節。。。)

這裏寫圖片描述

  然而運行的時候發現reset沒用

  進行以下步驟修改:

  • 在編輯器中打開CarImageViewController.h文件,將resetZoomButton的類別改成UIButton
  • 在iPhone故事面板中,選擇CarImageViewController並將一個正常的按鈕拖入到頂層視圖,改標題爲Reset Zoom
  • 設置約束,到頂部爲系統默認,到後邊緣爲0
  • 拖拽一個從該按鈕到.h文件中的resetZoomButton實例變量的關聯
  • 拖拽一個從該按鈕到car image視圖中發送resetZoom消息的關聯
  • 在與該按鈕相對應的Attributes編輯器中的Control部分,將默認值設置爲不可用

ok,運行程序就行啦。

最後一點,移動的Info

  我們通過代碼的形式添加about到標籤欄

  • 移除Add/View中的about按鈕
  • 打開ViewController.m並刪除對AboutVIewController.h的引用,刪除aboutCarValet:方法以及在ViewController.h中的定義
  • 打開AppDelegate.m,導入AboutVIewController.h的引用。然後修改代碼如下:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
    // Override point for customization after application launch.
    UIColor *Mocha = [UIColor colorWithDisplayP3Red:128.0/255 green:64.0/255.0 blue:0/255.0 alpha:1.0];

    [[UIButton appearance]setTitleColor:Mocha forState:UIControlStateNormal];
    [[UIBarButtonItem appearance] setTintColor:Mocha];

    UITabBarController *tabBarController = (UITabBarController*)self.window.rootViewController;//1
    //2
    AboutViewController *aboutViewController = [[AboutViewController alloc]initWithNibName:@"AboutViewController"
                                                                                    bundle:[NSBundle mainBundle]];
    UITabBarItem *aboutItem = [[UITabBarItem alloc]initWithTitle:@"About" //3
                                                           image:[UIImage imageNamed:@"tag"]
                                                             tag:0];
    [aboutViewController setTabBarItem:aboutItem];//4
    NSMutableArray *currentItems = [NSMutableArray arrayWithArray:tabBarController.viewControllers];//5
    [currentItems addObject:aboutViewController];//6
    [tabBarController setViewControllers:currentItems animated:NO];//7
    return YES;
}

註釋:

  1. 獲得對標籤欄控制器的引用。
  2. 從XIB文件創建About視圖控制器
  3. 爲About場景創建一個標籤欄選項,並設置合適的標題和圖片
  4. 將About視圖控制器的tabBarItem設置爲新的標籤欄選項。標籤欄控制器會在設置標籤欄選項的時候尋找該屬性
  5. 基於那些由標籤欄控制器進行管理的視圖控制器,創建一個可變數組
  6. 將About場景添加到視圖控制器數組的結尾。標籤欄選項以數組中相同的順序顯示
  7. 在應用程序啓動時,以不帶動畫效果的方式更新選項卡數組。如果該操作是在應用程序因用戶行爲而運行時發生,那麼我們可能願意以動畫效果更新變化

      好了運行程序,再次貼圖:

這裏寫圖片描述

今天的介紹就到這裏咯

我的另一個博客站點:Arnold-你們好啊

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章