3.iOS14下UIPageControl自定義樣式
1.概覽
首先在iOS14中UIPageControl
中增加了幾個新屬性及方法:
/// 表示當前的背景樣式,枚舉值
open var backgroundStyle: UIPageControl.BackgroundStyle
/// 只讀屬性,表示當前處於離散互動還是連續互動
open var interactionState: UIPageControl.InteractionState { get }
/// 表示是否開始連續互動,默認true
open var allowsContinuousInteraction: Bool
/// 指示器樣式統一調整,默認nil,樣式為圓點
open var preferredIndicatorImage: UIImage?
/// 獲取page處對應的圖片,沒有設置則為nil
open func indicatorImage(forPage page: Int) -> UIImage?
/// 設置page處對應的圖片
open func setIndicatorImage(_ image: UIImage?, forPage page: Int)
同時廢棄了一個方法和屬性:
/// 設置該屬性后,延緩更新指示器,直到調用updateCurrentPageDisplay為止
open var defersCurrentPageDisplay: Bool
/// 更新指示器
open func updateCurrentPageDisplay()
2.部分新增屬性及方法
2.1 preferredIndicatorImage
let control = UIPageControl()
control.numberOfPages = 10
control.frame = CGRect(x: 0, y: 300, width: 350, height: 30)
control.pageIndicatorTintColor = .systemRed
control.currentPageIndicatorTintColor = .systemGreen
if #available(iOS 14.0, *) {
control.preferredIndicatorImage = UIImage(named:"heart")
}
self.view.addSubview(control)
preferredIndicatorImage
可以將指示器圖片替換成任意我們想要的圖片
2.2 setIndicatorImage(UIImage?, forPage: Int)
可以設置任意page對應的圖片,如果image為nil的話則顯示圓點
let indicatorImages = ["summy", "cloudy", "rainy", "thunder"]
if #available(iOS 14.0, *) {
for (idx, imageName) in indicatorImages.enumerated() {
control.setIndicatorImage(UIImage(named:imageName), forPage: idx)
}
}
2.3 自定義樣式
通過iOS14中新增的幾個屬性,只能實現簡單的自定義樣式,想要實現完全的自定義仍舊需要采用之前的辦法,在這之前先看一下UIPageControl
在iOS14中層級的變化


圓點有原先UIView
一個視圖變成了由_UIPageControlContentView
、_UIPageControlIndicatorContentView
、_UIPageIndicatorView
組合的視圖,由於_UIPageIndicatorView
是一個UIImageView
,所以我們可以直接使用這個視圖來呈現
if #available(iOS 14.0, *) {
guard let dotContentView = findIndicatorContentView() else {
return
}
for (index, view) in dotContentView.subviews.enumerated() {
if view.isKind(of: UIImageView.self) {
self.currentPageIndicatorTintColor = self.currentTintColor
self.pageIndicatorTintColor = self.inactiveTintColor
let indicatorView = view as! UIImageView
indicatorView.image = nil
if index == self.currentPage {
indicatorView.image = currentImage.withRenderingMode(.alwaysTemplate)
} else {
indicatorView.image = inactiveImage.withRenderingMode(.alwaysTemplate)
}
}
}
}
@available(iOS 14.0, *)
func findIndicatorContentView() -> UIView? {
for contentView in self.subviews {
if let contentViewClass = NSClassFromString("_UIPageControlContentView"), contentView.isKind(of: contentViewClass) {
for indicatorContentView in contentView.subviews {
if let indicatorContentViewClass = NSClassFromString("_UIPageControlIndicatorContentView"), indicatorContentView.isKind(of: indicatorContentViewClass) {
return indicatorContentView
}
}
}
}
return nil
}
