带有点图像的自定义 UIPageControl
Posted
技术标签:
【中文标题】带有点图像的自定义 UIPageControl【英文标题】:Custom UIPageControl with dot images 【发布时间】:2016-08-10 09:20:07 【问题描述】:当我需要自定义 UIPageControl 时,我使用了 this 和 this 解决方案。
为我们拥有的新版本的 swift 稍微修改一下:
class myPageControl: UIPageControl
var activeImage: UIImage!
var inactiveImage: UIImage!
required init?(coder aDecoder: NSCoder)
super.init(coder: aDecoder)
activeImage = UIImage(named: "active.png")!
inactiveImage = UIImage(named: "inactive.png")!
func updateDots()
for i in 0 ..< self.subviews.count
let dot : UIImageView = imageViewForSubview(self.subviews[i])
if (i == self.currentPage)
dot.image = activeImage
else
dot.image = inactiveImage
func imageViewForSubview(view: UIView) -> UIImageView
var dot: UIImageView? = nil
if (view.isKindOfClass(UIView))
for subview: UIView in view.subviews
if (subview is UIImageView)
dot = (subview as! UIImageView)
if dot == nil
dot = UIImageView(frame: CGRectMake(0.0, 0.0, view.frame.size.width, view.frame.size.height))
view.addSubview(dot!)
else
dot = (view as! UIImageView)
return dot!
func setPage(page: Int)
super.currentPage = page
self.updateDots()
我的问题是当你第一次启动应用程序时我无法更改图片。 只有当页面改变时才会改变。
在viewDidLoad()
中,我添加了setPage(0)
和updateDots()
,但是没有结果。我可能做错了什么?
【问题讨论】:
【参考方案1】:Swift 3.0 ...您知道您是否可以接受声明的风险:“修改现有控件的子视图很脆弱”。
您必须在 viewDidAppear() 和页面控件的 valueChanged 处理程序中调用“updateDots()”。
import UIKit
class CustomImagePageControl: UIPageControl
let activeImage:UIImage = UIImage(named: "SelectedPage")!
let inactiveImage:UIImage = UIImage(named: "UnselectedPage")!
override func awakeFromNib()
super.awakeFromNib()
self.pageIndicatorTintColor = UIColor.clear
self.currentPageIndicatorTintColor = UIColor.clear
self.clipsToBounds = false
func updateDots()
var i = 0
for view in self.subviews
if let imageView = self.imageForSubview(view)
if i == self.currentPage
imageView.image = self.activeImage
else
imageView.image = self.inactiveImage
i = i + 1
else
var dotImage = self.inactiveImage
if i == self.currentPage
dotImage = self.activeImage
view.clipsToBounds = false
view.addSubview(UIImageView(image:dotImage))
i = i + 1
fileprivate func imageForSubview(_ view:UIView) -> UIImageView?
var dot:UIImageView?
if let dotImageView = view as? UIImageView
dot = dotImageView
else
for foundView in view.subviews
if let imageView = foundView as? UIImageView
dot = imageView
break
return dot
【讨论】:
这是调用“updateDots()”的更好主意。还没有尝试过,但 Dmitry 建议覆盖 numberOfPages 和 currentPage 变量 --> ***.com/questions/12190147/… 刚刚签入 ios 14,self.subviews 只获得一个子视图。有什么想法吗? iOS 14 有 prefferedIndicatorImage,使用它并设置 tintColor 此方案适用于活动图像和非活动图像不同的情况。否则,您可以使用“prefferedIndicatorImage”和色调颜色。 @Laurynas Letkauskas【参考方案2】:我稍微改进了@CodenameDuchess 的回答。您还可以自定义 xibs/storyboards 上的图像。
class CustomPageControl: UIPageControl
@IBInspectable var currentPageImage: UIImage?
@IBInspectable var otherPagesImage: UIImage?
override var numberOfPages: Int
didSet
updateDots()
override var currentPage: Int
didSet
updateDots()
override func awakeFromNib()
super.awakeFromNib()
pageIndicatorTintColor = .clear
currentPageIndicatorTintColor = .clear
clipsToBounds = false
private func updateDots()
for (index, subview) in subviews.enumerated()
let imageView: UIImageView
if let existingImageview = getImageView(forSubview: subview)
imageView = existingImageview
else
imageView = UIImageView(image: otherPagesImage)
imageView.center = subview.center
subview.addSubview(imageView)
subview.clipsToBounds = false
imageView.image = currentPage == index ? currentPageImage : otherPagesImage
private func getImageView(forSubview view: UIView) -> UIImageView?
if let imageView = view as? UIImageView
return imageView
else
let view = view.subviews.first (view) -> Bool in
return view is UIImageView
as? UIImageView
return view
【讨论】:
【参考方案3】:你可以使用UIStackView
来达到你想要的效果。
将您的activeImageView
和其他inactiveImageView
s 放入aStackView
。不仅仅是在scrollViewDidScroll(_:)
中更改activeImageView
的索引。
func scrollViewDidScroll(_ scrollView: UIScrollView)
let index = Int(scrollView.contentOffset.x / scrollView.frame.width)
aStackView.insertArrangedSubview(activeImageView, at: index)
ps。 UIStackView 的insertArrangedSubview(_:at:)
只是更新已排列子视图的堆栈索引,如果它已经在排列子视图列表中。
【讨论】:
【参考方案4】:Apple 为 UIPageControll 引入了一些新的 API。从 iOS 14 开始,可以选择提供自定义图像。
这是支持 iOS 14 的更新代码
class CustomPageControl: UIPageControl
@IBInspectable var currentPageImage: UIImage?
@IBInspectable var otherPagesImage: UIImage?
override var numberOfPages: Int
didSet
updateDots()
override var currentPage: Int
didSet
updateDots()
override func awakeFromNib()
super.awakeFromNib()
if #available(iOS 14.0, *)
defaultConfigurationForiOS14AndAbove()
else
pageIndicatorTintColor = .clear
currentPageIndicatorTintColor = .clear
clipsToBounds = false
private func defaultConfigurationForiOS14AndAbove()
if #available(iOS 14.0, *)
for index in 0..<numberOfPages
let image = index == currentPage ? currentPageImage : otherPagesImage
setIndicatorImage(image, forPage: index)
// give the same color as "otherPagesImage" color.
pageIndicatorTintColor = .gray
// give the same color as "currentPageImage" color.
currentPageIndicatorTintColor = .red
/*
Note: If Tint color set to default, Indicator image is not showing. So, give the same tint color based on your Custome Image.
*/
private func updateDots()
if #available(iOS 14.0, *)
defaultConfigurationForiOS14AndAbove()
else
for (index, subview) in subviews.enumerated()
let imageView: UIImageView
if let existingImageview = getImageView(forSubview: subview)
imageView = existingImageview
else
imageView = UIImageView(image: otherPagesImage)
imageView.center = subview.center
subview.addSubview(imageView)
subview.clipsToBounds = false
imageView.image = currentPage == index ? currentPageImage : otherPagesImage
private func getImageView(forSubview view: UIView) -> UIImageView?
if let imageView = view as? UIImageView
return imageView
else
let view = view.subviews.first (view) -> Bool in
return view is UIImageView
as? UIImageView
return view
【讨论】:
在 iOS 14 中你应该使用 prefferedIndicatorImage 代替 @Laurynas Letkauskas 当活动图像和非活动图像不同时,此解决方案将适用。否则,您可以使用“prefferedIndicatorImage”和 tint color。以上是关于带有点图像的自定义 UIPageControl的主要内容,如果未能解决你的问题,请参考以下文章
带有用于突出显示的图像的自定义 UITableViewCell