【问题标题】:Custom UIPageControl with dot images带有点图像的自定义 UIPageControl
【发布时间】:2016-08-10 09:20:07
【问题描述】:

当我需要自定义 UIPageControl 时,我使用了 thisthis 解决方案。

为我们拥有的新版本的 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(),但是没有结果。我可能做错了什么?

【问题讨论】:

    标签: ios swift uipagecontrol


    【解决方案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 变量 --> stackoverflow.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 和其他inactiveImageViews 放入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。
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-04-21
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多