我正在尝试创建一个Gallery应用,非常类似于iOS设备中已内置的应用。我添加了一些随机图像作为源数据,并设置了两个视图控制器,两个都是“集合”视图,但第一个显示所有可用图像,第二个分别显示每个图像。当我导航到第二个视图控制器(您可以在其中看到单个图像)时,问题就开始出现;当我尝试水平滚动时,总是出现同一张照片,它永远不会改变或遍历imagesArray(它为UICollectionView Data提供了源)资源)。即使UIImageArray中有四个图像,当我导航到第二个视图控制器时,我也可以前后滚动,但始终会出现同一张照片。我希望它的行为使用户可以前后滚动并查看数组中的每个图像(iOS Gallery App中也是一样)
该应用程序应该加载用户选择的图像,但是可以加载,但是当我滚动时它会保留在同一图像中。该应用程序确切地知道在第一个视图控制器中使用indexPath中给出的indexPath在imagesArray中检索什么图像,并在prepareForSegue方法中将其推送到第二个图像中,当我这样做时,将显示用户选择的图像,但仅显示该图像。该引用存储在一个名为“ passedContentOffSet”的变量中,该变量引用先前ViewController的indexPath。然后,我使用passedContentOffSet.item来填充第二个视图控制器的集合视图的数据,但是它发生了上述问题。我将其更改为indexPath.item,现在集合视图可以滚动浏览所有可用的图像,但是它始终从第一张图像开始,而不是从用户选择的图像开始。
First View Controller(垂直显示所有图像)
class CollectionViewController: UIViewController, UINavigationBarDelegate, UICollectionViewDelegate, UICollectionViewDataSource, UICollectionViewDelegateFlowLayout {
let context = (UIApplication.shared.delegate as! AppDelegate).persistentContainer.viewContext
@IBOutlet weak var collectionView: UICollectionView!
struct Storyboard {
static let photoCell = "PhotoCell"
static let sectionHeaderView = "SectionHeaderView"
static let showDetailVC = "ShowImageDetail"
static let leftAndRightPaddings: CGFloat = 2.0
static let numberOfItemsPerRow: CGFloat = 3.0
}
var images:[UIImage] = [UIImage(named: "facebook")!, UIImage(named: "pinterest")!, UIImage(named: "linkedin")!, UIImage(named: "amazon")! ]
@IBOutlet weak var toolBar: UIToolbar!
var selectedIndexPath:IndexPath = IndexPath()
override func viewDidLoad() {
super.viewDidLoad()
navigationItem.backBarButtonItem?.tintColor = UIColor.white
collectionView.delegate = self
collectionView.reloadData()
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
let collectionViewWidth = collectionView.frame.width
let itemWidth = (collectionViewWidth - Storyboard.leftAndRightPaddings) / Storyboard.numberOfItemsPerRow
return CGSize(width: itemWidth, height: itemWidth)
}
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return images.count
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "photo", for: indexPath) as! CollectionViewCell
let selectedItem = images[indexPath.row]
cell.userImageView.image = selectedItem
return cell
}
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
selectedIndexPath = indexPath
performSegue(withIdentifier: "goToDescription", sender: self)
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "goToDescription" {
let destinationVC = segue.destination as! ImagePreviewVC
destinationVC.images = images
destinationVC.passedContentOffset = selectedIndexPath
}
}
}
现在,第二个View Controller,该应用程序应该在其中向用户显示用户选择的单个图像,并且还能够水平滚动以查看其他图像
class ImagePreviewVC: UIViewController, UICollectionViewDelegate, UICollectionViewDataSource, UICollectionViewDelegateFlowLayout {
var myCollectionView: UICollectionView!
var imgArray = [UIImage]()
var passedContentOffset = IndexPath()
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
self.view.backgroundColor=UIColor.black
let layout = UICollectionViewFlowLayout()
layout.sectionInset = UIEdgeInsets(top: 0, left: 0, bottom: 0, right: 0)
layout.minimumInteritemSpacing=0
layout.minimumLineSpacing=0
layout.scrollDirection = .horizontal
myCollectionView = UICollectionView(frame: self.view.frame, collectionViewLayout: layout)
myCollectionView.delegate=self
myCollectionView.dataSource=self
myCollectionView.register(ImagePreviewFullViewCell.self, forCellWithReuseIdentifier: "Cell")
myCollectionView.isPagingEnabled = true
myCollectionView.scrollToItem(at: passedContentOffset, at: .left, animated: true)
self.view.addSubview(myCollectionView)
myCollectionView.autoresizingMask = UIViewAutoresizing(rawValue: UIViewAutoresizing.RawValue(UInt8(UIViewAutoresizing.flexibleWidth.rawValue) | UInt8(UIViewAutoresizing.flexibleHeight.rawValue)))
}
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return imgArray.count
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell=collectionView.dequeueReusableCell(withReuseIdentifier: "Cell", for: indexPath) as! ImagePreviewFullViewCell
cell.imgView.image=imgArray[indexPath.row]
return cell
}
override func viewWillLayoutSubviews() {
super.viewWillLayoutSubviews()
guard let flowLayout = myCollectionView.collectionViewLayout as? UICollectionViewFlowLayout else { return }
flowLayout.itemSize = myCollectionView.frame.size
flowLayout.invalidateLayout()
myCollectionView.collectionViewLayout.invalidateLayout()
}
override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) {
super.viewWillTransition(to: size, with: coordinator)
let offset = myCollectionView.contentOffset
let width = myCollectionView.bounds.size.width
let index = round(offset.x / width)
let newOffset = CGPoint(x: index * size.width, y: offset.y)
myCollectionView.setContentOffset(newOffset, animated: false)
coordinator.animate(alongsideTransition: { (context) in
self.myCollectionView.reloadData()
self.myCollectionView.setContentOffset(newOffset, animated: false)
}, completion: nil)
}
}
单元格类别:
class ImagePreviewFullViewCell: UICollectionViewCell, UIScrollViewDelegate {
var scrollImg: UIScrollView!
var imgView: UIImageView!
override init(frame: CGRect) {
super.init(frame: frame)
scrollImg = UIScrollView()
scrollImg.delegate = self
scrollImg.alwaysBounceVertical = false
scrollImg.alwaysBounceHorizontal = false
scrollImg.showsVerticalScrollIndicator = true
scrollImg.flashScrollIndicators()
scrollImg.minimumZoomScale = 1.0
scrollImg.maximumZoomScale = 4.0
let doubleTapGest = UITapGestureRecognizer(target: self, action: #selector(handleDoubleTapScrollView(recognizer:)))
doubleTapGest.numberOfTapsRequired = 2
scrollImg.addGestureRecognizer(doubleTapGest)
self.addSubview(scrollImg)
imgView = UIImageView()
imgView.image = UIImage(named: "user3")
scrollImg.addSubview(imgView!)
imgView.contentMode = .scaleAspectFit
}
@objc func handleDoubleTapScrollView(recognizer: UITapGestureRecognizer) {
if scrollImg.zoomScale == 1 {
scrollImg.zoom(to: zoomRectForScale(scale: scrollImg.maximumZoomScale, center: recognizer.location(in: recognizer.view)), animated: true)
} else {
scrollImg.setZoomScale(1, animated: true)
}
}
func zoomRectForScale(scale: CGFloat, center: CGPoint) -> CGRect {
var zoomRect = CGRect.zero
zoomRect.size.height = imgView.frame.size.height / scale
zoomRect.size.width = imgView.frame.size.width / scale
let newCenter = imgView.convert(center, from: scrollImg)
zoomRect.origin.x = newCenter.x - (zoomRect.size.width / 2.0)
zoomRect.origin.y = newCenter.y - (zoomRect.size.height / 2.0)
return zoomRect
}
func viewForZooming(in scrollView: UIScrollView) -> UIView? {
return self.imgView
}
override func layoutSubviews() {
super.layoutSubviews()
scrollImg.frame = self.bounds
imgView.frame = self.bounds
}
override func prepareForReuse() {
super.prepareForReuse()
scrollImg.setZoomScale(1, animated: true)
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}
我希望用户实际上可以在第一个视图控制器中选择图像,并在第二个视图控制器中分别显示该图像,也可以从那里向右或向左滑动并查看阵列中的其他图像,就像iOS Gallery应用程序一样。