[iOS] #1 運用 Storyboard 模仿視覺化搜尋App『Pinterest』
之前沈迷於動物森友會(還在遊戲裡舉辦生日趴踢),常透過Pinterest尋找佈置靈感,情緒低落的時候也很適合打開Pinterest瀏覽各種可愛時尚漂亮的影像轉換心情!因此這次作業決定以Pinterest為模仿對象,練習各種UI元件的運用。
展示
minimap
頁面串接 > Tab Bar Controller
Pinterest以Tab切換五個主頁面:首頁、搜尋、建立、通知、已儲存,除了基本的各個View Controller的串接之外,特別筆記如何變更Tab字體及圖示的顏色。由於Attributes面板沒有相關設定,需改由Identity面板定義:
(1) 點選Tab Bar Controller 中的 Tab Bar
(2) 再切換至 Identity Inspector 於 User Define Runtime Attributes 設定
(3) Key Path = tintColor,Type = Color,Value = 由選色工具挑選
頁面串接 > Navigation Controller
五個主頁面都採用Navigation Controller串接不同階層的子頁面,每一層頁面會自動於左上方顯示Back按鈕,若有設定Title,Back會自動變更為Title字串,但若不想在頁面上顯示Title,又想自訂Back按鈕的文字,也可以利用Back Button項目客製。在此練習如何變更Back的字串和顏色:
> 變更Back文字
(1) 點選上一頁的Title Bar
(2) 切換至Attributes Inspector面板
(3) 在Back Button欄位輸入想要顯示的文字
> 變更 Back 顏色
(1) 展開上一頁的Navigation Item,點選Back Button
(2) 切換至Attributes Inspector面板
(3) 在 Tint 項目設定顏色
A. 首頁
(A-1) 橫向Scroll View
上方的橫向捲動按鈕選單,運用Scroll View實現。一開始在模擬器無法捲動,才發現由於這個Scroll View的位置和Navigation Title重疊,必須把Navigation Bar的User Interaction Enabled取消勾選,使用者才能直接點觸到Scroll View。
(A-2) 直向Scroll View
首頁的照片以Button、Label組成,利用Button的Corner Style設定照片的圓角效果,每張照片右下角的 + 按鈕,也是利用Button Corner Style = Capsule繪製成圓形。點選任一個照片按鈕,即可進入該照片的詳細說明頁。
(A-3) 詳細說明頁
詳細說明頁以圓角卡片的形式呈現。因此將外層View設定User Define Runtime Attributes:KeyPath = cornerRadius、Type = Number、Value=數字愈大愈圓。另外也要記得在View的Attribute模板勾選Clips to Bounds,才能讓Image View的邊緣也一同切出圓角。
B. 搜尋
搜尋功能我只繪製了Search Bar,待之後更熟悉Swift再來追加 !
C. 建立
Tab建立的頁面與其他Tab不同,點選之後並沒有切換頁面,而是在原本的頁面上方,新增只有螢幕高度一半的View,且將原頁面加上毛玻璃效果,以突顯新區塊的內容。若使用者再點選其他Tab,將解除畫面上的毛玻璃效果,並隱藏新區塊。
在網路上搜尋到的解決方案得透過程式實現,不確定做法是否正確。主要的概念是在既有的View上面,透過程式動態追加新的View蓋在上方,總共需要蓋兩個新的View,一個是毛玻璃View,一個是螢幕一半的View。
(C-1) 利用Storyboard繪製View,並指定Identity Id = MyView,以便程式透過Id取得View物件。
(C-2) 在ViewController.swift撰寫程式如下:
class TabBarController: UITabBarController, UITabBarControllerDelegate {
override func viewDidLoad() {
super.viewDidLoad()
self.delegate = self
}
func tabBarController(_ tabBarController: UITabBarController,
shouldSelect viewController: UIViewController) -> Bool {
//偵測目前使用者點選了哪一個Tab
let tabbarIndex = tabBarController.viewControllers!.firstIndex(of: viewController)!
//偵測目前畫面上停留的是哪一個View
let getCurrentView = tabBarController.selectedViewController!.view!
//remove subviews
//檢查目前是不是已經有毛玻璃View和“建立View",若有的話要先移除,不然會產生千千萬萬個View
//程式產生"建立View"時,已指定View.Tag=999,因此可以透過viewWithTag的function找到它
if let viewWithTag = getCurrentView.viewWithTag(999) {
//將"建立View"移除
viewWithTag.removeFromSuperview()
}
//程式產生毛玻璃View時,已指定View.Tag=998,因此可以透過viewWithTag的function找到它
if let maskWithTag = getCurrentView.viewWithTag(998) {
//將毛玻璃View移除
maskWithTag.removeFromSuperview()
}
//如果使用者點選“建立Tab”
if tabbarIndex == 2 {
//---- 毛玻璃View ----//
//設定毛玻璃效果
let blurEffect = UIBlurEffect(style: .systemUltraThinMaterialLight)
//產生一個新的view,加上毛玻璃效果
let blurView = UIVisualEffectView(effect: blurEffect)
//給毛玻璃View加個標籤,之後需要透過Tag找到它
blurView.tag = 998
//指定View在螢幕上的座標和長寬尺寸
//毛玻璃要蓋住整個View,所以直接取用目前的尺寸
blurView.frame = CGRectMake(0, 0, self.view.frame.size.width, self.view.frame.size.height);
//在目前顯示的View上面,加一層新的View
getCurrentView.addSubview(blurView)
//---- "建立View" ----
//直接把透過Storyboard繪製的View作為"建立View"
//預先在Storyboard的Identity面板設定View的Id="MyView"
//利用Id找到已繪製好的View
let myview = storyboard!.instantiateViewController(withIdentifier: "MyView").view
//給"建立View"加個標籤,之後需要透過Tag找到它
myview?.tag = 999
//指定View在螢幕上的座標和長寬尺寸
//View是在螢幕的下方,高度300,因此Y座標可以利用上一層View的高度-300計算而得
myview?.frame = CGRectMake(0, self.view.frame.size.height-300, self.view.frame.size.width, 300);
//在目前顯示的View上面,加一層新的View
getCurrentView.addSubview(myview!)
//確保"建立View"蓋在所有View的最上方
getCurrentView.bringSubviewToFront(myview!)
return false
} else {
return true
}
}
}
D. 通知
Table View Controller
通知主頁採用Table View,表格選擇靜態格式 ( Content = Static Cells ),以符合每一列內容都不相同的需求。原本畫面最上方的 “更新” 及 “訊息“ 按鈕,應是固定在Title Bar的位置,當捲動Table View時,兩個按鈕固定待在原處才對,但我一直找不到方法在Table View的Header放置按鈕,只好暫時將兩個按鈕放在Table View內的第一列中,也因此會跟著整個表格往上捲。之後若找到解決方式再來更新文章。
相片拼貼
Pinterest常有相片拼貼的區塊,區塊內的相片會以白色邊線區隔。每個區塊以一個View和多個Image View組成。
底層的View,BackgroundColor = 白色,且設定為圓角(在Identity模板設定User Define Runtime Attributes:KeyPath = cornerRadius、Type = Number、Value=數字愈大愈圓),也要記得在Attribute模板勾選Clips to Bounds,才能讓Image View的邊緣也一同切出圓角。
Image View可以隨意編排,但彼此之間保留一點空隙,就會有白色邊線的效果。
E. 已儲存
已儲存Tab的內容,和其他Tab採用的UI大致相似,比較不一樣的地方是進入第二層相片流選單時,下方的Tab Button自動隱藏。這可簡單於Storyboard的Attribute面板設定即可。
(1) 點選View Controller
(2) 切換至Attributes Inspector面板
(3) 勾選 Hide Bottom Bar On Push
心得
練習真的是熟悉的最佳法門!從一開始參考課程投影片一步一步操作,到後來幾秒鐘就可以設定好Scroll View了。忍不住要讚嘆Xcode的開發環境真的非常友善,元件們會乖乖地待在正確的位置,很多背後的小細節都幫忙處理好,畫面和工具也簡單明暸,不會迷失在繁複的介面中。一方面也期許自己深入認識更多種類的UI元件,才能挑選出最符合需求的UI組合。