首發於公眾號
微信在 iPad 上豎屏時顯示的樣式和手機版一樣,橫屏的顯示為分隔檢視。
UIKit 裡可以實現這樣的效果的元件是UISplitViewController
。
接下來就是要自定義一個 UISplitViewController 來逐步實現像微信一樣的效果。
豎屏時只顯示 Master 檢視
豎屏時 master 檢視需要佔滿全屏,橫屏的時候則 master 和 detail 都需要顯示,可以更好的利用 iPad 大螢幕的優勢。
豎屏模式下,設定 master 的寬度為全屏大小:
private func toPortraitWidth() {
maximumPrimaryColumnWidth = maxMasterWidth
preferredPrimaryColumnWidthFraction = 1
}
複製程式碼
橫屏時恢復為預設寬度
private func toLandscapeWidth() {
maximumPrimaryColumnWidth = UISplitViewController.automaticDimension
preferredPrimaryColumnWidthFraction = UISplitViewController.automaticDimension
}
複製程式碼
處理子檢視的顯示
豎屏模式下,所有子檢視的顯示都由 master 來處理,
橫屏模式下,子檢視的顯示都放到 detail 檢視中,
需要實現下面這個代理方法,自己來控制頁面的顯示。
public func splitViewController(_ splitViewController: UISplitViewController, showDetail vc: UIViewController, sender: Any?) -> Bool {
if isPortrait {
masterViewController?.show(vc, sender: nil)
} else {
detailViewController?.viewControllers = [vc]
}
return true
}
複製程式碼
處理橫豎屏切換
豎屏時,所有的頁面都顯示在 master 檢視中,
橫屏時,所有的子頁面都顯示在 detail 檢視中,
思路比較簡單,在 viewWillTransition
方法裡直接操作 viewControllers
屬性來達到移動子頁面的目的。
public override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) {
super.viewWillTransition(to: size, with: coordinator)
var subVCs: [UIViewController] = masterViewController!.viewControllers
// after transition, it will be portrait mode
if !isPortrait {
var flag: Bool = false
if let topVC = detailViewController?.topViewController, !topVC.isKind(of: placeholderViewControllerClass) {
subVCs.append(contentsOf: detailViewController!.viewControllers)
flag = true
}
if flag {
let placeholderViewController = (placeholderViewControllerClass as? UIViewController.Type)?.init() ?? UIViewController()
detailViewController?.viewControllers = [placeholderViewController]
masterViewController?.viewControllers = subVCs
}
toPortraitWidth()
} else {
if subVCs.count > 1 {
subVCs.remove(at: 0)
masterViewController!.popToRootViewController(animated: false)
detailViewController?.viewControllers = subVCs
}
toLandscapeWidth()
}
}
複製程式碼
SFSplitViewController
根據以上思路封裝了一個 SFSplitViewController
元件來實現像微信一樣的佈局功能。
使用起來也很簡單,把 SFSplitViewController
作為 RootController 就可以了,要求 master 和 detail 的容器必須是 UINavigationController
型別。
使用方法如下:
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
let rootVC = SFSplitViewController(master: UINavigationController(rootViewController: MainViewController()),
detail: UINavigationController(rootViewController: PlaceholderViewController()))
rootVC.placeholderViewControllerClass = PlaceholderViewController.self
window = UIWindow(frame: UIScreen.main.bounds)
window?.rootViewController = rootVC
window?.makeKeyAndVisible()
return true
}
複製程式碼
完整的程式碼請參考我的 github: SFSplitViewController