版本記錄
版本號(hào) | 時(shí)間 |
---|---|
V1.0 | 2019.04.02 星期二 |
前言
iOS中有關(guān)視圖控件用戶能看到的都在UIKit框架里面,用戶交互也是通過UIKit進(jìn)行的茧吊。感興趣的參考上面幾篇文章坟岔。
1. UIKit框架(一) —— UIKit動(dòng)力學(xué)和移動(dòng)效果(一)
2. UIKit框架(二) —— UIKit動(dòng)力學(xué)和移動(dòng)效果(二)
3. UIKit框架(三) —— UICollectionViewCell的擴(kuò)張效果的實(shí)現(xiàn)(一)
4. UIKit框架(四) —— UICollectionViewCell的擴(kuò)張效果的實(shí)現(xiàn)(二)
5. UIKit框架(五) —— 自定義控件:可重復(fù)使用的滑塊(一)
6. UIKit框架(六) —— 自定義控件:可重復(fù)使用的滑塊(二)
7. UIKit框架(七) —— 動(dòng)態(tài)尺寸UITableViewCell的實(shí)現(xiàn)(一)
8. UIKit框架(八) —— 動(dòng)態(tài)尺寸UITableViewCell的實(shí)現(xiàn)(二)
9. UIKit框架(九) —— UICollectionView的數(shù)據(jù)異步預(yù)加載(一)
10. UIKit框架(十) —— UICollectionView的數(shù)據(jù)異步預(yù)加載(二)
11. UIKit框架(十一) —— UICollectionView的重用、選擇和重排序(一)
12. UIKit框架(十二) —— UICollectionView的重用、選擇和重排序(二)
開始
首先看下寫作環(huán)境
Swift 4.2, iOS 12, Xcode 10
在本教程中展父,您將構(gòu)建一個(gè)滑出式面板導(dǎo)航,這是使用普通UINavigationController
或UITabBarController
進(jìn)行應(yīng)用程序?qū)Ш降某S锰娲椒ā?滑出式導(dǎo)航面板允許用戶將內(nèi)容滑到屏幕或滑出屏幕。
打開已有的項(xiàng)目臣镣,下面的效果就是要達(dá)到的最終效果辅愿。
滑出導(dǎo)航面板設(shè)計(jì)模式允許開發(fā)人員為他們的應(yīng)用添加永久導(dǎo)航,而不會(huì)占用寶貴的屏幕空間忆某,因?yàn)橛脩艨梢噪S時(shí)選擇顯示導(dǎo)航点待,同時(shí)仍然可以看到他們當(dāng)前的上下文。
在本教程中弃舒,您將采用更少的方法癞埠,以便您可以相對(duì)輕松地將滑出式導(dǎo)航面板技術(shù)應(yīng)用于您自己的應(yīng)用程序。
從名為SlideOutNavigation.xcodeproj
的SlideOutNavigation-Starter
文件夾中打開項(xiàng)目聋呢,并查看它是如何組織的苗踪。除了視圖控制器之外,還有一個(gè)名為Assets.xcassets
的資產(chǎn)目錄削锰,其中包含您將在應(yīng)用程序中使用的所有可愛的小貓和小狗圖像通铲。
這是這個(gè)應(yīng)用程序的整體結(jié)構(gòu):
-
ContainerViewController
是魔術(shù)發(fā)生的地方!這是視圖控制器器贩,可以處理動(dòng)畫和中心視圖控制器與左右面板之間的滑動(dòng)等操作颅夺。它負(fù)責(zé)保存對(duì)所有其他必要視圖控制器的引用。 -
CenterViewController
是中心面板視圖控制器蛹稍。 -
SidePanelViewController
用作左側(cè)和右側(cè)面板視圖控制器吧黄。
您可以在Main.storyboard
中找到中央,左側(cè)和右側(cè)視圖控制器的視圖唆姐。所以拗慨,隨便看看整個(gè)項(xiàng)目。
現(xiàn)在您已經(jīng)熟悉了應(yīng)用程序的結(jié)構(gòu)奉芦,現(xiàn)在是時(shí)候從正方形 - 中心面板開始了赵抢。
Finding Your Center
第一項(xiàng)業(yè)務(wù)是將CenterViewController
放在ContainerViewController
中作為子視圖控制器。
打開ContainerViewController.swift
声功。 找到viewDidLoad()
并在其上方添加以下屬性:
var centerNavigationController: UINavigationController!
var centerViewController: CenterViewController!
這兩個(gè)屬性將同時(shí)包含centerViewController
及其父導(dǎo)航控制器烦却。
注意:這些是隱式解包的選項(xiàng)(由!表示)减噪。 它們必須是可選的短绸,因?yàn)樗鼈兊闹翟?code>init()完成之前不會(huì)被初始化,但它們可以隱式解包筹裕,因?yàn)槟阒浪鼈儠?huì)在你使用它們時(shí)被初始化醋闭。 如果不是,那么這是一個(gè)程序員錯(cuò)誤朝卒,你想在測(cè)試應(yīng)用程序時(shí)知道它证逻。
在文件的底部,您將看到UIStoryboard
的類擴(kuò)展抗斤,其中包含一些靜態(tài)方法囚企,可以更方便地從應(yīng)用程序的故事板中加載特定的視圖控制器丈咐。 您將利用這些方法填充剛剛創(chuàng)建的屬性。
在對(duì)super
的調(diào)用下面的viewDidLoad()
中添加以下代碼:
// 1
centerViewController = UIStoryboard.centerViewController()
// 2
centerViewController.delegate = self
// 3
centerNavigationController = UINavigationController(rootViewController: centerViewController)
view.addSubview(centerNavigationController.view)
addChild(centerNavigationController)
// 4
centerNavigationController.didMove(toParent: self)
不要擔(dān)心第二行上的編譯器錯(cuò)誤龙宏,你很快就會(huì)解決這個(gè)問題棵逊。
這個(gè)簡(jiǎn)短的方法有一些有趣的東西。這是你正在做的事情:
- 1) 通過從故事板中拉出它來獲取
centerViewController
银酗。 - 2) 將當(dāng)前視圖控制器設(shè)置為中心視圖控制器的委托辆影,以便中心視圖控制器可以通知其容器何時(shí)顯示和隱藏左側(cè)和右側(cè)面板。
- 3) 創(chuàng)建一個(gè)導(dǎo)航控制器以包含中心視圖控制器黍特,以便您可以將視圖推送到它并在導(dǎo)航欄中顯示條形按鈕項(xiàng)目蛙讥。然后,將導(dǎo)航控制器的視圖添加到
ContainerViewController
的視圖中灭衷。 - 4) 使用
addChild(_ :)
和didMove(toParent :)
設(shè)置父子關(guān)系次慢。
真棒!現(xiàn)在要處理下錯(cuò)誤翔曲,修改此類以便它實(shí)現(xiàn)CenterViewControllerDelegate
迫像。
將以下類擴(kuò)展添加到文件底部的UIStoryboard
擴(kuò)展下面的ContainerViewController
(這還包括一些您將在稍后填寫的空方法):
// MARK: CenterViewController delegate
extension ContainerViewController: CenterViewControllerDelegate {
func toggleLeftPanel() {
}
func toggleRightPanel() {
}
func collapseSidePanels() {
}
}
實(shí)現(xiàn)這些方法使此類符合CenterViewControllerDelegate
。
現(xiàn)在是檢查進(jìn)度的好時(shí)機(jī)部默。 構(gòu)建并運(yùn)行應(yīng)用程序侵蒙。 您應(yīng)該看到類似于以下屏幕的內(nèi)容:
是的造虎,頂部的那些按鈕最終將為您帶來小貓和小狗傅蹂。 創(chuàng)建滑動(dòng)導(dǎo)航面板有什么更好的理由? 但為了讓你更可愛算凿,你必須開始滑動(dòng)份蝴。 首先,向左氓轰!
Kittens to the Left of Me…
您已創(chuàng)建了中心面板婚夫,但添加左視圖控制器需要一組不同的步驟。
要展開左側(cè)面板署鸡,用戶將點(diǎn)擊導(dǎo)航欄中的Kitties
按鈕案糙。 打開CenterViewController.swift
開始實(shí)現(xiàn)它。
為了使本教程專注于重要的內(nèi)容靴庆,IBActions
和IBOutlets
在故事板中為您預(yù)先連接时捌。 但是,要實(shí)現(xiàn)DIY滑出式導(dǎo)航面板炉抒,您需要了解按鈕的配置方式奢讨。
請(qǐng)注意,已經(jīng)有兩種IBAction
方法焰薄,每種方法對(duì)應(yīng)一個(gè)按鈕拿诸。 找到kittiesTapped(_ :)
并將以下實(shí)現(xiàn)添加到其中:
delegate?.toggleLeftPanel()
如前所述扒袖,該方法已經(jīng)連接到Kitties
按鈕。 僅當(dāng)delegate
具有值時(shí)亩码,這使用可選鏈接來調(diào)用toggleLeftPanel()
季率。
您可以在底部看到委托協(xié)議的定義。 正如您將看到的描沟,有一些方法叫做toggleLeftPanel()
蚀同,toggleRightPanel()
和collapseSidePanels()
。 如果您還記得啊掏,當(dāng)您先設(shè)置中心視圖控制器實(shí)例時(shí)蠢络,將其委托設(shè)置為容器視圖控制器。 是時(shí)候去實(shí)現(xiàn)toggleLeftPanel()
了迟蜜。
注意:有關(guān)委托方法及其實(shí)現(xiàn)方式的更多信息刹孔,請(qǐng)參閱Apple’s Developer Documentation。
打開ContainerViewController.swift
并在ContainerViewController
的頂部添加一個(gè)枚舉:
enum SlideOutState {
case bothCollapsed
case leftPanelExpanded
case rightPanelExpanded
}
您將使用它來跟蹤側(cè)面板的當(dāng)前狀態(tài)娜睛,因此您可以判斷兩個(gè)面板是否都不可見髓霞,或者左側(cè)或右側(cè)面板中的一個(gè)是否可見。
接下來畦戒,在現(xiàn)有的centerViewController
屬性下添加兩個(gè)屬性:
var currentState: SlideOutState = .bothCollapsed
var leftViewController: SidePanelViewController?
這些將保持側(cè)面板和左側(cè)面板視圖控制器本身的當(dāng)前狀態(tài):
您將currentState
初始化為.bothCollapsed
- 也就是說方库,當(dāng)應(yīng)用程序首次加載時(shí),兩個(gè)側(cè)面板都不可見障斋。 leftViewController
屬性是可選的纵潦,因?yàn)槟鷮⒃诓煌瑫r(shí)間添加和刪除視圖控制器,因此它可能并不總是具有值垃环。
接下來邀层,添加toggleLeftPanel()
的實(shí)現(xiàn):
let notAlreadyExpanded = (currentState != .leftPanelExpanded)
if notAlreadyExpanded {
addLeftPanelViewController()
}
animateLeftPanel(shouldExpand: notAlreadyExpanded)
首先,此方法檢查左側(cè)面板是否已展開遂庄。 如果它尚未顯示寥院,則調(diào)用一個(gè)方法將面板添加到視圖層次結(jié)構(gòu)中。 然后涛目,它調(diào)用另一種方法秸谢,將其動(dòng)畫為open
位置。 如果面板已經(jīng)可見霹肝,則它將面板設(shè)置為closed
位置的動(dòng)畫估蹄。
接下來,您需要添加代碼以將左側(cè)面板添加到視圖層次結(jié)構(gòu)中阿迈。 在下面添加以下toggleLeftPanel()
:
func addLeftPanelViewController() {
guard leftViewController == nil else { return }
if let vc = UIStoryboard.leftViewController() {
vc.animals = Animal.allCats()
addChildSidePanelController(vc)
leftViewController = vc
}
}
此代碼首先檢查leftViewController
屬性是否為nil
元媚。 如果是,則創(chuàng)建一個(gè)新的SidePanelViewController
并設(shè)置要顯示的動(dòng)物列表 - 在這種情況下,貓刊棕!
接下來炭晒,在擴(kuò)展的底部添加addChildSidePanelController(_ :)
的實(shí)現(xiàn):
func addChildSidePanelController(_ sidePanelController: SidePanelViewController) {
view.insertSubview(sidePanelController.view, at: 0)
addChild(sidePanelController)
sidePanelController.didMove(toParent: self)
}
此方法將子視圖控制器添加到容器視圖控制器。 這與先前添加中心視圖控制器相同甥角。 它只是插入它的視圖 - 在這種情況下网严,它插入z-index 0
,這意味著它將在中心視圖控制器下面 - 并將其添加為子視圖控制器嗤无。
在ContainerViewController
頂部的其他屬性下面添加以下常量:
let centerPanelExpandedOffset: CGFloat = 90
此值是中心視圖控制器在屏幕上設(shè)置動(dòng)畫后可見的寬度(以磅為單位)震束。 90
個(gè)點(diǎn)應(yīng)該可以了。
接下來当犯,返回CenterViewControllerDelegate
擴(kuò)展垢村,在addLeftPanelViewController()
下面添加以下內(nèi)容:
func animateLeftPanel(shouldExpand: Bool) {
if shouldExpand {
currentState = .leftPanelExpanded
animateCenterPanelXPosition(
targetPosition: centerNavigationController.view.frame.width
- centerPanelExpandedOffset)
} else {
animateCenterPanelXPosition(targetPosition: 0) { _ in
self.currentState = .bothCollapsed
self.leftViewController?.view.removeFromSuperview()
self.leftViewController = nil
}
}
}
此方法首先檢查是否已告知它是否展開或折疊側(cè)面板。 如果它應(yīng)該展開嚎卫,則它設(shè)置當(dāng)前狀態(tài)以指示左面板已展開并調(diào)用方法為中心面板設(shè)置動(dòng)畫以使其打開嘉栓。 否則,它會(huì)動(dòng)畫中心面板關(guān)閉拓诸,移除其視圖并設(shè)置當(dāng)前狀態(tài)以指示它已關(guān)閉侵佃。
現(xiàn)在在addChildSidePanelController(_ :)
上面添加這個(gè)方法:
func animateCenterPanelXPosition(
targetPosition: CGFloat,
completion: ((Bool) -> Void)? = nil) {
UIView.animate(
withDuration: 0.5,
delay: 0,
usingSpringWithDamping: 0.8
initialSpringVelocity: 0,
options: .curveEaseInOut,
animations: {
self.centerNavigationController.view.frame.origin.x = targetPosition
},
completion: completion)
}
這是實(shí)際動(dòng)畫發(fā)生的地方。 它使用漂亮的彈簧動(dòng)畫將中心視圖控制器的視圖移動(dòng)到指定位置奠支。 該方法還采用可選的完成閉包馋辈,并將其傳遞給UIView動(dòng)畫。 如果要更改動(dòng)畫的外觀倍谜,可以嘗試調(diào)整持續(xù)時(shí)間和彈簧阻尼參數(shù)迈螟。
構(gòu)建并運(yùn)行應(yīng)用程序。
點(diǎn)擊導(dǎo)航欄中的Kitties
枢劝。 中央視圖控制器應(yīng)該滑過 - 嗖井联! - 并顯示下面的Kitties
菜單卜壕。 噢您旁,看看他們都很可愛。
但太多的可愛可能是一件危險(xiǎn)的事情轴捎! 再次點(diǎn)擊Kitties
按鈕隱藏它們鹤盒!
Me and My Shadow
當(dāng)左側(cè)面板打開時(shí),請(qǐng)注意它是如何正對(duì)著中央視圖控制器的侦副。 如果它們之間有一點(diǎn)間隔侦锯,那就太好了。 添加陰影怎么樣秦驯?
仍然在ContainerViewController.swift
中尺碰,將以下方法添加到擴(kuò)展的末尾:
func showShadowForCenterViewController(_ shouldShowShadow: Bool) {
if shouldShowShadow {
centerNavigationController.view.layer.shadowOpacity = 0.8
} else {
centerNavigationController.view.layer.shadowOpacity = 0.0
}
}
這會(huì)調(diào)整導(dǎo)航控制器陰影的不透明度,使其可見或隱藏。 每當(dāng)currentState
屬性更改時(shí)亲桥,您將實(shí)現(xiàn)didSet
觀察器以添加或刪除陰影洛心。
滾動(dòng)到ContainerViewController.swift
的頂部并將currentState
聲明更改為:
var currentState: SlideOutState = .bothCollapsed {
didSet {
let shouldShowShadow = currentState != .bothCollapsed
showShadowForCenterViewController(shouldShowShadow)
}
}
只要屬性的值發(fā)生變化,就會(huì)執(zhí)行didSet
閉包题篷。 如果任一面板可見词身,則顯示陰影。
再次構(gòu)建并運(yùn)行應(yīng)用程序番枚。 這次當(dāng)你點(diǎn)擊Kitties
時(shí)法严,看看甜蜜的新影子! 看起來更好葫笼,對(duì)吧深啤?
接下來,為右側(cè)添加相同的功能路星,這意味著...小狗墓塌!
Puppies to the Right…
要添加右側(cè)面板視圖控制器,只需重復(fù)添加左側(cè)視圖控制器的步驟奥额。
打開ContainerViewController.swift
并在leftViewController
下面添加以下屬性:
var rightViewController: SidePanelViewController?
接下來苫幢,找到toggleRightPanel()
并添加以下實(shí)現(xiàn):
let notAlreadyExpanded = (currentState != .rightPanelExpanded)
if notAlreadyExpanded {
addRightPanelViewController()
}
animateRightPanel(shouldExpand: notAlreadyExpanded)
接下來,添加以下toggleRightPanel()
:
func addRightPanelViewController() {
guard rightViewController == nil else { return }
if let vc = UIStoryboard.rightViewController() {
vc.animals = Animal.allDogs()
addChildSidePanelController(vc)
rightViewController = vc
}
}
func animateRightPanel(shouldExpand: Bool) {
if shouldExpand {
currentState = .rightPanelExpanded
animateCenterPanelXPosition(
targetPosition: -centerNavigationController.view.frame.width
+ centerPanelExpandedOffset)
} else {
animateCenterPanelXPosition(targetPosition: 0) { _ in
self.currentState = .bothCollapsed
self.rightViewController?.view.removeFromSuperview()
self.rightViewController = nil
}
}
}
此代碼幾乎與左側(cè)面板的代碼完全相同垫挨,當(dāng)然韩肝,除了方法和屬性名稱以及方向的差異之外。 如果您對(duì)此有任何疑問九榔,可以隨時(shí)查看上一節(jié)中的說明哀峻。
與以前一樣,IBActions
和IBOutlets
已經(jīng)在故事板中為您連接哲泊。 與Kitties
類似剩蟀,Puppies
連接到名為puppiesTapped(_ :)
的IBAction
方法。 此按鈕控制中央面板的滑動(dòng)以顯示右側(cè)面板切威。
切換到CenterViewController.swift
并將以下行添加到puppiesTapped(_ :)
:
delegate?.toggleRightPanel()
同樣育特,這與kittiesTapped(_ :)
相同,只是它切換右側(cè)面板而不是左側(cè)面板先朦。
是時(shí)候看一些小狗了缰冤!
再次構(gòu)建并運(yùn)行應(yīng)用程序以確保一切正常。 點(diǎn)擊小狗喳魏。 您的屏幕應(yīng)如下所示:
看起來不錯(cuò)吧棉浸? 但請(qǐng)記住,你不想讓自己暴露在幼犬的可愛中太長(zhǎng)時(shí)間刺彩,所以再次點(diǎn)擊該按鈕以隱藏它們迷郑。
您現(xiàn)在可以查看小貓和小狗枝恋,但是能夠查看每個(gè)小貓的大圖非常棒,不是嗎嗡害?
Pick an Animal, Any Animal!
小貓和小狗列在左側(cè)和右側(cè)小組中鼓择。 這些都是SidePanelViewController
的實(shí)例,它只包含一個(gè)table view
就漾。
打開SidePanelViewController.swift
以查看SidePanelViewControllerDelegate
協(xié)議呐能。 無論何時(shí)點(diǎn)擊動(dòng)物,都可以通過此方法通知側(cè)面板的代表抑堡。 是時(shí)候用了摆出!
在SidePanelViewController.swift
中,在類頂部添加以下屬性首妖,在表視圖IBOutlet
下面:
var delegate: SidePanelViewControllerDelegate?
然后偎漫,在UITableViewDelegate
擴(kuò)展中填寫tableView(_:didSelectRowAt :)
的實(shí)現(xiàn):
let animal = animals[indexPath.row]
delegate?.didSelectAnimal(animal)
如果有一個(gè)委托集,這將告訴用戶選擇了一個(gè)動(dòng)物有缆。 目前象踊,沒有代理! 將CenterViewController
作為側(cè)面板的委托是有意義的棚壁,因?yàn)樗梢燥@示所選的動(dòng)物照片和標(biāo)題杯矩。
打開CenterViewController.swift
以實(shí)現(xiàn)委托協(xié)議。 在現(xiàn)有類定義下添加以下擴(kuò)展:
extension CenterViewController: SidePanelViewControllerDelegate {
func didSelectAnimal(_ animal: Animal) {
imageView.image = animal.image
titleLabel.text = animal.title
creatorLabel.text = animal.creator
delegate?.collapseSidePanels()
}
}
此方法只使用動(dòng)物的圖像袖外,標(biāo)題和創(chuàng)建者填充中心視圖控制器中的圖像視圖和標(biāo)簽史隆。 然后,如果中心視圖控制器具有自己的委托曼验,則告訴它折疊側(cè)面板泌射,以便您可以專注于所選項(xiàng)目。
但是鬓照,collapseSidePanels()
不會(huì)做任何事情熔酷! 打開,ContainerViewController.swift
并將以下實(shí)現(xiàn)添加到collapseSidePanels()
:
switch currentState {
case .rightPanelExpanded:
toggleRightPanel()
case .leftPanelExpanded:
toggleLeftPanel()
case .bothCollapsed:
break
}
此方法中的switch
語句只檢查側(cè)面板的當(dāng)前狀態(tài)豺裆,并折疊打開的任何一個(gè)拒秘。
現(xiàn)在,找到addChildSidePanelController(_ :)
并將以下內(nèi)容添加到方法的底部:
sidePanelController.delegate = centerViewController
除了之前的工作之外留储,該方法現(xiàn)在將中心視圖控制器設(shè)置為側(cè)面板的委托翼抠。
應(yīng)該這樣做!
構(gòu)建并運(yùn)行應(yīng)用程序获讳。 查看小貓或小狗,然后點(diǎn)擊其中一個(gè)可愛的小動(dòng)物活喊。 側(cè)面板應(yīng)該再次折疊丐膝,你應(yīng)該看到你選擇的動(dòng)物的細(xì)節(jié)。
Move Your Hands Back and Forth
導(dǎo)航欄按鈕很棒,但大多數(shù)應(yīng)用程序還允許您滑動(dòng)以打開側(cè)面板帅矗。 向您的應(yīng)用添加手勢(shì)非常簡(jiǎn)單偎肃。 不要被暗示,你會(huì)做得很好浑此!
再次打開ContainerViewController.swift
累颂。 首先,通過在UIStoryboard
擴(kuò)展上方添加以下擴(kuò)展凛俱,使此類符合UIGestureRecognizerDelegate
:
// MARK: Gesture recognizer
extension ContainerViewController: UIGestureRecognizerDelegate {
@objc func handlePanGesture(_ recognizer: UIPanGestureRecognizer) {
}
}
接下來紊馏,找到viewDidLoad()
。 將以下內(nèi)容添加到方法的末尾:
let panGestureRecognizer = UIPanGestureRecognizer(
target: self,
action: #selector(handlePanGesture(_:)))
centerNavigationController.view.addGestureRecognizer(panGestureRecognizer)
這將創(chuàng)建一個(gè)UIPanGestureRecognizer
蒲犬,將self
指定為target
朱监,并將handlePanGesture(_ :)
作為選擇器來處理任何檢測(cè)到的拖動(dòng)手勢(shì)。
默認(rèn)情況下原叮,拖動(dòng)手勢(shì)識(shí)別器會(huì)檢測(cè)單個(gè)手指的單次觸摸赫编,因此不需要任何額外配置。 您只需要將新創(chuàng)建的手勢(shì)識(shí)別器添加到centerNavigationController
視圖中奋隶。
我不是告訴你這很簡(jiǎn)單嗎擂送? 您的滑出導(dǎo)航面板例程中只剩下一個(gè)移動(dòng)。 手勢(shì)識(shí)別器在檢測(cè)到手勢(shì)時(shí)調(diào)用handlePanGesture(_ :)
唯欣。 因此团甲,本教程的最后一項(xiàng)任務(wù)是實(shí)現(xiàn)該方法。
將以下代碼塊添加到handlePanGesture(_ :)
(這是一個(gè)很多代碼J蚰簟):
// 1
let gestureIsDraggingFromLeftToRight = (recognizer.velocity(in: view).x > 0)
// 2
switch recognizer.state {
// 3
case .began:
if currentState == .bothCollapsed {
if gestureIsDraggingFromLeftToRight {
addLeftPanelViewController()
} else {
addRightPanelViewController()
}
showShadowForCenterViewController(true)
}
// 4
case .changed:
if let rview = recognizer.view {
rview.center.x = rview.center.x + recognizer.translation(in: view).x
recognizer.setTranslation(CGPoint.zero, in: view)
}
// 5
case .ended:
if let _ = leftViewController,
let rview = recognizer.view {
// animate the side panel open or closed based on whether the view
// has moved more or less than halfway
let hasMovedGreaterThanHalfway = rview.center.x > view.bounds.size.width
animateLeftPanel(shouldExpand: hasMovedGreaterThanHalfway)
} else if let _ = rightViewController,
let rview = recognizer.view {
let hasMovedGreaterThanHalfway = rview.center.x < 0
animateRightPanel(shouldExpand: hasMovedGreaterThanHalfway)
}
default:
break
}
下面進(jìn)行細(xì)分:
- 1) 拖動(dòng)手勢(shì)識(shí)別器可以檢測(cè)任何方向的平移躺苦,但您只對(duì)水平移動(dòng)感興趣。首先产还,設(shè)置
gestureIsDraggingFromLeftToRight
布爾值匹厘,以使用手勢(shì)速度的x分量來檢查這一點(diǎn)。 - 2) 需要跟蹤三種狀態(tài):
UIGestureRecognizerState.began
脐区,UIGestureRecognizerState.changed
和UIGestureRecognizerState.ended
愈诚。使用switch
相應(yīng)地處理每個(gè)。 - 3)
.began
:如果用戶開始平移且兩個(gè)面板都不可見牛隅,則根據(jù)平移方向顯示正確的面板并使陰影可見炕柔。 - 4)
.changed
:如果用戶已經(jīng)在平移,請(qǐng)按用戶平移的距離移動(dòng)中心視圖控制器的視圖 - 5)
.ended
:當(dāng)拖動(dòng)結(jié)束時(shí)媒佣,檢查左視圖控制器或右視圖控制器是否可見匕累。根據(jù)哪個(gè)可見以及平移了多遠(yuǎn),執(zhí)行動(dòng)畫默伍。
您可以使用這三種狀態(tài)的組合以及平移手勢(shì)的位置欢嘿,速度和方向來移動(dòng)中心視圖衰琐,顯示和隱藏左視圖和右視圖。
例如炼蹦,如果手勢(shì)方向是右側(cè)羡宙,則顯示左側(cè)面板。如果方向是左側(cè)掐隐,則顯示右側(cè)面板狗热。
再次構(gòu)建并運(yùn)行應(yīng)用程序。此時(shí)虑省,您應(yīng)該能夠左右滑動(dòng)中央面板匿刮,露出下面的面板。
如果您想通過DIY解決方案嘗試預(yù)建庫(kù)慷妙,請(qǐng)務(wù)必查看SideMenu僻焚。 有關(guān)此UI控件的起源(以及內(nèi)存通道)的深入討論,請(qǐng)查看iOS開發(fā)人員和設(shè)計(jì)師Ken Yarmosh發(fā)布的New iOS Design Pattern: Slide-Out Navigation膝擂。 他很好地解釋了使用這種設(shè)計(jì)模式的好處并展示了常見用途虑啤。
后記
本篇主要講述了如何創(chuàng)建自己的側(cè)滑式面板導(dǎo)航,感興趣的給個(gè)贊或者關(guān)注~~~