自定义 PageControl 图像 - Swift

Posted

技术标签:

【中文标题】自定义 PageControl 图像 - Swift【英文标题】:Custom PageControl image - Swift 【发布时间】:2017-11-14 06:36:20 【问题描述】:

我正在尝试为 UIPageControl 点设置图像。

我需要更改默认点,而不是我需要图像。 我使用了下面的代码

self.pageCtrl.currentPageIndicatorTintColor = UIColor.init(patternImage: UIImage(named: "Page Indicator_Selected")!)
self.pageCtrl.pageIndicatorTintColor = UIColor.init(patternImage: UIImage(named: "Page Indicator_Normal")!)

我可以在 Pagecontrol 中设置图像,但是它与默认点重叠。

【问题讨论】:

Custom UIPageControl with dot images的可能重复 【参考方案1】:

Politta 建议的代码不适用于 ios 14,因为 Apple 已经为 UIPageControll 引入了一些新的 API。

详情请看这里UIPageControls New APIs

这是支持 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
    


【讨论】:

这个工作但颜色效果不能正常工作 尝试使用具有透明背景的图像并获得正确的 RGB 或十六进制。这可能会有所帮助。 我试过了,它在第一次加载和滚动后会给出不同的颜色。 您的布局似乎没有正确更新。尝试使用 layoutIfNeeded() 或延迟。 它的更新问题是它第一次显示相反的色调【参考方案2】:

我改进了史密斯特工的答案,可以处理任意数量的页面。您可以自定义 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
    


【讨论】:

这个不适用于iOS14,子视图数总是1【参考方案3】:

这种方法对我有用。我创建了一个自定义 pageControl 类并将点的图像更改为任何自定义图像。

在下面的代码中,我使用任何自定义图像更改了 pageControl 中第一个点的图像。

您可以根据需要更改 updateDots() 方法。

希望对你有帮助!!!

override func viewDidLoad() 
    super.viewDidLoad()

    let pageControl = CustomPageControl(frame: CGRect(x: 100, y: 100, width: 104, height: 40))
    pageControl.numberOfPages = 5
    pageControl.currentPage = 0
    self.view.addSubview(pageControl)



class CustomPageControl: UIPageControl 


var imageToBeReplacedByDot: UIImage 
    return // Image you want to replace with dots

var circleImage: UIImage 

    return //Default Image



override var numberOfPages: Int 
    didSet 
        updateDots()
    


override var currentPage: Int 
    didSet 
        updateDots()
    


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 
        var imageView = self.imageView(forSubview: view)
        if imageView == nil 
            if i == 0 
                imageView = UIImageView(image: imageToBeReplacedByDot)
             else 
                imageView = UIImageView(image: circleImage)
            
            imageView!.center = view.center
            view.addSubview(imageView!)
            view.clipsToBounds = false
        
        if i == self.currentPage 
            imageView!.alpha = 1.0
         else 
            imageView!.alpha = 0.5
        
        i += 1
    


fileprivate func imageView(forSubview 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


【讨论】:

【参考方案4】:

支持 iOS 14,我们的 PageControl 子类,我们可以这样做:

    override var numberOfPages: Int 
        didSet 
            self._updateIndicators()
        
    
    
    override var currentPage: Int 
        didSet 
            self._updateIndicators()
        
    

    private func _updateIndicators() 
        var indicators: [UIView] = []
        
        if #available(iOS 14.0, *) 
            indicators = self.subviews.first?.subviews.first?.subviews ?? []
         else 
            indicators = self.subviews
        
        
        for (index, indicator) in indicators.enumerated() 
            let image = self.currentPage == index ? UIImage.init(named: "Page Indicator_Normal") : UIImage.init(named: "Page Indicator_Selected")
            if let dot = indicator as? UIImageView 
                dot.image = image
                
             else 
                let imageView = UIImageView.init(image: image)
                indicator.addSubview(imageView)
                // here you can add some constraints to fix the imageview to his superview
            
        
    

【讨论】:

以上是关于自定义 PageControl 图像 - Swift的主要内容,如果未能解决你的问题,请参考以下文章

带有 PageControl 的 ScrollView 中的图像

delphi中如何让pagecontrol的tab宽度自适应

启动时可关闭的 PageControl

缩放后 UIImageView 在 PageControl 的右侧被切断

PageControl 将标记放置在我想要的位置 ios 9

DataGridView实现简单分页功能