我正在开发一款为用户展示照片的应用。我的设计就像Pinterest app。我在UICollectionView
内添加了UIScrollView
并禁用了UICollectionView
的滚动条。但是当我使用这个组件时,这样的UICollectionView根据其内容不可滚动。仅显示可见而其他未显示。这个项目的主要痛苦是CollectionViews'内容是动态的。它可能会随着用户的交互而改变。我的问题是如何使用UIScrollView完全滚动UICollectionView及其动态内容。
让我分享截图。
第一张图片描述首次打开。第二个图像描述了滚动问题。 第三张图片描述了我的故事板。
感谢您的帮助。
这是我的故事板
我的代码
//
// ViewController.swift
// ScrollCollectionView
//
// Created by Cbs on 31.05.2017.
// Copyright © 2017 Cbs. All rights reserved.
//
import UIKit
class ViewController: UIViewController, UICollectionViewDelegate, UICollectionViewDataSource, UICollectionViewDelegateFlowLayout {
@IBOutlet weak var collectionView: UICollectionView!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return 25
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "cell", for: indexPath) as! CollectionViewCell
cell.addShadow(opacitiy: 1, shadowRadius: 3, shadowOffsetWidth: 2, shadowOffsetHeight: 2, shadowColor: UIColor.lightGray, backgroundColor: UIColor.red)
cell.addCornerRadius(cornerRadius: 8)
return cell
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
let cellSpacing = CGFloat(2) //Define the space between each cell
let leftRightMargin = CGFloat(40) //If defined in Interface Builder for "Section Insets"
let numColumns = CGFloat(2) //The total number of columns you want
let totalCellSpace = cellSpacing * (numColumns - 1)
let screenWidth = UIScreen.main.bounds.width
let width = (screenWidth - leftRightMargin - totalCellSpace) / numColumns
let height = CGFloat(210) //whatever height you want
return CGSize(width: width, height: height) // width & height are the same to make a square cell
}
}
编辑:
我想我无法清楚地解释我的问题。在这里,我将提供一些额外的视频,以清楚地说明问题。我上传了2个视频。
在此视频中,我的标题不会与collectionview子项滚动。所以我想在屏幕上滚动整个元素。 (https://youtu.be/0ArQe6mZytc)
在这个简短的视频中,您可以在滚动时看到Pinterest App的行为。我想让我的应用像这个视频(https://youtu.be/Nm-sjXVEL5s)
答案 0 :(得分:4)
根据您的要求,无需使用UIScrollView
。您只需使用UICollectionView
即可创建屏幕。
要显示scrollable header
,您可以使用UICollectionReusableView
作为section header
的{{1}}。
1.UICollection视图代码:
collection view
<强> 2。接口强>
第3。输出屏幕:
修改强>
在https://www.raywenderlich.com/107439/uicollectionview-custom-layout-tutorial-pinterest
中提供的代码中进行一些更改:
import UIKit
class PinterestViewController: UIViewController
{
override func viewDidLoad()
{
super.viewDidLoad()
}
}
extension PinterestViewController : UICollectionViewDataSource, UICollectionViewDelegate
{
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int
{
return 25
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell
{
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "cell", for: indexPath)
return cell
}
func collectionView(_ collectionView: UICollectionView, viewForSupplementaryElementOfKind kind: String, at indexPath: IndexPath) -> UICollectionReusableView
{
if kind == UICollectionElementKindSectionHeader
{
let headerView = collectionView.dequeueReusableSupplementaryView(ofKind: UICollectionElementKindSectionHeader, withReuseIdentifier: "headerView", for: indexPath)
return headerView
}
return UICollectionReusableView()
}
}
extension PinterestViewController : UICollectionViewDelegateFlowLayout
{
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize
{
let cellSpacing = CGFloat(2) //Define the space between each cell
let leftRightMargin = CGFloat(40) //If defined in Interface Builder for "Section Insets"
let numColumns = CGFloat(2) //The total number of columns you want
let totalCellSpace = cellSpacing * (numColumns - 1)
let screenWidth = UIScreen.main.bounds.width
let width = (screenWidth - leftRightMargin - totalCellSpace) / numColumns
let height = CGFloat(210) //whatever height you want
return CGSize(width: width, height: height) // width & height are the same to make a square cell
}
}
同样在class PinterestLayout: UICollectionViewFlowLayout
{
//...
override func prepare()
{
// 1
if cache.isEmpty
{
//...
var yOffset = [CGFloat](repeating: 150, count: numberOfColumns) //Height of your header view
//...
}
}
override var collectionViewContentSize: CGSize
{
return CGSize(width: contentWidth, height: contentHeight)
}
override func layoutAttributesForElements(in rect: CGRect) -> [UICollectionViewLayoutAttributes]?
{
guard let attributes = super.layoutAttributesForElements(in: rect) else
{
return nil
}
var layoutAttributes = [UICollectionViewLayoutAttributes]()
for attr in attributes where attr.representedElementKind == UICollectionElementKindSectionHeader
{
if let supplementaryAttributes = layoutAttributesForSupplementaryView(ofKind: UICollectionElementKindSectionHeader, at: attr.indexPath)
{
layoutAttributes.append(supplementaryAttributes)
}
}
for attributes in cache
{
if attributes.frame.intersects(rect)
{
layoutAttributes.append(attributes)
}
}
return layoutAttributes
}
override func layoutAttributesForSupplementaryView(ofKind elementKind: String, at indexPath: IndexPath) -> UICollectionViewLayoutAttributes?
{
if elementKind == UICollectionElementKindSectionHeader
{
let attributes = UICollectionViewLayoutAttributes(forSupplementaryViewOfKind: UICollectionElementKindSectionHeader, with: indexPath)
attributes.frame = CGRect(x: 0, y: 0, width: self.contentWidth, height: 150) //Height of your header view
return attributes
}
return nil
}
}
:
答案 1 :(得分:1)
将NSLayoutConstraint作为集合视图的高度,并在viewdidLayoutSubviews()方法中更改该高度约束,如下所示。
self.hgtCollectionView.constant = CGFloat(number of rows) * 210) + CGFloat(10)
这将根据其内容更新集合视图的高度。
答案 2 :(得分:1)
答案 3 :(得分:0)
看起来您的解决方案只是打破了CollectionView的主要目的 - 保存应用程序内存并重用设备资源。但是在这里你可以使CollectionView的高度大于设备大小,这很糟糕。 如果你有1000张图片怎么办?你的应用程序只会因内存不足问题而崩溃。 使用自定义单元格和标题与collectionviewflowlayout子类。 例如,看看这个示例代码。 https://github.com/zwaldowski/AdvancedCollectionView
我观看了Pinterest应用,但没有在那里找到任何标题。 你需要什么样的自定义标题? 它应该有什么行为? 你需要几个部分的粘性标题,还是它应该与细胞一起消失?
看一下本教程 https://www.objc.io/issues/3-views/collection-view-layouts/
您应用的部署目标是什么?如果你需要iOS 9,那么UICollectionViewFlowLayout sectionHeadersPinToVisibleBounds属性。
答案 4 :(得分:0)
不要使用图片查看侧边集合视图,只需使用 UICollectionReusableView 作为标题
将此添加到您的班级
override func collectionView(_ collectionView: UICollectionView,
viewForSupplementaryElementOfKind kind: String, at indexPath: IndexPath) -> UICollectionReusableView {
//1
switch kind {
//2
case UICollectionElementKindSectionHeader:
//3
let headerView = collectionView.dequeueReusableSupplementaryView(ofKind: kind, withReuseIdentifier: "customHeaderView", for: indexPath) as! customHeaderView
headerView.imageView.image = //some random image local or dynamic you can use here..
return headerView
default:
//4
assert(false, "Unexpected element kind")
}
}
您的标题类应如下所示
class customHeaderView: UICollectionReusableView {
@IBOutlet weak var imageView: UIImageView!
//you can add more functions here you want
}
答案 5 :(得分:0)
对于您的信息,UICollectionView已经是UIScrollView的子类。无需再次将其添加到UIScrollView。
以下是层次结构:
<强> UICollectionView-&GT; UIScrollView-&GT; UIView-&GT; UIResponder-&GT; NSObjec吨强>