Reputation: 349
I've implemented a UIPageControl
as a outlet in my code. Now I want to have the capability where I can navigate to a specific view controller by tapping a dot in the UIPageControl.
To achieve this I've added an IBAction to the UIPageControl
and in the implementation I'm taking the currentPage
to load that specific view controller
-(IBAction)pageControlDotDidTap:(id)sender {
if (![sender isKindOfClass:[UIPageControl class]]) {
return;
}
NSInteger selectedPage = [(UIPageControl *)sender currentPage];
// got the currentPage now I can load the view controller
}
But the problem is by default UIPageControl moves 1 page at a time. Link: https://developer.apple.com/documentation/uikit/uipagecontrol#:~:text=The%20page%20control%20advances%20only%20one%20page%20in%20either%20direction.
So when I'm on the rightmost dot, If I clicked on the leftmost dot it only navigate to the second rightmost dot.
Is it possible to achieve that, the dot I'm clicking the UIPageControl
will return that dot number instead of moving one a time?
Upvotes: 0
Views: 274
Reputation: 349
Yes. After some more searching I've got that there is no API available to achieve this by using UIPageControl directly. Thanks to @DonMag for mentioning the should be approach.
Thus I've implemented a Custom Class to have the functionality to load the specific tapped view controller by tapping any indicator in UIPageControl
Here is my implementation -
import UIKit
protocol CustomPageControlDelegate: AnyObject {
func customPageControl(_ pageControl: UIPageControl, didTapIndicatorAtIndex index: Int)
}
class CustomPageControl: UIPageControl {
weak var delegate: CustomPageControlDelegate?
override init(frame: CGRect) {
super.init(frame: frame)
setupTapGesture()
}
required init?(coder: NSCoder) {
super.init(coder: coder)
setupTapGesture()
}
private func setupTapGesture() {
let tapGesture = UITapGestureRecognizer(target: self, action: #selector(handleTap(_:)))
addGestureRecognizer(tapGesture)
}
@objc private func handleTap(_ gesture: UITapGestureRecognizer) {
let tapPoint = gesture.location(in: self)
if let tappedIndicatorIndex = indicatorIndex(for: tapPoint) {
currentPage = tappedIndicatorIndex
delegate?.customPageControl(self, didTapIndicatorAtIndex: tappedIndicatorIndex)
}
}
private func indicatorIndex(for tapPoint: CGPoint) -> Int? {
let indicatorSize: CGFloat = 7.0 // Adjust this value according to your indicator size
let spacing: CGFloat = 10.0 // Adjust this value according to your spacing between indicators
let totalWidth = CGFloat(numberOfPages) * indicatorSize + CGFloat(numberOfPages - 1) * spacing
let startX = (bounds.size.width - totalWidth) / 2.0
if tapPoint.x >= startX && tapPoint.x < startX + totalWidth {
let relativeX = tapPoint.x - startX
let indicatorIndex = Int(relativeX / (indicatorSize + spacing))
return indicatorIndex
}
return nil
}
}
After that in the view controller I've used the delegate function to load the tapped indicator's view controller -
func customPageControl(_ pageControl: UIPageControl, didTapIndicatorAtIndex index: Int) {
print("Tapped indicator at index: \(index)")
// Handle the tap event and update your view accordingly
// Example: Scroll to the corresponding page in a UIScrollView
}
Upvotes: 0