如何解决如何在自定义flowLayout中的uicollectionview中平滑动画过渡单元格
我想创建一个应用程序,该应用程序显示一系列带有标题(现在我有空圆圈)的照片,这些照片在水平 uicollectionview 中排列。我想让一个更大的圆圈显示在屏幕的中心,但线条中的其余圆圈更小并带有阴影。我通过为 uicollectionview 创建自己的布局来做到这一点。但是我有一个问题,我不知道如何解决。我希望圆圈之间的过渡平滑动画。这是我所做的example:
我想实现这样的目标:gif
我知道有一些库和框架可以做到这一点,但我想自己做。 这是我的代码:
class FlowViewController: UIViewController {
let cellWidth : CGFloat = 275
let cellHeight : CGFloat = 300
let cellSpacing : CGFloat = 10
private let circleCollectionView = UICollectionView(frame: CGRect.zero,collectionViewLayout: UICollectionViewFlowLayout.init())
private let layout = myCarouselFlowLayout()
private let collectionViewCellIdentifier = "PositionCollectionViewCell"
private var circles : [myCircle] = {
let pok1 = myCircle(name: "Bl4")
let pok2 = myCircle(name: "Bl3")
let pok3 = myCircle(name: "Bli")
let pok4 = myCircle(name: "Bl0")
let pok5 = myCircle(name: "Lal")
let pok6 = myCircle(name: "Te")
let pok7 = myCircle(name: "wTW")
let pok8 = myCircle(name: "H3RHG")
return [pok1,pok2,pok3,pok4,pok5,pok6,pok7,pok8]
}()
override func viewDidLoad() {
super.viewDidLoad()
view.backgroundColor = #colorLiteral(red: 0.4745098054,green: 0.8392156959,blue: 0.9764705896,alpha: 1)
view.addSubview(circleCollectionView)
configureCollectionView()
print(circles.count)
}
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
configureCollectionViewLayoutItemSize()
}
func configureCollectionView(){
layout.scrollDirection = .horizontal
layout.itemSize = CGSize(width: cellWidth,height: cellHeight)
layout.minimumLinespacing = cellSpacing
//set layout
circleCollectionView.setCollectionViewLayout(layout,animated: true)
//set delegates
setTableViewDelegates()
//register cells
circleCollectionView.register(CircleCollectionViewCell.self,forCellWithReuseIdentifier: collectionViewCellIdentifier)
//set contraits
circleCollectionView.translatesAutoresizingMaskIntoConstraints = false
circleCollectionView.heightAnchor.constraint(equalToConstant: cellHeight).isActive = true
circleCollectionView.widthAnchor.constraint(equalTo: view.widthAnchor).isActive = true
circleCollectionView.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true
circleCollectionView.centerYAnchor.constraint(equalTo: view.centerYAnchor).isActive = true
circleCollectionView.backgroundColor = .clear
circleCollectionView.decelerationRate = .fast
}
func calculateSectionInset() -> CGFloat { // should be overridden
let viewWith = UIScreen.main.bounds.size.width
return ( viewWith - cellWidth ) / 2
}
private func configureCollectionViewLayoutItemSize() {
let inset: CGFloat = calculateSectionInset()
layout.sectionInset = UIEdgeInsets(top: 0,left: inset,bottom: 0,right: inset)
layout.itemSize = CGSize(width: layout.collectionView!.frame.size.width - inset * 2,height: layout.collectionView!.frame.size.height)
}
}
extension FlowViewController: UICollectionViewDelegate,UICollectionViewDataSource{
func collectionView(_ collectionView: UICollectionView,numberOfItemsInSection section: Int) -> Int {
circles.count
}
func collectionView(_ collectionView: UICollectionView,cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
guard let cell = collectionView.dequeueReusableCell(withReuseIdentifier: collectionViewCellIdentifier,for: indexPath) as? CircleCollectionViewCell else {
fatalError("Bad instance of FavoritesCollectionViewCell")
}
cell.nameLabel.text = circles[indexPath.row].name
return cell
}
func setTableViewDelegates(){
circleCollectionView.delegate = self
circleCollectionView.dataSource = self
}
func collectionView(_ collectionView: UICollectionView,didSelectItemAt indexPath: IndexPath) {
print(circles.count)
}
}
extension FlowViewController: UICollectionViewDelegateFlowLayout {
func collectionView(_ collectionView: UICollectionView,layout collectionViewLayout: UICollectionViewLayout,sizeforItemAt indexPath: IndexPath) -> CGSize {
let width = cellWidth
let height = cellHeight
return CGSize(width: width,height: height)
}
}
class myCarouselFlowLayout: UICollectionViewFlowLayout,UICollectionViewDelegateFlowLayout {
private let fadeFactor: CGFloat = 0.5
override var collectionViewContentSize: CGSize {
super.collectionViewContentSize
}
override func layoutAttributesForElements(in rect: CGRect) -> [UICollectionViewLayoutAttributes]? {
super.layoutAttributesForElements(in: rect)?.map {
self.layoutAttributesForItem(at: $0.indexPath)!
}
}
override func layoutAttributesForItem(at indexPath: IndexPath) -> UICollectionViewLayoutAttributes? {
guard let superValue = super.layoutAttributesForItem(at: indexPath)?.copy() as? UICollectionViewLayoutAttributes else { return nil }
guard let cv = collectionView else { return nil }
let collectionMidPoint = CGPoint(x: cv.bounds.midX,y: cv.bounds.midY)
let itemmidPoint = superValue.center
let distance = abs(itemmidPoint.x - collectionMidPoint.x)
if distance > 100 {
UIView.animate(withDuration: 0.2) {
superValue.alpha = self.fadeFactor
superValue.transform = CGAffineTransform(scaleX: 0.8,y: 0.8)
cv.layoutIfNeeded()
}
}
return superValue
}
override func shouldInvalidateLayout(forBoundsChange newBounds: CGRect) -> Bool {
true
}
var veLocityThresholdPerPage: CGFloat = 2
override func targetContentOffset(forProposedContentOffset proposedContentOffset: CGPoint,withScrollingVeLocity veLocity: CGPoint) -> CGPoint {
guard let collectionView = collectionView else { return proposedContentOffset }
let pageLength: CGFloat
let approxPage: CGFloat
let currentPage: CGFloat
pageLength = (self.itemSize.width + self.minimumLinespacing)
approxPage = collectionView.contentOffset.x / pageLength
currentPage = round(approxPage)
if veLocity.x == 0 {
return CGPoint(x: currentPage * pageLength,y: 0)
}
var nextPage: CGFloat = currentPage + (veLocity.x > 0 ? 1 : -1)
let increment = veLocity.x / veLocityThresholdPerPage
nextPage += round(increment)
return CGPoint(x: nextPage * pageLength,y: 0)
}
请给我一些关于我应该在哪里以及如何在上面使用动画的建议?我应该用 UIView.animate 还是其他东西来做?我知道我需要使用 layoutIfNeeded() 来为约束设置动画,但它不起作用。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。