我试图创建一个类似于TastemadeCity for iPad的效果。 仅景观。一个collectionView由细列(屏幕上的7.5)组成,用于动态数量的图像。 这个想法是,当collectionView水平滚动时,图像本身几乎不会移动,但是单元格会移动它并显示更多的图像。
我的工作几乎完美。但是,当创建单元格时,它将图像置于单元格中心而不是整个屏幕(由单元格数或collectionView内容偏移量抵消)。因此,当滚动集合时,eery图像会向右开始太远,并且最终会在显示边缘之前用完图像。如果我改变它,我尝试使用Aspect fit和aspect fill,它只是将图像缩小到单元格的宽度。它必须保持屏幕的高度/宽度。
为了简单起见,我试图将阵列中的所有图像自动裁剪为与设备屏幕相同的形状(我认为代码没问题?)
所以基本上,我如何将ImageView设置为屏幕大小,但只有一小部分可通过单元格看到,但是带有collectionView内容的偏移量?
import UIKit
let parallaxCellIdentifier = "parallaxCell"
class HomeViewController: UICollectionViewController {
var images = [UIImage]()
override func viewDidLoad() {
super.viewDidLoad()
setup()
}
func setup() {
for i in 1...14 {
let img = cropToBounds(UIImage(named:"\(i)@2x")!, width: Double(UIScreen.mainScreen().bounds.size.width), height: Double(UIScreen.mainScreen().bounds.size.height))
images.append(img)
}
}
func cropToBounds(image: UIImage, width: Double, height: Double) -> UIImage {
let contextImage: UIImage = UIImage(CGImage: image.CGImage!)
let contextSize: CGSize = UIScreen.mainScreen().bounds.size
var posX: CGFloat = 0.0
var posY: CGFloat = 0.0
var cgwidth: Double = width
var cgheight: Double = height
if Double(image.size.width/image.size.height) > 1 {
posX = ((contextSize.height - contextSize.width) / 2)
posY = 0
cgwidth = Double(contextSize.width)
cgheight = Double(contextSize.height)
} else if Double(image.size.width/image.size.height) <= 1 {
posX = 0
posY = ((contextSize.width - contextSize.height) / 2)
cgwidth = Double(contextSize.width)
cgheight = Double(contextSize.height)
}
let rect: CGRect = CGRectMake(posX, posY, CGFloat(cgwidth), CGFloat(cgheight))
// Create bitmap image from context using the rect
let imageRef: CGImageRef = CGImageCreateWithImageInRect(contextImage.CGImage, rect)!
// Create a new image based on the imageRef and rotate back to the original orientation
let image: UIImage = UIImage(CGImage: imageRef, scale: image.scale, orientation: image.imageOrientation)
return image
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
override func numberOfSectionsInCollectionView(collectionView: UICollectionView) -> Int {
return 1
}
override func collectionView(collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return images.count
}
override func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
let parallaxCell = collectionView.dequeueReusableCellWithReuseIdentifier(parallaxCellIdentifier, forIndexPath: indexPath) as! ParallaxCollectionViewCell
parallaxCell.image = images[indexPath.row]
parallaxCell.imageView.contentMode = .ScaleAspectFill
let xOffset = (collectionView.contentOffset.x )
parallaxCell.offset(CGPointMake(xOffset, 0.0)) // this doesnt make any difference at this point, i can remove it. I have tried moving the constraints which works here, but breaks them when scrolling
return parallaxCell
}
func collectionView(collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumInteritemSpacingForSectionAtIndex section: Int) -> CGFloat {
return 0
}
func collectionView(collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumLineSpacingForSectionAtIndex section: Int) -> CGFloat {
return 0
}
func collectionView(collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAtIndexPath indexPath: NSIndexPath) -> CGSize {
let widthOfPoster = collectionView.frame.size.width / 7.5
let heightOfPoster = collectionView.frame.size.height
return CGSizeMake(widthOfPoster, heightOfPoster)
}
override func scrollViewDidScroll(scrollView: UIScrollView) {
if let visibleCells = collectionView!.visibleCells() as? [ParallaxCollectionViewCell] {
for parallaxCell in visibleCells {
let xOffset = (collectionView!.contentOffset.x )
parallaxCell.offset(CGPointMake(xOffset, 0.0)) // this doesnt seem to do anything here, but works in the sr
}
}
}
}
这是单元格中的函数,它只是在滚动期间更改偏移量
func offset(offset: CGPoint) {
imageView.frame = CGRectOffset(self.imageView.bounds, offset.x, offset.y)
}
答案 0 :(得分:1)
所以我解决了。 我将所有图像裁剪成屏幕的形状。 然后在单元格的子视图中创建imageView。 这让我可以控制偏移量。
let parallaxCellIdentifier = "parallaxCell"
class HomeViewController: UICollectionViewController {
var images = [UIImage]()
let OffsetSpeed: CGFloat = 1025
let cellsPerScreen: CGFloat = 7.5
let ImageWidth: CGFloat = UIScreen.mainScreen().bounds.size.width
let imageHeight: CGFloat = UIScreen.mainScreen().bounds.size.height
override func viewDidLoad() {
super.viewDidLoad()
setup()
}
func setup() {
for i in 1...22 {
let img = cropToBounds(UIImage(named:"\(i)@2x")!, width: Double(ImageWidth), height: Double(imageHeight))
images.append(img)
}
}
func cropToBounds(image: UIImage, width: Double, height: Double) -> UIImage {
let contextImage: UIImage = UIImage(CGImage: image.CGImage!)
let posX: CGFloat = 0.0
let posY: CGFloat = 0.0
var cgwidth: Double = width
var cgheight: Double = height
let imageRatio = contextImage.size.width / contextImage.size.height
let contextRatio = CGFloat(width) / CGFloat(height)
if imageRatio >= contextRatio {
cgwidth = Double(contextImage.size.height) * Double(contextRatio)
cgheight = Double(contextImage.size.height)
} else {
cgwidth = Double(contextImage.size.width)
cgheight = (Double(contextImage.size.width) / Double(contextRatio))
}
let rect: CGRect = CGRectMake(posX, posY, CGFloat(cgwidth), CGFloat(cgheight))
// Create bitmap image from context using the rect
let imageRef: CGImageRef = CGImageCreateWithImageInRect(contextImage.CGImage, rect)!
// Create a new image based on the imageRef and rotate back to the original orientation
let image: UIImage = UIImage(CGImage: imageRef, scale: image.scale, orientation: image.imageOrientation)
return image
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
override func numberOfSectionsInCollectionView(collectionView: UICollectionView) -> Int {
return 1
}
override func collectionView(collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return images.count
}
override func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
let parallaxCell = collectionView.dequeueReusableCellWithReuseIdentifier(parallaxCellIdentifier, forIndexPath: indexPath) as! ParallaxCollectionViewCell
let xOffset = -((UIScreen.mainScreen().bounds.size.width / cellsPerScreen) * CGFloat(indexPath.row))
parallaxCell.offsetX = xOffset
parallaxCell.viewDidLayoutSubviews()
parallaxCell.rangeView.image = images[indexPath.row]
parallaxCell.path = indexPath
return parallaxCell
}
func collectionView(collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumInteritemSpacingForSectionAtIndex section: Int) -> CGFloat {
return 0
}
func collectionView(collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumLineSpacingForSectionAtIndex section: Int) -> CGFloat {
return 0
}
func collectionView(collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAtIndexPath indexPath: NSIndexPath) -> CGSize {
let widthOfPoster = collectionView.frame.size.width / cellsPerScreen
let heightOfPoster = collectionView.frame.size.height
return CGSizeMake(widthOfPoster, heightOfPoster)
}
override func scrollViewDidScroll(scrollView: UIScrollView) {
if let visibleCells = collectionView!.visibleCells() as? [ParallaxCollectionViewCell] {
for parallaxCell in visibleCells {
let xOffset = (((collectionView!.contentOffset.x ) / ImageWidth) * OffsetSpeed)
parallaxCell.offset(CGPointMake(xOffset, 0.0))
}
}
}
}
和Cell代码。 (RangeImage,只是一个空白的UIImageView类)
class ParallaxCollectionViewCell: UICollectionViewCell {
let rangeView = RangeImage(frame: CGRectZero)
let width = UIScreen.mainScreen().bounds.size.width
let height = UIScreen.mainScreen().bounds.size.height
var offsetX:CGFloat = 0.0
var path = NSIndexPath()
override func awakeFromNib() {
rangeView.backgroundColor = UIColor.redColor()
contentView.addSubview(rangeView)
}
func viewDidLayoutSubviews() {
rangeView.frame = CGRect(x: offsetX, y: 0.0,
width: width, height: height)
}
func offset(offset: CGPoint) {
contentView.frame = CGRectOffset(contentView.bounds, offset.x, offset.y)
}
}