TMCoverFlowLayout
来源:互联网 发布:查车档案软件 编辑:程序博客网 时间:2024/06/06 00:46
A cover flow implementation by subclassing UICollectionViewFlowLayout
Original found on here, thanks to solomidSF(He must be a dota player:p), and I copy it using Swift with a little modifications
/*** Layout to add cover flow effect to collection view scrolling.* Applicable only for horizontal flow direction.*/class TMCoverFlowLayout: UICollectionViewFlowLayout { /** * Max degree that can be applied to individual item. * Default to 45 degrees. */ var maxCoverDegree: CGFloat = 0 /** * Determines how elements covers each other. * Should be in range 0..1. * Default to 0.25. * Examples: * 0 means that items are placed within a continious line. * 0.5 means that half of 3 and 1 cover will be behind 2. */ var coverDensity: CGFloat = 0 required init(coder aDecoder: NSCoder) { super.init(coder: aDecoder) self.commonInit() } override init() { super.init() self.commonInit() } override func prepareLayout() { super.prepareLayout() //This is a cover flow layout so forcely set these properties self.scrollDirection = .Horizontal self.collectionView?.pagingEnabled = true assert(self.collectionView?.numberOfSections() == 1, "TMCoverFlowLayout: Multiple sections aren't supported!") assert(self.scrollDirection == .Horizontal, "TMCoverFlowLayout: Vertical scrolling isn't supported!") } override func shouldInvalidateLayoutForBoundsChange(newBounds: CGRect) -> Bool { return true } override func layoutAttributesForElementsInRect(rect: CGRect) -> [AnyObject]? { var indexPaths = self.indexPathsContainedInRect(rect) var resultingAttributes = [UICollectionViewLayoutAttributes]() for path in indexPaths { // We should create attributes by ourself. var attributes = self.layoutAttributesForItemAtIndexPath(path) resultingAttributes.append(attributes) } return resultingAttributes } override func layoutAttributesForItemAtIndexPath(indexPath: NSIndexPath) -> UICollectionViewLayoutAttributes! { var attributes = UICollectionViewLayoutAttributes(forCellWithIndexPath: indexPath) attributes.size = self.itemSize attributes.center = CGPoint(x: self.collectionViewWidth() * CGFloat(indexPath.row) + self.collectionViewWidth(), y: self.collectionViewHeight()/2) self.interpolateAttributes(attributes, forOffset: self.collectionView!.contentOffset.x) return attributes } override func collectionViewContentSize() -> CGSize { return CGSize(width: self.collectionView!.bounds.size.width * CGFloat(self.collectionView!.numberOfItemsInSection(0)), height: self.collectionView!.bounds.size.height) } func collectionViewHeight() -> CGFloat { return self.collectionView!.bounds.size.height } func collectionViewWidth() -> CGFloat { return self.collectionView!.bounds.size.width } func commonInit() { self.maxCoverDegree = 15 self.coverDensity = 0 } func itemCenterForRow(row: Int) -> CGPoint { var collectionViewSize = self.collectionView!.bounds.size return CGPoint(x: CGFloat(row) * collectionViewSize.width + collectionViewSize.width/2, y: collectionViewSize.height/2) } func minXForRow(row: Int) -> CGFloat { return self.itemCenterForRow(row - 1).x + (1.0/2 - self.coverDensity) * self.itemSize.width } func maxXForRow(row: Int) -> CGFloat { return self.itemCenterForRow(row + 1).x - (1.0/2 - self.coverDensity) * self.itemSize.width } func minXCenterForRow(row: Int) -> CGFloat { var center = self.itemCenterForRow(row - 1).x return center + (self.itemSize.width/2) * (1 - 2 * self.coverDensity + cos(self.degreesToRad(self.maxCoverDegree))) } func maxXCenterForRow(row: Int) -> CGFloat { var center = self.itemCenterForRow(row + 1).x return center - (self.itemSize.width/2) * (1 - 2 * self.coverDensity + cos(self.degreesToRad(self.maxCoverDegree))) } func degreesToRad(degrees: CGFloat) -> CGFloat { return degrees * CGFloat(M_PI)/180.0 } func indexPathsContainedInRect(rect: CGRect) -> [NSIndexPath] { if self.collectionView!.numberOfItemsInSection(0) == 0 { // Nothing to do here when we don't have items. return [NSIndexPath]() } // Find min and max rows that can be determined for sure. var minRow = Int(max(rect.origin.x/self.collectionViewWidth(), 0)) var maxRow = Int(CGRectGetMaxX(rect)/self.collectionViewWidth()) // Additional check for rows that also can be included (our rows are moving depending on content size). var candidateMinRow = Int(max(minRow - 1, 0)) if self.maxXForRow(candidateMinRow) >= rect.origin.x { // We have a row that is less than given minimum. minRow = candidateMinRow } var candidateMaxRow = Int(min(maxRow + 1, self.collectionView!.numberOfItemsInSection(0) - 1)) if self.minXForRow(candidateMaxRow) <= CGRectGetMaxX(rect) { maxRow = candidateMaxRow } // Simply add index paths between min and max. var resultingIndexPaths = [NSIndexPath]() for var i = minRow; i <= maxRow; i++ { resultingIndexPaths.append(NSIndexPath(forRow: i, inSection: 0)) } return resultingIndexPaths } func interpolateAttributes(attributes: UICollectionViewLayoutAttributes, forOffset offset: CGFloat) { var attributesPath = attributes.indexPath // Interpolate offset for given attribute. For this task we need min max interval and min and max x allowed for item. var minInterval = CGFloat(attributesPath.row - 1) * self.collectionViewWidth() var maxInterval = CGFloat(attributesPath.row + 1) * self.collectionViewWidth() var minX = self.minXCenterForRow(attributesPath.row) var maxX = self.maxXCenterForRow(attributesPath.row) // Interpolate by formula var interpolatedX = min(max(minX + ((maxX - minX)/(maxInterval - minInterval)) * (offset - minInterval), minX), maxX) attributes.center = CGPoint(x: interpolatedX, y: attributes.center.y) // Interpolate position into angle by formula. var angle = -self.maxCoverDegree + (interpolatedX - minX) * 2 * self.maxCoverDegree / (maxX - minX) var transform = CATransform3DIdentity // Add perspective. transform.m34 = -1/500.0 // Then rotate.// transform = CATransform3DRotate(transform, angle * CGFloat(M_PI)/180, 0, 1, 0) // Or scale let scale = max(1 - abs(angle)/45, 0.9) transform = CATransform3DScale(transform, scale, scale, scale) let alpha = max(1 - abs(angle)/45, 0.5) attributes.alpha = alpha attributes.transform3D = transform attributes.zIndex = NSIntegerMax - attributesPath.row }}
0 0
- TMCoverFlowLayout
- 体育场围栏网
- 用Swift开发Mac App(2)
- 基姆拉尔森计算公式
- opencv学习2
- DFS Letter Combinations of a Phone Number
- TMCoverFlowLayout
- tomcat配置过程中出现JRE_HOME environment variable is not defined correctly的错误
- read/write proc例程
- 园林隔离栅
- Linux上的free命令详解
- Duplicate standby database from active database
- 动态规划之最优二叉搜索树
- linux服务器用作路由器
- eclipse 工程导入可能出现的情况