Reputation: 255
I'm trying to change the dots in a page control with some images.
Here is the code I have tried:
import UIKit
class PageViewController: UIPageViewController, UIPageViewControllerDelegate, UIPageViewControllerDataSource {
// MARK: Data source functions.
func pageViewController(_ pageViewController: UIPageViewController, viewControllerBefore viewController: UIViewController) -> UIViewController? {
guard let viewControllerIndex = orderedViewControllers.index(of: viewController) else {
return nil
}
let previousIndex = viewControllerIndex - 1
guard previousIndex >= 0 else {
return orderedViewControllers.last
// Uncommment the line below, remove the line above if you don't want the page control to loop.
// return nil
}
guard orderedViewControllers.count > previousIndex else {
return nil
}
return orderedViewControllers[previousIndex]
}
func pageViewController(_ pageViewController: UIPageViewController, viewControllerAfter viewController: UIViewController) -> UIViewController? {
guard let viewControllerIndex = orderedViewControllers.index(of: viewController) else {
return nil
}
let nextIndex = viewControllerIndex + 1
let orderedViewControllersCount = orderedViewControllers.count
// the first view controller.
guard orderedViewControllersCount != nextIndex else {
return orderedViewControllers.first
// Uncommment the line below, remove the line above if you don't want the page control to loop.
// return nil
}
guard orderedViewControllersCount > nextIndex else {
return nil
}
return orderedViewControllers[nextIndex]
}
lazy var orderedViewControllers: [UIViewController] = {
return [self.newVc(viewController: "sbYellow"),
self.newVc(viewController: "sbRed"),
self.newVc(viewController: "sbBlue")]
}()
var pageControl = UIPageControl()
override func viewDidLoad() {
super.viewDidLoad()
self.dataSource = self
// This sets up the first view that will show up on our page control
if let firstViewController = orderedViewControllers.first {
setViewControllers([firstViewController],
direction: .forward,
animated: true,
completion: nil)
}
let pageControl = CustomPageControl(frame: CGRect(x: 100, y: 100, width: 104, height: 40))
pageControl.numberOfPages = 3
pageControl.currentPage = 0
self.view.addSubview(pageControl)
/*self.delegate = self
configurePageControl()*/
}
func configurePageControl() {
// The total number of pages that are available is based on how many available colors we have.
pageControl = UIPageControl(frame: CGRect(x: 0,y: UIScreen.main.bounds.maxY - 50,width: UIScreen.main.bounds.width,height: 50))
self.pageControl.numberOfPages = orderedViewControllers.count
self.pageControl.currentPage = 0
self.pageControl.tintColor = UIColor.black
self.pageControl.pageIndicatorTintColor = UIColor.white
self.pageControl.currentPageIndicatorTintColor = UIColor.black
self.view.addSubview(pageControl)
}
func newVc(viewController: String) -> UIViewController {
return UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier: viewController)
}
func pageViewController(_ pageViewController: UIPageViewController, didFinishAnimating finished: Bool, previousViewControllers: [UIViewController], transitionCompleted completed: Bool) {
let pageContentViewController = pageViewController.viewControllers![0]
self.pageControl.currentPage = orderedViewControllers.index(of: pageContentViewController)!
}
}
class CustomPageControl: UIPageControl {
var imageToBeReplacedByDot: UIImage {
return imageLiteral(resourceName: "av_timer - material") // Image you want to replace with dots
}
var circleImage: UIImage {
return imageLiteral(resourceName: "cancel - material") //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
}
}
Which is working fine and changing the dots with images. The issue is that the image will not change if i scroll. Also, I want to position the page control on center top of the screen.
How to achieve that?
Screenshot:
Upvotes: 0
Views: 6834
Reputation: 1
import UIKit
class ViewController: UIViewController {
@IBOutlet weak var pageControl: UIPageControl! // Make IBOutlet of page Control
var indexNo = 0 // initialised Starting index number
var timer = Timer() // here i used timer for change pages
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
timer = Timer.scheduledTimer(timeInterval: 2, target: self,selector: #selector(setimage), userInfo: nil, repeats: true)
}
@objc func setimage(){
pageControl.numberOfPages = 3 // declare number of pages
pageControl.page = indexNo // assign value for current page
pageControl.currentPage = indexNo // for current indicator color
indexNo += 1
if indexNo == 3 {
indexNo = 0
timer.invalidate() // after end of the pages you can modified also
}
}
}
//Mark :- make extension of UIPageControl
extension UIPageControl {
var page: Int {
get {
currentPage
}
set {
//currentPage = newValue
print(newValue)
setIndicatorImage(UIImage(named: "Rectangle 2"), forPage: newValue)
for in 0..<numberOfPages where index != newValue {
print(index)
setIndicatorImage(UIImage(named: "Ellipse 4"), forPage: index)
}
}
}
}
Upvotes: -1
Reputation: 109
With the help of AI I got that subclass and it works well for me
import UIKit
class CustomPageControl: UIControl {
private var dotImageViews: [UIImageView] = []
private let spacing: CGFloat = 8
var currentPage: Int = 0 {
didSet {
updateDots()
}
}
var numberOfPages: Int = 0 {
didSet {
updateDotImageViews()
updateDots()
}
}
var dotImage: UIImage? {
didSet {
updateDots()
}
}
var currentDotImage: UIImage? {
didSet {
updateDots()
}
}
private var dotSize: CGSize {
return dotImage?.size ?? CGSize(width: 10, height: 10)
}
override var intrinsicContentSize: CGSize {
let width = CGFloat(numberOfPages) * dotSize.width + CGFloat(max(0, numberOfPages - 1)) * spacing
let height = dotSize.height
return CGSize(width: width, height: height)
}
override func layoutSubviews() {
super.layoutSubviews()
updateDotImageViews()
updateDots()
setViewInCenter()
}
private func setViewInCenter() {
let totalWidth = CGFloat(dotImageViews.count) * dotSize.width + CGFloat(max(0, dotImageViews.count - 1)) * spacing
let startX = (bounds.width - totalWidth) / 2
var x = startX
for dotImageView in dotImageViews {
dotImageView.frame = CGRect(x: x, y: (bounds.height - dotSize.height) / 2, width: dotSize.width, height: dotSize.height)
x += dotSize.width + spacing
}
}
private func updateDotImageViews() {
// Remove existing dot image views
dotImageViews.forEach { $0.removeFromSuperview() }
dotImageViews.removeAll()
// Create and add new dot image views
for _ in 0..<numberOfPages {
let dotImageView = UIImageView()
dotImageView.contentMode = .center
addSubview(dotImageView)
dotImageViews.append(dotImageView)
}
}
private func updateDots() {
for (index, dotImageView) in dotImageViews.enumerated() {
dotImageView.image = index == currentPage ? currentDotImage : dotImage
}
}
}
Create an outlet for the CustomPageControl in your view controller:
@IBOutlet weak var customPageControl: CustomPageControl!
In your view controller's code, set the properties of the customPageControl instance to customize its appearance:
customPageControl.dotImage = UIImage(named: "dot_image")
customPageControl.currentDotImage = UIImage(named: "current_dot_image")
customPageControl.numberOfPages = 5
customPageControl.currentPage = 2
Replace "dot_image" and "current_dot_image" with the actual names of your dot images.
Upvotes: -1
Reputation: 1822
You can use this code for Reference:
import UIKit
class LocationPageControl: UIPageControl {
let locationArrow: UIImage = UIImage(named: "locationArrow")!
let pageCircle: UIImage = UIImage(named: "pageCircle")!
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: locationArrow)
} else {
imageView = UIImageView(image: pageCircle)
}
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
}
}
Note:- Set your image according as per your need
Upvotes: 0