 	
 	private var lastCollectionViewSize: CGSize = CGSize.zero
 	private var lastScrollDirection: UICollectionViewScrollDirection!
+    var pageWidth: CGFloat {
+        switch scrollDirection {
+        case .horizontal:
+            return itemSize.width + minimumLineSpacing
+        case .vertical:
+            return itemSize.height + minimumLineSpacing
+        }
+    }
+    
+    /// Calculates the current centered page.
+    public var currentCenteredPage: Int? {
+        guard let collectionView = collectionView else { return nil }
+        let currentCenteredPoint = CGPoint(x: collectionView.contentOffset.x + collectionView.bounds.width/2, y: collectionView.contentOffset.y + collectionView.bounds.height/2)
+        
+        return collectionView.indexPathForItem(at: currentCenteredPoint)?.row
+    }
 	
 	public override init() {
 		super.init()

		// invalidate layout to center first and last
		let currentCollectionViewSize = collectionView.bounds.size
		if !currentCollectionViewSize.equalTo(lastCollectionViewSize) || lastScrollDirection != scrollDirection {
			let inset: CGFloat
			switch scrollDirection {
			case .horizontal:
				inset = (collectionView.bounds.size.width - itemSize.width) / 2
				collectionView.contentInset = UIEdgeInsets(top: 0, left: inset, bottom: 0, right: inset)
				collectionView.contentOffset = CGPoint(x: -inset, y: 0)
			case .vertical:
				inset = (collectionView.bounds.size.height - itemSize.height) / 2
				collectionView.contentInset = UIEdgeInsets(top: inset, left: 0, bottom: inset, right: 0)
				collectionView.contentOffset = CGPoint(x: 0, y: -inset)
			}
			lastCollectionViewSize = currentCollectionViewSize
			lastScrollDirection = scrollDirection
		}
	}
	
	private func determineProposedRect(collectionView: UICollectionView, proposedContentOffset: CGPoint) -> CGRect {
		let size = collectionView.bounds.size
		let origin: CGPoint
		switch scrollDirection {
		case .horizontal:
			origin = CGPoint(x: proposedContentOffset.x, y: 0)
		case .vertical:
			origin = CGPoint(x: 0, y: proposedContentOffset.y)
		}
		return CGRect(origin: origin, size: size)
	}
	
	private func attributesForRect(
		collectionView: UICollectionView,
		layoutAttributes: [UICollectionViewLayoutAttributes],
		proposedContentOffset: CGPoint
		) -> UICollectionViewLayoutAttributes? {
		
		var candidateAttributes: UICollectionViewLayoutAttributes?
		let proposedCenterOffset: CGFloat
		
		switch scrollDirection {
		case .horizontal:
			proposedCenterOffset = proposedContentOffset.x + collectionView.bounds.size.width / 2
		case .vertical:
			proposedCenterOffset = proposedContentOffset.y + collectionView.bounds.size.height / 2
		}
		
		for attributes: UICollectionViewLayoutAttributes in layoutAttributes {
			guard attributes.representedElementCategory == .cell else { continue }
			guard candidateAttributes != nil else {
				candidateAttributes = attributes
				continue
			}
			
			switch scrollDirection {
			case .horizontal:
				if fabs(attributes.center.x - proposedCenterOffset) < fabs(candidateAttributes!.center.x - proposedCenterOffset) {
					candidateAttributes = attributes
				}
			case .vertical:
				if fabs(attributes.center.y - proposedCenterOffset) < fabs(candidateAttributes!.center.y - proposedCenterOffset) {
					candidateAttributes = attributes
				}
			}
		}
		return candidateAttributes
	}
	
	// swiftlint:disable line_length

		}
	}
	
	/// Programatically scrolls to a page at a specified index.
	///
	/// - Parameters:
