Custom UIPageControl with dot images

前端 未结 4 1482
不知归路
不知归路 2020-12-15 13:59

When I needed to custom my UIPageControl I used this and this solution.

Slightly modifying it for the new version of swift we have :

class myPageCont         


        
相关标签:
4条回答
  • 2020-12-15 14:29

    I improved @CodenameDuchess's answer a bit. You can also customize the images on 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
        }
    }
    }
    
    0 讨论(0)
  • 2020-12-15 14:49

    Swift 3.0 ... you know if you are OK with accepting stated risk: "Modifying the subviews of an existing control is fragile".

    You will have to call "updateDots()" in viewDidAppear() and your valueChanged handler for the page control.

     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
         }
     }
    
    0 讨论(0)
  • 2020-12-15 14:49

    You can use UIStackView to achieve the effect you want.

    Put your activeImageView and other inactiveImageViews into aStackView. Than just change the index of activeImageView in scrollViewDidScroll(_:).

    func scrollViewDidScroll(_ scrollView: UIScrollView) {
      let index = Int(scrollView.contentOffset.x / scrollView.frame.width)
      aStackView.insertArrangedSubview(activeImageView, at: index)
    }  
    

    ps. UIStackView's insertArrangedSubview(_:at:) just updates the stack index of the arranged subview if it's already in the arrangedSubviews list.

    0 讨论(0)
  • 2020-12-15 14:51

    Apple had introduced some new APIs for UIPageControll. From iOS 14 there is an option for providing a custom image.

    Here is the updated code supporting 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
        }
    }
    }
    
    0 讨论(0)
提交回复
热议问题