Fixing reuse and sizing issues.
This commit is contained in:
parent
185efa547e
commit
8da03356e4
@ -54,6 +54,32 @@ open class Carousel: View {
|
||||
|
||||
private var size: CGFloat?
|
||||
|
||||
// Updates the model and index.
|
||||
public func updateModelIndex() {
|
||||
(model as? CarouselModel)?.index = pageIndex
|
||||
}
|
||||
|
||||
open override func layoutSubviews() {
|
||||
super.layoutSubviews()
|
||||
// Accounts for any collection size changes
|
||||
DispatchQueue.main.async {
|
||||
self.layoutCollection()
|
||||
}
|
||||
}
|
||||
|
||||
/// Invalidates the layout and ensures we are paged to the correct cell.
|
||||
open func layoutCollection() {
|
||||
collectionView.collectionViewLayout.invalidateLayout()
|
||||
showPeaking(false)
|
||||
|
||||
// Go to current cell. layoutIfNeeded is needed otherwise cellForItem returns nil for peaking logic. The dispatch is a sad way to ensure the collection view is ready to be scrolled.
|
||||
DispatchQueue.main.async {
|
||||
self.collectionView.scrollToItem(at: IndexPath(row: self.currentIndex, section: 0), at: self.itemAlignment, animated: false)
|
||||
self.collectionView.layoutIfNeeded()
|
||||
self.showPeaking(true)
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - MVMCoreViewProtocol
|
||||
open override func setupView() {
|
||||
super.setupView()
|
||||
@ -73,15 +99,12 @@ open class Carousel: View {
|
||||
open override func updateView(_ size: CGFloat) {
|
||||
super.updateView(size)
|
||||
self.size = size
|
||||
collectionView.collectionViewLayout.invalidateLayout()
|
||||
showPeaking(false)
|
||||
|
||||
// Go to current cell. layoutIfNeeded is needed otherwise cellForItem returns nil for peaking logic. The dispatch is a sad way to ensure the collection view is ready to be scrolled.
|
||||
DispatchQueue.main.async {
|
||||
self.collectionView.scrollToItem(at: IndexPath(row: self.currentIndex, section: 0), at: self.itemAlignment, animated: false)
|
||||
self.collectionView.layoutIfNeeded()
|
||||
self.showPeaking(true)
|
||||
|
||||
// Update cells and re-layout.
|
||||
for cell in collectionView.visibleCells {
|
||||
(cell as? MVMCoreViewProtocol)?.updateView(size)
|
||||
}
|
||||
layoutCollection()
|
||||
}
|
||||
|
||||
// MARK: - MoleculeViewProtocol
|
||||
@ -108,6 +131,9 @@ open class Carousel: View {
|
||||
}
|
||||
|
||||
setupPagingMolecule(carouselModel.pagingMolecule, delegateObject: delegateObject)
|
||||
|
||||
pageIndex = carouselModel.index
|
||||
pagingView?.setPage(carouselModel.index)
|
||||
collectionView.reloadData()
|
||||
}
|
||||
|
||||
@ -197,6 +223,7 @@ open class Carousel: View {
|
||||
}
|
||||
let currentPage = pager.currentPage()
|
||||
localSelf.pageIndex = currentPage
|
||||
localSelf.updateModelIndex()
|
||||
localSelf.goTo(localSelf.currentIndex, animated: !UIAccessibility.isVoiceOverRunning)
|
||||
})
|
||||
}
|
||||
@ -246,7 +273,7 @@ open class Carousel: View {
|
||||
|
||||
extension Carousel: UICollectionViewDelegateFlowLayout {
|
||||
open func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
|
||||
let itemWidth = (size ?? collectionView.bounds.width) * CGFloat(itemWidthPercent)
|
||||
let itemWidth = collectionView.bounds.width * CGFloat(itemWidthPercent)
|
||||
return CGSize(width: itemWidth, height: collectionView.bounds.height)
|
||||
}
|
||||
|
||||
@ -280,19 +307,18 @@ extension Carousel: UIScrollViewDelegate {
|
||||
|
||||
func goTo(_ index: Int, animated: Bool) {
|
||||
showPeaking(false)
|
||||
setAccessiblity(collectionView.cellForItem(at: IndexPath(row: self.currentIndex, section: 0)), index: index)
|
||||
self.currentIndex = index
|
||||
self.collectionView.scrollToItem(at: IndexPath(row: self.currentIndex, section: 0), at: self.itemAlignment, animated: animated)
|
||||
if let cell = collectionView.cellForItem(at: IndexPath(row: self.currentIndex, section: 0)) {
|
||||
setAccessiblity(collectionView.cellForItem(at: IndexPath(row: self.currentIndex, section: 0)), index: index)
|
||||
setAccessiblity(collectionView.cellForItem(at: IndexPath(row: currentIndex, section: 0)), index: index)
|
||||
currentIndex = index
|
||||
updateModelIndex()
|
||||
collectionView.scrollToItem(at: IndexPath(row: currentIndex, section: 0), at: itemAlignment, animated: animated)
|
||||
if let cell = collectionView.cellForItem(at: IndexPath(row: currentIndex, section: 0)) {
|
||||
setAccessiblity(collectionView.cellForItem(at: IndexPath(row: currentIndex, section: 0)), index: index)
|
||||
UIAccessibility.post(notification: .layoutChanged, argument: cell)
|
||||
}
|
||||
}
|
||||
|
||||
func handleUserOnBufferCell() {
|
||||
guard loop else {
|
||||
return
|
||||
}
|
||||
guard loop else { return }
|
||||
|
||||
let lastPageIndex = numberOfPages + 1
|
||||
let goToIndex = {(index: Int) in
|
||||
@ -320,9 +346,11 @@ extension Carousel: UIScrollViewDelegate {
|
||||
let index = scrollView.contentOffset.x / (itemWidth + separatorWidth)
|
||||
let lastCellIndex = collectionView(collectionView, numberOfItemsInSection: 0) - 1
|
||||
if index < 1 {
|
||||
self.currentIndex = 0
|
||||
currentIndex = 0
|
||||
updateModelIndex()
|
||||
} else if index > CGFloat(lastCellIndex - 1) {
|
||||
self.currentIndex = lastCellIndex
|
||||
currentIndex = lastCellIndex
|
||||
updateModelIndex()
|
||||
}
|
||||
}
|
||||
|
||||
@ -348,9 +376,7 @@ extension Carousel: UIScrollViewDelegate {
|
||||
targetContentOffset.pointee = scrollView.contentOffset
|
||||
|
||||
// This is for setting up smooth custom paging. (Since UICollectionView only handles paging based on collection view size and not cell size).
|
||||
guard let separatorWidth = (collectionView.collectionViewLayout as? UICollectionViewFlowLayout)?.minimumLineSpacing else {
|
||||
return
|
||||
}
|
||||
guard let separatorWidth = (collectionView.collectionViewLayout as? UICollectionViewFlowLayout)?.minimumLineSpacing else { return }
|
||||
|
||||
// We switch cards if we pass the velocity threshold or position threshold (currently 50%).
|
||||
let itemWidth = collectionView.bounds.width * CGFloat(itemWidthPercent)
|
||||
|
||||
@ -12,7 +12,7 @@ import UIKit
|
||||
public static var identifier: String = "carousel"
|
||||
public var backgroundColor: Color?
|
||||
public var molecules: [CarouselItemModel]
|
||||
|
||||
public var index: Int = 0
|
||||
public var spacing: Float?
|
||||
public var border: Bool?
|
||||
public var loop: Bool?
|
||||
@ -29,6 +29,7 @@ import UIKit
|
||||
case moleculeName
|
||||
case backgroundColor
|
||||
case molecules
|
||||
case index
|
||||
case spacing
|
||||
case border
|
||||
case loop
|
||||
@ -40,15 +41,16 @@ import UIKit
|
||||
|
||||
required public init(from decoder: Decoder) throws {
|
||||
let typeContainer = try decoder.container(keyedBy: CodingKeys.self)
|
||||
self.molecules = try typeContainer.decode([CarouselItemModel].self, forKey: .molecules)
|
||||
self.backgroundColor = try typeContainer.decodeIfPresent(Color.self, forKey: .backgroundColor)
|
||||
self.spacing = try typeContainer.decodeIfPresent(Float.self, forKey: .spacing)
|
||||
self.border = try typeContainer.decodeIfPresent(Bool.self, forKey: .border)
|
||||
self.loop = try typeContainer.decodeIfPresent(Bool.self, forKey: .loop)
|
||||
self.height = try typeContainer.decodeIfPresent(Float.self, forKey: .height)
|
||||
self.itemWidthPercent = try typeContainer.decodeIfPresent(Float.self, forKey: .itemWidthPercent)
|
||||
self.itemAlignment = try typeContainer.decodeIfPresent(UICollectionView.ScrollPosition.self, forKey: .itemAlignment)
|
||||
self.pagingMolecule = try typeContainer.decodeModelIfPresent(codingKey: .pagingMolecule)
|
||||
molecules = try typeContainer.decode([CarouselItemModel].self, forKey: .molecules)
|
||||
index = try typeContainer.decodeIfPresent(Int.self, forKey: .index) ?? 0
|
||||
backgroundColor = try typeContainer.decodeIfPresent(Color.self, forKey: .backgroundColor)
|
||||
spacing = try typeContainer.decodeIfPresent(Float.self, forKey: .spacing)
|
||||
border = try typeContainer.decodeIfPresent(Bool.self, forKey: .border)
|
||||
loop = try typeContainer.decodeIfPresent(Bool.self, forKey: .loop)
|
||||
height = try typeContainer.decodeIfPresent(Float.self, forKey: .height)
|
||||
itemWidthPercent = try typeContainer.decodeIfPresent(Float.self, forKey: .itemWidthPercent)
|
||||
itemAlignment = try typeContainer.decodeIfPresent(UICollectionView.ScrollPosition.self, forKey: .itemAlignment)
|
||||
pagingMolecule = try typeContainer.decodeModelIfPresent(codingKey: .pagingMolecule)
|
||||
}
|
||||
|
||||
public func encode(to encoder: Encoder) throws {
|
||||
|
||||
@ -33,7 +33,7 @@ open class ThreeLayerTableViewController: ProgrammaticTableViewController {
|
||||
bottomView.updateView(width)
|
||||
showFooter(width)
|
||||
}
|
||||
self.tableView?.reloadData()
|
||||
tableView?.reloadData()
|
||||
}
|
||||
|
||||
open override func handleNewData() {
|
||||
|
||||
@ -278,7 +278,8 @@ import UIKit
|
||||
return
|
||||
}
|
||||
|
||||
if needsUpdateUI || screenSizeChanged() {
|
||||
// First update should be explicit (hence the zero check)
|
||||
if needsUpdateUI || (previousScreenSize != .zero && screenSizeChanged()) {
|
||||
updateViews()
|
||||
needsUpdateUI = false
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user