版本記錄
版本號 | 時間 |
---|---|
V1.0 | 2019.04.03 星期三 |
前言
iOS中有關(guān)視圖控件用戶能看到的都在UIKit框架里面凑保,用戶交互也是通過UIKit進行的熄求。感興趣的參考上面幾篇文章。
1. UIKit框架(一) —— UIKit動力學(xué)和移動效果(一)
2. UIKit框架(二) —— UIKit動力學(xué)和移動效果(二)
3. UIKit框架(三) —— UICollectionViewCell的擴張效果的實現(xiàn)(一)
4. UIKit框架(四) —— UICollectionViewCell的擴張效果的實現(xiàn)(二)
5. UIKit框架(五) —— 自定義控件:可重復(fù)使用的滑塊(一)
6. UIKit框架(六) —— 自定義控件:可重復(fù)使用的滑塊(二)
7. UIKit框架(七) —— 動態(tài)尺寸UITableViewCell的實現(xiàn)(一)
8. UIKit框架(八) —— 動態(tài)尺寸UITableViewCell的實現(xiàn)(二)
9. UIKit框架(九) —— UICollectionView的數(shù)據(jù)異步預(yù)加載(一)
10. UIKit框架(十) —— UICollectionView的數(shù)據(jù)異步預(yù)加載(二)
11. UIKit框架(十一) —— UICollectionView的重用、選擇和重排序(一)
12. UIKit框架(十二) —— UICollectionView的重用患膛、選擇和重排序(二)
13. UIKit框架(十三) —— 如何創(chuàng)建自己的側(cè)滑式面板導(dǎo)航(一)
源碼
首先看下代碼組織結(jié)構(gòu)
接著看下xib中的內(nèi)容
下面就是源碼了
1. AppDelegate.swift
import UIKit
@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
var window: UIWindow?
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey : Any]? = nil) -> Bool {
window = UIWindow(frame: UIScreen.main.bounds)
let containerViewController = ContainerViewController()
window!.rootViewController = containerViewController
window!.makeKeyAndVisible()
return true
}
}
2. SidePanelViewController.swift
import UIKit
class SidePanelViewController: UIViewController {
@IBOutlet weak var tableView: UITableView!
var delegate: SidePanelViewControllerDelegate?
var animals: [Animal]!
enum CellIdentifiers {
static let AnimalCell = "AnimalCell"
}
override func viewDidLoad() {
super.viewDidLoad()
tableView.reloadData()
}
}
// MARK: Table View Data Source
extension SidePanelViewController: UITableViewDataSource {
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return animals.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: CellIdentifiers.AnimalCell, for: indexPath) as! AnimalCell
cell.configureForAnimal(animals[indexPath.row])
return cell
}
}
// Mark: Table View Delegate
extension SidePanelViewController: UITableViewDelegate {
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
let animal = animals[indexPath.row]
delegate?.didSelectAnimal(animal)
}
}
protocol SidePanelViewControllerDelegate {
func didSelectAnimal(_ animal: Animal)
}
3. CenterViewController.swift
import UIKit
class CenterViewController: UIViewController {
@IBOutlet weak var imageView: UIImageView!
@IBOutlet weak var titleLabel: UILabel!
@IBOutlet weak var creatorLabel: UILabel!
var delegate: CenterViewControllerDelegate?
// MARK: Button actions
@IBAction func kittiesTapped(_ sender: Any) {
delegate?.toggleLeftPanel()
}
@IBAction func puppiesTapped(_ sender: Any) {
delegate?.toggleRightPanel()
}
}
extension CenterViewController: SidePanelViewControllerDelegate {
func didSelectAnimal(_ animal: Animal) {
imageView.image = animal.image
titleLabel.text = animal.title
creatorLabel.text = animal.creator
delegate?.collapseSidePanels()
}
}
protocol CenterViewControllerDelegate {
func toggleLeftPanel()
func toggleRightPanel()
func collapseSidePanels()
}
4. ContainerViewController.swift
import UIKit
class ContainerViewController: UIViewController {
enum SlideOutState {
case bothCollapsed
case leftPanelExpanded
case rightPanelExpanded
}
var centerNavigationController: UINavigationController!
var centerViewController: CenterViewController!
var currentState: SlideOutState = .bothCollapsed {
didSet {
let shouldShowShadow = currentState != .bothCollapsed
showShadowForCenterViewController(shouldShowShadow)
}
}
var leftViewController: SidePanelViewController?
var rightViewController: SidePanelViewController?
let centerPanelExpandedOffset: CGFloat = 90
override func viewDidLoad() {
super.viewDidLoad()
centerViewController = UIStoryboard.centerViewController()
centerViewController.delegate = self
// wrap the centerViewController in a navigation controller, so we can push views to it
// and display bar button items in the navigation bar
centerNavigationController = UINavigationController(rootViewController: centerViewController)
view.addSubview(centerNavigationController.view)
addChild(centerNavigationController)
centerNavigationController.didMove(toParent: self)
let panGestureRecognizer = UIPanGestureRecognizer(target: self, action: #selector(handlePanGesture(_:)))
centerNavigationController.view.addGestureRecognizer(panGestureRecognizer)
}
}
private extension UIStoryboard {
static func mainStoryboard() -> UIStoryboard { return UIStoryboard(name: "Main", bundle: Bundle.main) }
static func leftViewController() -> SidePanelViewController? {
return mainStoryboard().instantiateViewController(withIdentifier: "LeftViewController") as? SidePanelViewController
}
static func rightViewController() -> SidePanelViewController? {
return mainStoryboard().instantiateViewController(withIdentifier: "RightViewController") as? SidePanelViewController
}
static func centerViewController() -> CenterViewController? {
return mainStoryboard().instantiateViewController(withIdentifier: "CenterViewController") as? CenterViewController
}
}
// MARK: CenterViewController delegate
extension ContainerViewController: CenterViewControllerDelegate {
func toggleLeftPanel() {
let notAlreadyExpanded = (currentState != .leftPanelExpanded)
if notAlreadyExpanded {
addLeftPanelViewController()
}
animateLeftPanel(shouldExpand: notAlreadyExpanded)
}
func addLeftPanelViewController() {
guard leftViewController == nil else { return }
if let vc = UIStoryboard.leftViewController() {
vc.animals = Animal.allCats()
addChildSidePanelController(vc)
leftViewController = vc
}
}
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
}
}
}
func toggleRightPanel() {
let notAlreadyExpanded = (currentState != .rightPanelExpanded)
if notAlreadyExpanded {
addRightPanelViewController()
}
animateRightPanel(shouldExpand: notAlreadyExpanded)
}
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
}
}
}
func collapseSidePanels() {
switch currentState {
case .rightPanelExpanded:
toggleRightPanel()
case .leftPanelExpanded:
toggleLeftPanel()
default:
break
}
}
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)
}
func addChildSidePanelController(_ sidePanelController: SidePanelViewController) {
sidePanelController.delegate = centerViewController
view.insertSubview(sidePanelController.view, at: 0)
addChild(sidePanelController)
sidePanelController.didMove(toParent: self)
}
func showShadowForCenterViewController(_ shouldShowShadow: Bool) {
if shouldShowShadow {
centerNavigationController.view.layer.shadowOpacity = 0.8
} else {
centerNavigationController.view.layer.shadowOpacity = 0.0
}
}
}
// MARK: Gesture recognizer
extension ContainerViewController: UIGestureRecognizerDelegate {
@objc func handlePanGesture(_ recognizer: UIPanGestureRecognizer) {
let gestureIsDraggingFromLeftToRight = (recognizer.velocity(in: view).x > 0)
switch recognizer.state {
case .began:
if currentState == .bothCollapsed {
if gestureIsDraggingFromLeftToRight {
addLeftPanelViewController()
} else {
addRightPanelViewController()
}
showShadowForCenterViewController(true)
}
case .changed:
if let rview = recognizer.view {
rview.center.x = rview.center.x + recognizer.translation(in: view).x
recognizer.setTranslation(CGPoint.zero, in: view)
}
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
}
}
}
5. Animal.swift
import UIKit
struct Animal {
let title: String
let creator: String
let image: UIImage?
init(title: String, creator: String, image: UIImage?) {
self.title = title
self.creator = creator
self.image = image
}
static func allCats() -> [Animal] {
return [
Animal(title: "Sleeping Cat", creator: "papaija2008", image: UIImage(named: "ID-100113060.jpg")),
Animal(title: "Pussy Cat", creator: "Carlos Porto", image: UIImage(named: "ID-10022760.jpg")),
Animal(title: "Korat Domestic Cat", creator: "sippakorn", image: UIImage(named: "ID-10091065.jpg")),
Animal(title: "Tabby Cat", creator: "dan", image: UIImage(named: "ID-10047796.jpg")),
Animal(title: "Yawning Cat", creator: "dan", image: UIImage(named: "ID-10092572.jpg")),
Animal(title: "Tabby Cat", creator: "dan", image: UIImage(named: "ID-10041194.jpg")),
Animal(title: "Cat On The Rocks", creator: "Willem Siers", image: UIImage(named: "ID-10017782.jpg")),
Animal(title: "Brown Cat Standing", creator: "aopsan", image: UIImage(named: "ID-10091745.jpg")),
Animal(title: "Burmese Cat", creator: "Rosemary Ratcliff", image: UIImage(named: "ID-10056941.jpg")),
Animal(title: "Cat", creator: "dan", image: UIImage(named: "ID-10019208.jpg")),
Animal(title: "Cat", creator: "graur codrin", image: UIImage(named: "ID-10011404.jpg"))
]
}
static func allDogs() -> [Animal] {
return [
Animal(title: "White Dog Portrait", creator: "photostock", image: UIImage(named: "ID-10034505.jpg")),
Animal(title: "Black Labrador Retriever", creator: "Michal Marcol", image: UIImage(named: "ID-1009881.jpg")),
Animal(title: "Anxious Dog", creator: "James Barker", image: UIImage(named: "ID-100120.jpg")),
Animal(title: "Husky Dog", creator: "James Barker", image: UIImage(named: "ID-100136.jpg")),
Animal(title: "Puppy", creator: "James Barker", image: UIImage(named: "ID-100140.jpg")),
Animal(title: "Black Labrador Puppy", creator: "James Barker", image: UIImage(named: "ID-10018395.jpg")),
Animal(title: "Yellow Labrador", creator: "m_bartosch", image: UIImage(named: "ID-10016005.jpg")),
Animal(title: "Black Labrador", creator: "Felixco, Inc.", image: UIImage(named: "ID-10012923.jpg")),
Animal(title: "Sleepy Dog", creator: "Maggie Smith", image: UIImage(named: "ID-10021769.jpg")),
Animal(title: "English Springer Spaniel Puppy", creator: "Tina Phillips", image: UIImage(named: "ID-10056667.jpg")),
Animal(title: "Intelligent Dog", creator: "James Barker", image: UIImage(named: "ID-100137.jpg"))
]
}
}
6. AnimalCell.swift
import UIKit
class AnimalCell: UITableViewCell {
@IBOutlet weak var animalImageView: UIImageView!
@IBOutlet weak var imageNameLabel: UILabel!
@IBOutlet weak var imageCreatorLabel: UILabel!
func configureForAnimal(_ animal: Animal) {
animalImageView.image = animal.image
imageNameLabel.text = animal.title
imageCreatorLabel.text = animal.creator
}
}
后記
本篇主要講述了如何創(chuàng)建自己的側(cè)滑式面板導(dǎo)航,感興趣的給個贊或者關(guān)注~~~