gpt4 book ai didi

ios - 如何使 UICollectionView 的中心单元格与位于侧面的其他两个单元格重叠?

转载 作者:搜寻专家 更新时间:2023-10-30 21:56:00 26 4
gpt4 key购买 nike

我正在制作一个 Collection View 以生成轮播效果。

我需要中心单元格与左右两侧的其他两个单元格重叠。中心单元需要始终位于顶部。

但是,当我尝试将侧面的单元格与中心的单元格重叠时,它不起作用。相反,右侧单元格(蓝色单元格)与中心单元格(黑色单元格)重叠,如下图所示。

enter image description here

为此效果使用的代码如下:

下面是 Collection View 的 View Controller 。

import UIKit

private let reuseIdentifier = "Cell"
let kRoomCellScaling: CGFloat = 0.6

class RoomsViewController: UICollectionViewController {

override func viewDidLoad() {
super.viewDidLoad()

// This method sets up the collection view
let layout = UPCarouselFlowLayout()
layout.itemSize = CGSizeMake(250, 250)
layout.scrollDirection = .Horizontal

layout.sideItemAlpha = 1
layout.sideItemScale = 0.8
layout.spacingMode = UPCarouselFlowLayoutSpacingMode.overlap(visibleOffset: 60)

collectionView?.setCollectionViewLayout(layout, animated: false)

}

override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}



// MARK: UICollectionViewDataSource

override func numberOfSectionsInCollectionView(collectionView: UICollectionView) -> Int {
// #warning Incomplete implementation, return the number of sections
return 1
}


override func collectionView(collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
// #warning Incomplete implementation, return the number of items
return 3
}

override func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCellWithReuseIdentifier(reuseIdentifier, forIndexPath: indexPath)



// Configure the cell
switch indexPath.row%3 {

case 0:
cell.backgroundColor = UIColor.redColor()
case 1:
cell.backgroundColor = UIColor.blackColor()
case 2:
cell.backgroundColor = UIColor.blueColor()

default:
break

}

return cell
}


}

下面是用于 Collection View 的流布局。

import UIKit


public enum UPCarouselFlowLayoutSpacingMode {
case fixed(spacing: CGFloat)
case overlap(visibleOffset: CGFloat)
}

public class UPCarouselFlowLayout: UICollectionViewFlowLayout {

private struct LayoutState {
var size: CGSize
var direction: UICollectionViewScrollDirection
func isEqual(otherState: LayoutState) -> Bool {
return CGSizeEqualToSize(self.size, otherState.size) && self.direction == otherState.direction
}
}

@IBInspectable public var sideItemScale: CGFloat = 0.6
@IBInspectable public var sideItemAlpha: CGFloat = 0.6
public var spacingMode = UPCarouselFlowLayoutSpacingMode.fixed(spacing: 40)

private var state = LayoutState(size: CGSizeZero, direction: .Horizontal)


override public func prepareLayout() {
super.prepareLayout()

let currentState = LayoutState(size: self.collectionView!.bounds.size, direction: self.scrollDirection)

if !self.state.isEqual(currentState) {
self.setupCollectionView()
self.updateLayout()
self.state = currentState
}
}

private func setupCollectionView() {
guard let collectionView = self.collectionView else { return }
if collectionView.decelerationRate != UIScrollViewDecelerationRateFast {
collectionView.decelerationRate = UIScrollViewDecelerationRateFast
}
}

private func updateLayout() {
guard let collectionView = self.collectionView else { return }

let collectionSize = collectionView.bounds.size
let isHorizontal = (self.scrollDirection == .Horizontal)

let yInset = (collectionSize.height - self.itemSize.height) / 2
let xInset = (collectionSize.width - self.itemSize.width) / 2
self.sectionInset = UIEdgeInsetsMake(yInset, xInset, yInset, xInset)

let side = isHorizontal ? self.itemSize.width : self.itemSize.height
let scaledItemOffset = (side - side*self.sideItemScale) / 2
switch self.spacingMode {
case .fixed(let spacing):
self.minimumLineSpacing = spacing - scaledItemOffset
case .overlap(let visibleOffset):
let fullSizeSideItemOverlap = visibleOffset + scaledItemOffset
let inset = isHorizontal ? xInset : yInset
self.minimumLineSpacing = inset - fullSizeSideItemOverlap
}
}

override public func shouldInvalidateLayoutForBoundsChange(newBounds: CGRect) -> Bool {
return true
}

override public func layoutAttributesForElementsInRect(rect: CGRect) -> [UICollectionViewLayoutAttributes]? {
guard let superAttributes = super.layoutAttributesForElementsInRect(rect),
let attributes = NSArray(array: superAttributes, copyItems: true) as? [UICollectionViewLayoutAttributes]
else { return nil }
return attributes.map({ self.transformLayoutAttributes($0) })
}

private func transformLayoutAttributes(attributes: UICollectionViewLayoutAttributes) -> UICollectionViewLayoutAttributes {
guard let collectionView = self.collectionView else { return attributes }
let isHorizontal = (self.scrollDirection == .Horizontal)

let collectionCenter = isHorizontal ? collectionView.frame.size.width/2 : collectionView.frame.size.height/2
let offset = isHorizontal ? collectionView.contentOffset.x : collectionView.contentOffset.y
let normalizedCenter = (isHorizontal ? attributes.center.x : attributes.center.y) - offset

let maxDistance = (isHorizontal ? self.itemSize.width : self.itemSize.height) + self.minimumLineSpacing
let distance = min(abs(collectionCenter - normalizedCenter), maxDistance)
let ratio = (maxDistance - distance)/maxDistance

let alpha = ratio * (1 - self.sideItemAlpha) + self.sideItemAlpha
let scale = ratio * (1 - self.sideItemScale) + self.sideItemScale
attributes.alpha = alpha
attributes.transform3D = CATransform3DScale(CATransform3DIdentity, scale, scale, 1)

return attributes
}

override public func targetContentOffsetForProposedContentOffset(proposedContentOffset: CGPoint, withScrollingVelocity velocity: CGPoint) -> CGPoint {
guard let collectionView = collectionView where !collectionView.pagingEnabled,
let layoutAttributes = self.layoutAttributesForElementsInRect(collectionView.bounds)
else { return super.targetContentOffsetForProposedContentOffset(proposedContentOffset) }

let isHorizontal = (self.scrollDirection == .Horizontal)

let midSide = (isHorizontal ? collectionView.bounds.size.width : collectionView.bounds.size.height) / 2
let proposedContentOffsetCenterOrigin = (isHorizontal ? proposedContentOffset.x : proposedContentOffset.y) + midSide

var targetContentOffset: CGPoint
if isHorizontal {
let closest = layoutAttributes.sort { abs($0.center.x - proposedContentOffsetCenterOrigin) < abs($1.center.x - proposedContentOffsetCenterOrigin) }.first ?? UICollectionViewLayoutAttributes()
targetContentOffset = CGPoint(x: floor(closest.center.x - midSide), y: proposedContentOffset.y)
}
else {
let closest = layoutAttributes.sort { abs($0.center.y - proposedContentOffsetCenterOrigin) < abs($1.center.y - proposedContentOffsetCenterOrigin) }.first ?? UICollectionViewLayoutAttributes()
targetContentOffset = CGPoint(x: proposedContentOffset.x, y: floor(closest.center.y - midSide))
}

return targetContentOffset
}
}

那么,如何让中心单元格始终与其他两侧单元格重叠?

最佳答案

您可以根据与中心的距离翻译您的项目为一个小的负 z 值。

替换这一行:

attributes.transform3D = CATransform3DScale(CATransform3DIdentity, scale, scale, 1)

let visibleRect = CGRect(origin: self.collectionView!.contentOffset, size: self.collectionView!.bounds.size)
let dist = CGRectGetMidX(attributes.frame) - CGRectGetMidX(visibleRect)
var transform = CATransform3DScale(CATransform3DIdentity, scale, scale, 1)
transform = CATransform3DTranslate(transform, 0, 0, -abs(dist/1000))
attributes.transform3D = transform

enter image description here

或者您可以根据与中心的距离围绕 y 轴旋转项目,并为 transform.m34 提供一个小的负值,这样它就会有透视效果和更逼真的外观。

替换这一行:

attributes.transform3D = CATransform3DScale(CATransform3DIdentity, scale, scale, 1)

let visibleRect = CGRect(origin: self.collectionView!.contentOffset, size: self.collectionView!.bounds.size)
let dist = CGRectGetMidX(attributes.frame) - CGRectGetMidX(visibleRect)
let currentAngle = dist / (CGRectGetWidth(visibleRect)/2)
var transform = CATransform3DScale(CATransform3DIdentity, scale, scale, 1)
transform.m34 = -1.0 / 1000
transform = CATransform3DRotate(transform, -currentAngle, 0, 1, 0)
attributes.transform3D = transform

enter image description here

关于ios - 如何使 UICollectionView 的中心单元格与位于侧面的其他两个单元格重叠?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39390979/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com