基于之前的文章做了點更新 2022年02月21:
開發語言:Swift。
開發支持最低系統:iOS10.0。
項目需求:iPad支持全方向展示,iPhone限制豎屏模式(當然也可以放開支持)。
近階段項目需要適配iPad,需要考慮橫豎屏UI適配問題,總結一下我的做法:
項目配置
在General底下同時勾選iPhone,iPad,我們計劃通過代碼層面來控制頁面的方向,所以Device Orientation選項勾選就不重要了:
image.png
具體實現
- 在AppDelete中實現旋轉所支持的方向,為.all:
func application(_ application: UIApplication, supportedInterfaceOrientationsFor window: UIWindow?) -> UIInterfaceOrientationMask {
return .all
}
- 定義全局屬性:
- screenWidth, screenHeight變量:在屏幕旋轉方法中進行重新賦值操作,以確保其始終和UIScreen.main.bounds相等,也就是當前方向屏幕的寬高;
- isIPad屬性:userInterfaceIdiom有很多,我們認定除了pad,按照phone處理,所以我定義了isIPad而不是isIPhone;
- screenWidthScale:UI適配的比例先算好,用于視圖布局,字體大小的計算;因為UIScreen.main.bounds是固定的,所以這個比例是不會變的,我基于的iPad屏寬是768pt,其他的是375pt;
- 給需要的基本類型做func fit()的擴展,在視圖布局的時候調用.fit()方法;
var screenWidth = UIScreen.main.bounds.width
var screenHeight = UIScreen.main.bounds.height
let isIPad = UIDevice.current.userInterfaceIdiom == .pad
let screenWidthScale = min(UIScreen.main.bounds.width, UIScreen.main.bounds.height) / (isIPad ? 768 : 375)
extension Int {
func fit() -> CGFloat {
screenWidthScale * CGFloat(self)
}
}
舉例調用.fit()的代碼片段:
override func layoutSubviews() {
super.layoutSubviews()
let maxY_nav = WindowManager.share.safeAreaInsets.top + navH
let h_bg = maxY_nav + 160.fit()
bgImgV.frame = .init(x: 0, y: 0, width: bounds.width, height: h_bg)
}
- 在控制器中實現以下代碼:
- 這里建議只需在基類(BaseViewController)中實現一遍就好了;
- 如果在非iPad情況下涉及到橫屏展示的控制器,比如:手繪簽名,圖表展示,視頻播放等,那么需要在該控制器中再次重寫以下代碼以支持各方向展示;
- 如果自定義了NavBarController或TabBarController,那么也需要在類中重寫以下屬性,否則涉及到導航跳轉或tabBar菜單切換都會有橫豎UI層面問題;
/// 是否支持旋轉
override var shouldAutorotate: Bool {
isIPad
}
/// 支持頁面旋轉的類型:上下左右
override var supportedInterfaceOrientations: UIInterfaceOrientationMask {
isIPad ? .all : .portrait
}
override var preferredInterfaceOrientationForPresentation: UIInterfaceOrientation {
.portrait
}
- 旋轉后的布局處理:
- 就是對screenWidth和screenHeight一個重新賦值;
- 同樣建議在基類中實現,只需要寫一遍;
- 自定義的NavBarController或TabBarController無需實現;
override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) {
super.viewWillTransition(to: size, with: coordinator)
if isIPad {
screenWidth = size.width
screenHeight = size.height
}
}