我目前有这个自定义的UIView显示3点。选定的点是最大的。这是它的外观:
的数据
但问题是,有时当currentPage为0时,它会覆盖第二个点,只显示两个点,但在视图层次结构调试器中,我可以看到第一个点(大点)覆盖了第二个点,只有第三个点可见。
就像这样:
的
我的代码:
import UIKit
class ExpandedCustomLoopedPageControl: UIView {
// MARK: - start flow in pagenumber set
public var numberOfPages: Int = 0 {
didSet {
dotViewArray.forEach { $0.removeFromSuperview() }
dotViewArray.removeAll()
for _ in 0..<numberOfPages {
let dotView = UIView()
dotView.layer.cornerRadius = cornerRadius
addSubview(dotView)
dotViewArray.append(dotView)
}
isInitialize = true
setNeedsLayout()
}
}
public var currentPage: Int {
set {
if newValue < 0 ||
newValue >= dotViewArray.count ||
dotViewArray.count == 0 ||
newValue == currentPage ||
inAnimating {
return
}
var animationDuration = 0.1
if (( currentPage == (numberOfPages - 1) ) && ( newValue == 0))
|| (currentPage == 0 && (newValue == (numberOfPages - 1))) {
animationDuration = 0
}
// MARK: - Shift to the right
if newValue > currentPage {
let currentView = dotViewArray[currentPage]
bringSubviewToFront(currentView)
inAnimating = true
UIView.animate(withDuration: animationDuration, animations: {
// For the currently selected dot, the x is
// unchanged, the width is increased, and several dots
// and gap distances are added.
let x = currentView.frame.origin.x
let y = currentView.frame.origin.y
let w = self.currentDotWidth + (self.dotSpace + self.otherDotWidth) * CGFloat(newValue - self.currentPage)
let h = currentView.frame.size.height
currentView.frame = CGRect(x: x, y: y, width: w, height: h)
}) { (_) in
let endView = self.dotViewArray[newValue]
endView.backgroundColor = currentView.backgroundColor
endView.frame = currentView.frame
self.bringSubviewToFront(endView)
currentView.backgroundColor = self.otherDotColor
// Shift left one by one
let start_X = currentView.frame.origin.x
for i in 0..<(newValue - self.currentPage) {
let dotView = self.dotViewArray[self.currentPage + i]
// shift left
let x = start_X + (self.otherDotWidth + self.dotSpace) * CGFloat(i)
let y = dotView.frame.origin.y
let w = self.otherDotWidth
let h = self.dotHeight
dotView.frame = CGRect(x: x, y: y, width: w, height: h)
}
UIView.animate(withDuration: 0.1, animations: {
let w = self.currentDotWidth
let x = endView.frame.maxX - self.currentDotWidth
let y = endView.frame.origin.y
let h = endView.frame.size.height
endView.frame = CGRect(x: x, y: y, width: w, height: h)
}) { (_) in
self.currentPageInner = newValue
self.inAnimating = false
}
}
}
// MARK: - Shift to the Left
else {
let currentView = self.dotViewArray[self.currentPage]
bringSubviewToFront(currentView)
inAnimating = true
UIView.animate(withDuration: animationDuration, animations: {
// For the currently selected dot, move x to the left, increase the width, increase a few dots and the gap distance
let x = currentView.frame.origin.x - (self.dotSpace + self.otherDotWidth) * CGFloat(self.currentPage - newValue)
let y = currentView.frame.origin.y
let w = self.currentDotWidth + (self.dotSpace + self.otherDotWidth) * CGFloat(self.currentPage - newValue)
let h = currentView.frame.size.height
currentView.frame = CGRect(x: x, y: y, width: w, height: h)
}) { (_) in
let endView = self.dotViewArray[newValue]
endView.backgroundColor = currentView.backgroundColor
endView.frame = currentView.frame
self.bringSubviewToFront(endView)
currentView.backgroundColor = self.otherDotColor
// Move the view to the right one by one
let start_X = currentView.frame.maxX
for i in 0..<(self.currentPage - newValue) {
let dotView = self.dotViewArray[self.currentPage - i]
let tempFrame = dotView.frame
// move right
let x = start_X - self.otherDotWidth - (self.otherDotWidth + self.dotSpace) * CGFloat(i)
let y = tempFrame.origin.y
let w = self.otherDotWidth
let h = tempFrame.size.height
dotView.frame = CGRect(x: x, y: y, width: w, height: h)
}
UIView.animate(withDuration: 0.1, animations: {
let x = endView.frame.origin.x
let y = endView.frame.origin.y
let w = self.currentDotWidth
let h = endView.frame.size.height
endView.frame = CGRect(x: x, y: y, width: w, height: h)
}) { (_) in
self.currentPageInner = newValue
self.inAnimating = false
}
}
}
}
get {
currentPageInner
}
}
// MARK: - properties of pageControl
public var currentDotWidth: CGFloat = 20
public var otherDotWidth: CGFloat = 5
public var dotHeight: CGFloat = 5
public var dotSpace: CGFloat = 7
public var cornerRadius: CGFloat = 2.5
public var currentDotColor: UIColor = Color.lines.color
public var otherDotColor: UIColor = Color.slider_indicator_bubble.color
private var currentPageInner: Int = 0
private var dotViewArray = [UIView]()
private var isInitialize: Bool = false
private var inAnimating: Bool = false
// MARK: - init()
override init(frame: CGRect) {
super.init(frame: frame)
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
override func layoutSubviews() {
super.layoutSubviews()
setupUI()
}
// MARK: - Setup UI
private func setupUI() {
if dotViewArray.isEmpty || isInitialize == false {
return
}
self.isInitialize = false
let totalWidth = CGFloat(numberOfPages) * (currentDotWidth + dotSpace) - dotSpace
var currentX = (frame.size.width - totalWidth) / 2
for (index, dotView) in dotViewArray.enumerated() {
// Update location
let width = (index == currentPage ? currentDotWidth : otherDotWidth)
let height = dotHeight
let y = (frame.size.height - height) / 2
dotView.frame = CGRect(x: currentX, y: y, width: width, height: height)
// Update color
dotView.backgroundColor = (index == currentPage) ? currentDotColor : otherDotColor
currentX += width + dotSpace
}
}
}
字符串
第一个点不应覆盖第二个和第三个点。
1条答案
按热度按时间puruo6ea1#
如果这是你正在寻找的分页效果,请继续阅读以获得不同的方法。
的数据
字符串
其中DotView是:
型
自定义分页控件是通过UIStackView和一堆带圆角的UIView来实现的。源代码在github上。
的