Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import UIKit
class BasicExampleViewController: UIViewController,UITableViewDataSource,UITableViewDelegate,FSPagerViewDataSource,FSPagerViewDelegate {

fileprivate let sectionTitles = ["Configurations", "Decelaration Distance", "Item Size", "Interitem Spacing", "Number Of Items"]
fileprivate let configurationTitles = ["Automatic sliding","Infinite"]
fileprivate let configurationTitles = ["Automatic sliding","Infinite","itemAdjust"]
fileprivate let decelerationDistanceOptions = ["Automatic", "1", "2"]
fileprivate let imageNames = ["1.jpg","2.jpg","3.jpg","4.jpg","5.jpg","6.jpg","7.jpg"]
fileprivate var numberOfItems = 7
Expand Down Expand Up @@ -63,6 +63,9 @@ class BasicExampleViewController: UIViewController,UITableViewDataSource,UITable
} else if indexPath.row == 1 {
// IsInfinite
cell.accessoryType = self.pagerView.isInfinite ? .checkmark : .none
} else if indexPath.row == 2 {
// isItemAdjust
cell.accessoryType = self.pagerView.isItemAdjust ? .checkmark : .none
}
return cell
case 1:
Expand Down Expand Up @@ -130,6 +133,8 @@ class BasicExampleViewController: UIViewController,UITableViewDataSource,UITable
self.pagerView.automaticSlidingInterval = 3.0 - self.pagerView.automaticSlidingInterval
} else if indexPath.row == 1 { // IsInfinite
self.pagerView.isInfinite = !self.pagerView.isInfinite
} else if indexPath.row == 2 {
self.pagerView.isItemAdjust = !self.pagerView.isItemAdjust
}
tableView.reloadSections([indexPath.section], with: .automatic)
case 1:
Expand Down
26 changes: 19 additions & 7 deletions Sources/FSPageControl.swift
Original file line number Diff line number Diff line change
Expand Up @@ -103,31 +103,41 @@ open class FSPageControl: UIControl {

open override func layoutSublayers(of layer: CALayer) {
super.layoutSublayers(of: layer)

let diameter = self.itemSpacing
let spacing = self.interitemSpacing

let contentWidth: CGFloat = {
var width: CGFloat = 0.0
for layer in self.indicatorLayers {
width += layer.path?.boundingBoxOfPath.width ?? diameter
}
width += CGFloat((self.indicatorLayers.count - 1)) * spacing
return width
}()

var x: CGFloat = {
switch self.contentHorizontalAlignment {
case .left, .leading:
return 0
case .center, .fill:
let midX = self.contentView.bounds.midX
let amplitude = CGFloat(self.numberOfPages/2) * diameter + spacing*CGFloat((self.numberOfPages-1)/2)
return midX - amplitude
return midX - contentWidth * 0.5
case .right, .trailing:
let contentWidth = diameter*CGFloat(self.numberOfPages) + CGFloat(self.numberOfPages-1)*spacing
return contentView.frame.width - contentWidth
default:
return 0
}
}()

for (index,value) in self.indicatorLayers.enumerated() {
let width = value.path?.boundingBoxOfPath.width ?? diameter
let height = value.path?.boundingBoxOfPath.height ?? diameter
let state: UIControl.State = (index == self.currentPage) ? .selected : .normal
let image = self.images[state]
let size = image?.size ?? CGSize(width: diameter, height: diameter)
let origin = CGPoint(x: x - (size.width-diameter)*0.5, y: self.contentView.bounds.midY-size.height*0.5)
let size = image?.size ?? CGSize(width: width, height: height)
let origin = CGPoint(x: x - (size.width-width)*0.5, y: self.contentView.bounds.midY-size.height*0.5)
value.frame = CGRect(origin: origin, size: size)
x = x + spacing + diameter
x = x + spacing + width
}

}
Expand Down Expand Up @@ -221,6 +231,8 @@ open class FSPageControl: UIControl {
self.setNeedsLayout()
DispatchQueue.main.async {
self.updateIndicatorsIfNecessary()
// fix:iphone11 pro v17.5.1,更新indicators后没有调用layoutSublayers
self.setNeedsLayout()
}
}

Expand Down
21 changes: 18 additions & 3 deletions Sources/FSPageViewLayout.swift
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,17 @@ class FSPagerViewLayout: UICollectionViewLayout {
internal var leadingSpacing: CGFloat = 0
internal var itemSpacing: CGFloat = 0
internal var needsReprepare = true
internal var isItemAdjust: Bool = true {
didSet {
guard let collectionView = collectionView else { return }
if (isItemAdjust) {
self.leadingSpacing = self.scrollDirection == .horizontal ? (collectionView.frame.width-self.actualItemSize.width)*0.5 : (collectionView.frame.height-self.actualItemSize.height)*0.5
} else {
self.leadingSpacing = 0
}
self.adjustCollectionViewBounds()
}
}
internal var scrollDirection: FSPagerView.ScrollDirection = .horizontal

open override class var layoutAttributesClass: AnyClass {
Expand Down Expand Up @@ -75,7 +86,11 @@ class FSPagerViewLayout: UICollectionViewLayout {
return pagerView.interitemSpacing
}()
self.scrollDirection = pagerView.scrollDirection
self.leadingSpacing = self.scrollDirection == .horizontal ? (collectionView.frame.width-self.actualItemSize.width)*0.5 : (collectionView.frame.height-self.actualItemSize.height)*0.5
if (isItemAdjust) {
self.leadingSpacing = self.scrollDirection == .horizontal ? (collectionView.frame.width-self.actualItemSize.width)*0.5 : (collectionView.frame.height-self.actualItemSize.height)*0.5
} else {
self.leadingSpacing = 0
}
self.itemSpacing = (self.scrollDirection == .horizontal ? self.actualItemSize.width : self.actualItemSize.height) + self.actualInteritemSpacing

// Calculate and cache contentSize, rather than calculating each time
Expand Down Expand Up @@ -212,14 +227,14 @@ class FSPagerViewLayout: UICollectionViewLayout {
if self.scrollDirection == .vertical {
return 0
}
let contentOffsetX = origin.x - (collectionView.frame.width*0.5-self.actualItemSize.width*0.5)
let contentOffsetX = isItemAdjust ? (origin.x - (collectionView.frame.width*0.5-self.actualItemSize.width*0.5)) : origin.x
return contentOffsetX
}()
let contentOffsetY: CGFloat = {
if self.scrollDirection == .horizontal {
return 0
}
let contentOffsetY = origin.y - (collectionView.frame.height*0.5-self.actualItemSize.height*0.5)
let contentOffsetY = isItemAdjust ? (origin.y - (collectionView.frame.height*0.5-self.actualItemSize.height*0.5)) : origin.y
return contentOffsetY
}()
let contentOffset = CGPoint(x: contentOffsetX, y: contentOffsetY)
Expand Down
43 changes: 41 additions & 2 deletions Sources/FSPagerView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,15 @@ open class FSPagerView: UIView,UICollectionViewDataSource,UICollectionViewDelega
}
}

// 在banner中显示多项时,true: 调整item位置使其居中显示, false: 不调整
@IBInspectable
open var isItemAdjust: Bool = true {
didSet {
self.collectionViewLayout.isItemAdjust = isItemAdjust
self.collectionViewLayout.forceInvalidate()
}
}

/// An unsigned integer value that determines the deceleration distance of the pager view, which indicates the number of passing items during the deceleration. When the value of this property is FSPagerView.automaticDistance, the actual 'distance' is automatically calculated according to the scrolling speed of the pager view. Default is 1.
@IBInspectable
open var decelerationDistance: UInt = 1
Expand Down Expand Up @@ -252,6 +261,27 @@ open class FSPagerView: UIView,UICollectionViewDataSource,UICollectionViewDelega
}
return IndexPath(item: 0, section: 0)
}
// 新增
fileprivate var leftmostIndexPath: IndexPath {
guard self.numberOfItems > 0, self.collectionView.contentSize != .zero else {
return IndexPath(item: 0, section: 0)
}
let sortedIndexPaths = self.collectionView.indexPathsForVisibleItems.sorted { (l, r) -> Bool in
let leftFrame = self.collectionViewLayout.frame(for: l)
let rightFrame = self.collectionViewLayout.frame(for: r)
switch self.scrollDirection {
case .horizontal:
return leftFrame.minX < rightFrame.minX
case .vertical:
return leftFrame.minY < rightFrame.minY
}
}
let indexPath = sortedIndexPaths.first
if let indexPath = indexPath {
return indexPath
}
return IndexPath(item: 0, section: 0)
}
fileprivate var isPossiblyRotating: Bool {
guard let animationKeys = self.contentView.layer.animationKeys() else {
return false
Expand All @@ -278,6 +308,7 @@ open class FSPagerView: UIView,UICollectionViewDataSource,UICollectionViewDelega
self.backgroundView?.frame = self.bounds
self.contentView.frame = self.bounds
self.collectionView.frame = self.contentView.bounds
self.collectionViewLayout.needsReprepare = true
}

open override func willMove(toWindow newWindow: UIWindow?) {
Expand Down Expand Up @@ -477,8 +508,15 @@ open class FSPagerView: UIView,UICollectionViewDataSource,UICollectionViewDelega
/// Reloads all of the data for the collection view.
@objc(reloadData)
open func reloadData() {
self.collectionViewLayout.needsReprepare = true;
self.collectionViewLayout.needsReprepare = true
let indexPath = self.collectionView.indexPathsForVisibleItems.first
self.collectionView.reloadData()

// fix: 解决在reload时卡在一半的问题
if let indexPath = indexPath {
let offset = self.collectionViewLayout.contentOffset(for: indexPath)
self.collectionView.setContentOffset(offset, animated: false)
}
}

/// Selects the item at the specified index and optionally scrolls it into view.
Expand Down Expand Up @@ -561,6 +599,7 @@ open class FSPagerView: UIView,UICollectionViewDataSource,UICollectionViewDelega

// UICollectionView
let collectionViewLayout = FSPagerViewLayout()
collectionViewLayout.isItemAdjust = isItemAdjust
let collectionView = FSPagerCollectionView(frame: CGRect.zero, collectionViewLayout: collectionViewLayout)
collectionView.dataSource = self
collectionView.delegate = self
Expand All @@ -585,7 +624,7 @@ open class FSPagerView: UIView,UICollectionViewDataSource,UICollectionViewDelega
return
}
let contentOffset: CGPoint = {
let indexPath = self.centermostIndexPath
let indexPath = isItemAdjust ? self.centermostIndexPath : self.leftmostIndexPath
let section = self.numberOfSections > 1 ? (indexPath.section+(indexPath.item+1)/self.numberOfItems) : 0
let item = (indexPath.item+1) % self.numberOfItems
return self.collectionViewLayout.contentOffset(for: IndexPath(item: item, section: section))
Expand Down