jsdw_ios/QuickLocation/UIKit/JJPageControl.swift

467 lines
16 KiB
Swift

//
// JJPageControl.swift
// JJPageControl
//
// https://github.com/zxhkit/JJPageControl
// Created by xuanhe on 2022/9/1.
//
import UIKit
enum JJPageControlAliment {
case Center
case Left
case Right
}
protocol JJPageControlDelegate {
func jj_pageControlClick(pageControl: JJPageControl, index: Int)
}
class JJPageControl: UIControl {
///
var clickPointClosure: ((_ num : Int) -> Void)?
///
var currentPointSize: CGSize = CGSize(width: 6, height: 6) {
didSet{
assert((currentPointSize.width >= 1 && currentPointSize.height >= 1), "Parameter value is not valid. currentPointSize must be greater than 1.")
if numberOfPages > 0 {
createPointView()
}
}
}
///
var otherPointSize: CGSize = CGSize(width: 6, height: 6) {
didSet{
assert((otherPointSize.width >= 1 && otherPointSize.height >= 1), "Parameter value is not valid. otherPointSize must be greater than 1.")
if numberOfPages > 0 {
createPointView()
}
}
}
/// -
var pointCornerRadius:CGFloat = 3 {
didSet{
if numberOfPages > 0 {
createPointView()
}
}
}
///
var pageAliment: JJPageControlAliment = .Center {
didSet{
if numberOfPages > 0 {
createPointView()
}
}
}
///
var numberOfPages: Int = 0 {
didSet{
if oldValue != numberOfPages {
createPointView()
}
}
}
///
var currentPage: Int = 0 {
didSet{
if currentPage >= 0 {
exchangePointView(oldValue, currentPage)
}else{
currentPage = 0
}
}
}
///
var controlSpacing: CGFloat = 8 {
didSet{
if numberOfPages > 0 {
createPointView()
}
}
}
///
var leftAndRightSpacing: CGFloat = 10 {
didSet{
if leftAndRightSpacing < 0 {
leftAndRightSpacing = 0
}else{
if numberOfPages > 0 {
createPointView()
}
}
}
}
///
var otherColor: UIColor = .gray {
didSet{
if numberOfPages > 0 {
createPointView()
}
}
}
///
var currentColor: UIColor = .orange {
didSet{
if numberOfPages > 0 {
createPointView()
}
}
}
///
var otherBkImage: UIImage? {
didSet{
if numberOfPages > 0 {
createPointView()
}
}
}
///
var currentBkImage: UIImage? {
didSet{
if numberOfPages > 0 {
createPointView()
}
}
}
///layer
var currentLayerBorderWidth: CGFloat = 1 {
didSet{
if numberOfPages > 0 {
createPointView()
}
}
}
///layer
var otherLayerBorderWidth: CGFloat = 1 {
didSet{
if numberOfPages > 0 {
createPointView()
}
}
}
///layer
var currentLayerBorderColor: UIColor? {
didSet{
if numberOfPages > 0 {
createPointView()
}
}
}
///layer
var otherLayerBorderColor: UIColor? {
didSet{
if numberOfPages > 0 {
createPointView()
}
}
}
///
var isHidesForSinglePage = true {
didSet{
if numberOfPages > 0 {
createPointView()
}
}
}
///
var isCanClickPoint = false {
didSet{
if numberOfPages > 0 {
createPointView()
}
}
}
/// frame
override var frame:CGRect {
didSet{
let mainWidth = (CGFloat(numberOfPages) - 1) * otherPointSize.width + (CGFloat(numberOfPages) - 1) * controlSpacing + currentPointSize.width + leftAndRightSpacing * 2
if frame.width < mainWidth {
frame.size.width = mainWidth
}
let max_height = max(otherPointSize.height, currentPointSize.height)
if frame.height < max_height {
frame.size.height = max_height
}
createPointView()
}
}
///
var delegate:JJPageControlDelegate?
private var dots = [UIImageView]()
///
private func createPointView() {
///
clearView()
if numberOfPages <= 0 {
return
}
if isHidesForSinglePage == true ,numberOfPages == 1{
return
}
//
var startX:CGFloat = 0
var startY_current:CGFloat = 0
var startY_other:CGFloat = 0
let mainWidth = (CGFloat(numberOfPages) - 1) * otherPointSize.width + (CGFloat(numberOfPages) - 1) * controlSpacing + currentPointSize.width + leftAndRightSpacing * 2 + 1
if frame.width < mainWidth {
frame.size.width = mainWidth
}else{
if pageAliment == .Left {
startX = leftAndRightSpacing
} else if pageAliment == .Center {
startX = (self.frame.size.width - mainWidth)/2.0
} else {
startX = frame.width - mainWidth
}
}
let max_height = max(otherPointSize.height, currentPointSize.height)
if frame.height < max_height {
frame.size.height = max_height
startY_current = max_height - currentPointSize.height
startY_other = max_height - otherPointSize.height
} else {
startY_current = (frame.height - max_height)/2.0 + (max_height - currentPointSize.height)
startY_other = (frame.height - max_height)/2.0 + (max_height - otherPointSize.height)
}
for page in 0..<numberOfPages {
if page == currentPage {
let currentPoint = UIImageView(frame: CGRect(x: startX, y: startY_current, width: currentPointSize.width, height: currentPointSize.height))
currentPoint.layer.masksToBounds = true
currentPoint.layer.cornerRadius = pointCornerRadius
currentPoint.tag = 1000 + page
currentPoint.backgroundColor = currentColor
currentPoint.isUserInteractionEnabled = true
currentPoint.image = currentBkImage
if self.currentLayerBorderColor != nil {
currentPoint.layer.borderColor = self.currentLayerBorderColor?.cgColor
currentPoint.layer.borderWidth = self.currentLayerBorderWidth
}else{
currentPoint.layer.borderWidth = 0
}
if isCanClickPoint == true {
let tapGesture = UITapGestureRecognizer(target: self, action: #selector(clickAction(_:)))
currentPoint.addGestureRecognizer(tapGesture)
}
addSubview(currentPoint)
startX = currentPoint.frame.maxX + controlSpacing
if let _ = currentBkImage {
currentPoint.backgroundColor = .clear
}
dots.append(currentPoint)
}else{
let otherPoint = UIImageView(frame: CGRect(x: startX, y: startY_other, width: otherPointSize.width, height: otherPointSize.height))
otherPoint.layer.masksToBounds = true
otherPoint.layer.cornerRadius = pointCornerRadius
otherPoint.tag = 1000 + page
otherPoint.backgroundColor = otherColor
otherPoint.isUserInteractionEnabled = true
otherPoint.image = otherBkImage
if self.otherLayerBorderColor != nil {
otherPoint.layer.borderColor = self.otherLayerBorderColor?.cgColor
otherPoint.layer.borderWidth = self.otherLayerBorderWidth
}else{
otherPoint.layer.borderWidth = 0
}
if isCanClickPoint == true {
let tapGesture = UITapGestureRecognizer(target: self, action: #selector(clickAction(_:)))
otherPoint.addGestureRecognizer(tapGesture)
}
addSubview(otherPoint)
startX = otherPoint.frame.maxX + controlSpacing
if let _ = otherBkImage {
otherPoint.backgroundColor = .clear
}
dots.append(otherPoint)
}
}
}
@objc private func clickAction(_ recognizer: UITapGestureRecognizer) {
if let tag = recognizer.view?.tag {
let index = tag - 1000
if index >= 0 {
currentPage = index
delegate?.jj_pageControlClick(pageControl: self, index: index)
if let closure = self.clickPointClosure {
closure(index)
}
}
}
}
func clearView() {
// subviews.forEach { subView in
// subView.removeFromSuperview()
// }
subviews.forEach { $0.removeFromSuperview()}
dots.removeAll()
}
func exchangePointView(_ oldPage: Int, _ newPage: Int) {
if oldPage == newPage {
return
}
if oldPage > dots.count {
return
}
if newPage > dots.count {
return
}
let oldDot = dots[oldPage]
let oldFrame = oldDot.frame
let newDot = dots[newPage]
let newFrame = newDot.frame
newDot.image = currentBkImage
if let _ = currentBkImage {
newDot.backgroundColor = .clear
}else{
newDot.backgroundColor = currentColor
}
oldDot.image = otherBkImage
if let _ = otherBkImage {
oldDot.backgroundColor = .clear
}else{
oldDot.backgroundColor = otherColor
}
if self.currentLayerBorderColor != nil {
newDot.layer.borderColor = self.currentLayerBorderColor?.cgColor
newDot.layer.borderWidth = self.currentLayerBorderWidth
}else{
newDot.layer.borderWidth = 0
}
if self.otherLayerBorderColor != nil {
oldDot.layer.borderColor = self.otherLayerBorderColor?.cgColor
oldDot.layer.borderWidth = self.otherLayerBorderWidth
}else{
oldDot.layer.borderWidth = 0
}
var oldMinx = oldFrame.minX
var newMinx = newFrame.minX
UIView.animate(withDuration: 0.25) {
if newPage < oldPage {
oldMinx = oldMinx + (self.currentPointSize.width - self.otherPointSize.width)
}
oldDot.frame = CGRect(x: oldMinx, y: newFrame.minY, width: self.otherPointSize.width, height: self.otherPointSize.height)
if newPage > oldPage {
newMinx = newMinx - (self.currentPointSize.width - self.otherPointSize.width)
}
newDot.frame = CGRect(x: newMinx, y: oldFrame.minY, width: self.currentPointSize.width, height: self.currentPointSize.height)
if newPage - oldPage > 1 { //
for index in (oldPage+1)..<newPage {
if index < self.dots.count {
let point = self.dots[index]
point.frame = CGRect(x: point.frame.minX - (self.currentPointSize.width - self.otherPointSize.width),
y: point.frame.minY,
width: self.otherPointSize.width,
height: self.otherPointSize.height)
}else{
return
}
}
}
if newPage - oldPage < -1 { //
for index in (newPage+1)..<oldPage {
if index < self.dots.count {
let point = self.dots[index]
point.frame = CGRect(x: point.frame.minX + (self.currentPointSize.width - self.otherPointSize.width),
y: point.frame.minY,
width: self.otherPointSize.width,
height: self.otherPointSize.height)
}else{
return
}
}
}
} completion: { finshed in
if finshed == false { //
if newPage < oldPage {
oldMinx = oldMinx + (self.currentPointSize.width - self.otherPointSize.width)
}
oldDot.frame = CGRect(x: oldMinx, y: newFrame.minY, width: self.otherPointSize.width, height: self.otherPointSize.height)
if newPage > oldPage {
newMinx = newMinx - (self.currentPointSize.width - self.otherPointSize.width)
}
newDot.frame = CGRect(x: newMinx, y: oldFrame.minY, width: self.currentPointSize.width, height: self.currentPointSize.height)
if newPage - oldPage > 1 { //
for index in (oldPage+1)..<newPage {
if index < self.dots.count {
let point = self.dots[index]
point.frame = CGRect(x: point.frame.minX - (self.currentPointSize.width - self.otherPointSize.width),
y: point.frame.minY,
width: self.otherPointSize.width,
height: self.otherPointSize.height)
}else{
return
}
}
}
if newPage - oldPage < -1 { //
for index in (newPage+1)..<oldPage {
if index < self.dots.count {
let point = self.dots[index]
point.frame = CGRect(x: point.frame.minX + (self.currentPointSize.width - self.otherPointSize.width),
y: point.frame.minY,
width: self.otherPointSize.width,
height: self.otherPointSize.height)
}else{
return
}
}
}
}
}
}
}