3.iOS14下UIPageControl自定义样式
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
}

【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· C#/.NET/.NET Core优秀项目和框架2025年2月简报
· 葡萄城 AI 搜索升级:DeepSeek 加持,客户体验更智能
· 什么是nginx的强缓存和协商缓存
· 一文读懂知识蒸馏