collectionView 中的 Horizo​​ntal ScrollView 功能松散

Posted

技术标签:

【中文标题】collectionView 中的 Horizo​​ntal ScrollView 功能松散【英文标题】:Horizontal ScrollView in collectionView loose functionality 【发布时间】:2017-09-28 04:45:52 【问题描述】:

我有一个包含不同单元格的集合视图。一个单元格是带有元素的水平scrollViewscrollview 与“App Store”-App 或其他中的功能非常相似。

在第一个初始化中,它按预期工作,但是当我在 collectionView 中向下滚动到最后,然后滚动回我的水平 scrollView 时,contentSize 似乎是错误的。因此,当scrollView 单元重新初始化时,滚动视图就像被禁用。

奇怪的是,当我设置一个固定的contentSize 宽度时,它总是像预期的那样工作。

//calucalte width
var scrollViewWidth:CGFloat = 0
scrollViewWidth = CGFloat(allSkills.count)*scrollViewHeight

cell.skillsScrollView.alwaysBounceVertical = false
cell.skillsScrollView.alwaysBounceHorizontal = false
cell.skillsScrollView.frame = CGRect(x: 0, y: 0, width: scrollViewWidth, height: scrollViewHeight)

for (i,imagelink) in imagelinks.enumerated() 
let imageView:UIImageView = UIImageView(frame: CGRect(x: 0, y: 0, width: scrollViewHeight, height: scrollViewHeight)) //image is square height and width of scrollView

//set images in 
if i == 0 
    imageView.frame = CGRect(x: 0, y: 0, width: scrollViewHeight, height: scrollViewHeight)
 else 
    imageView.frame = CGRect(x: CGFloat(i)*scrollViewHeight, y: 0, width: scrollViewHeight, height: scrollViewHeight)


//set image in ImageValue
//[...]

cell.skillsScrollView.addSubview(imageView)


cell.skillsScrollView.contentSize = CGSize(width: scrollViewWidth, height: scrollViewHeight) // fixed width = 1000  works like expected but it's too width
return cell

我的细胞真的很乏味。

class MySkills: UICollectionViewCell 

@IBOutlet weak var titleLabel: UILabel!

@IBOutlet weak var contentSkillsUIView: UIView!
@IBOutlet weak var skillsScrollView: UIScrollView!

所以我真的对这种行为感到困惑。我试图在awakeFromNib 中设置宽度。我设置了单元格外的宽度。我在viewWillAppear 中初始化我的collectionView,并在viewDidLoad 中设置我的宽度。在prepareForReuse 中,我也将contentSize 设置为0。一切都没有改变。

当我打印 scrollViewWidth 时,它始终具有预期值。

所以我很感谢你的想法。

【问题讨论】:

可以分享演示项目吗? 你在storyBoard中设置了这个collectionView了吗?如果你有,那么我可以帮助你,否则我真的不知道如何以编程方式做事情建议尝试以编程方式为宽度添加一个 NSConstraint(你必须在其他地方做更多的研究) 【参考方案1】:

要正确制作集合视图,需要一长串步骤

我会尽量说清楚,所以请耐心等待

-GUIDE-

所以假设您希望根据一些变量和数组中的一些存储数据使所有单元格不同,让我们开始工作吧,因为我们有很多

第 1 步。

打开你的故事板,在你想要添加这个 collectionView 的 ViewController 中创建一个新的 .swift 文件并将这些东西添加到其中

import Foundation
import UIKit

class YourViewController: UIViewController, UICollectionViewDelegate, UICollectionViewDataSource  


(假设您熟悉创建类并将这些类绑定到 ViewControllers)

第 2 步。

在故事板中导航到右侧属性检查器选项卡上的身份检查选项卡,并将您的 viewController 设置为我们刚刚创建的类

第 3 步。

现在在底部,您要找到一个 collectionView 并将其拖到您选择的 viewController 上(确保它是一个集合视图而不是一个集合视图控制器

第 4 步。

在这里您可以设置单元格的大小和每个单元格之间的间距等(在属性检查器中)

第 5 步。

一旦你拥有了你想要的一切,你就想为这个新创建的 collectionView 添加一些约束

-在容器中水平添加一个中心

-在视图控制器的边缘添加一个尾随/前导约束

-在容器中垂直添加一个中心

第 6 步。

现在 collectionView 已经设置好了,你需要做一些编码工作

按住控制并从collectionView(不是collectionViewCell)拖动 到 viewController(在左侧或三个符号所在的 viewController 顶部)添加弹出的 delegate 和 datasource 选项(如果你不这样做,这些很重要这样做不会起作用)

第 7 步。

打开助手编辑器并按住控制并单击并从 collectionView 拖动到您的 viewController 类文件,使其成为 @IBOutlet 并将其命名为您想要的任何名称,您应该拥有类似这样的内容

class YourViewController: UIViewController, UICollectionViewDelegate, UICollectionViewDataSource  

    @IBOutlet weak var YourCollectionView: UICollectionView!



第 8 步。

现在是时候创建一个新文件并选择 cocoa touch class

确保您将其作为 UICollectionViewCell 类型的子类,然后单击 同时创建 XIB 文件复选框,您可以随意命名

第 9 步。

现在已经没有时间进行设置所需的其他一些事情了,转到 yourViewController 类文件并将此位添加到其中

override func viewDidLoad() 
    super.viewDidLoad()

    //or whatever you named the @IBOutlet earlier
    YourCollectionView.register(UINib(nibName: "CollectionViewCell", bundle: nil), forCellWithReuseIdentifier: "CollectionViewCell")
    // Do any additional setup after loading the view.

现在如果你现在构建并运行应用程序将会崩溃,那是因为我们之前创建的 CollectionViewCell 没有被赋予重用标识符

将此头部修复到您刚刚创建的 CollectionViewCell XIB 并在右侧(确保在执行此操作之前选择 CollectionViewCell 否则您将看不到任何内容)

在顶部添加一个重用标识符,随心所欲地命名它,但请确保它的相关头部回到你的 viewController 文件中的 didmove(toview: _) 方法的这一行

YourCollectionView.register(UINib(nibName: "CollectionViewCell", bundle: nil), forCellWithReuseIdentifier: "CollectionViewCell")

确保 forCellWithReuseIdentifier 字符串与您刚刚在 XIB 单元格中输入的重用标识符相同

第 10 步。

现在您可以在 XIB 文件中自定义您的单元格(您可以更改大小并添加图像和标签等),然后打开 CollectionViewCell XIB 的助理编辑器和 @IBOutlet 您添加到的每个标签/图像单元格为它们提供相关名称,以便您以后轻松引用

第 11 步。

回到你的 viewController 文件并在顶部创建一个这样的结构

struct cellData 
    //here you need to create a *let instance* for every image/label you have in your CollectionViewCell XIB 

    //this is neccesary for determining how to seperate the cells
    let cell : Int!
    //labels will not be declared as a UILabel but as a String like this
    let label : String!
    //images will be declared like this
    let Image : UIImage!



class YourViewController: UIViewController, UICollectionViewDelegate, UICollectionViewDataSource  

第 12 步。

现在我们已经完成了设置,我们现在必须进入代码的自定义部分

在你的类中创建一个空数组

class YourViewController: UIViewController, UICollectionViewDelegate, UICollectionViewDataSource  


    @IBOutlet weak var YourCollectionView: UICollectionView!

    /* array here */
    var array = [] 

    override func viewDidLoad() 
    super.viewDidLoad()

    YourCollectionView.register(UINib(nibName: "CollectionViewCell", bundle: nil), forCellWithReuseIdentifier: "CollectionViewCell")
    // Do any additional setup after loading the view.
    


像这样用结构中的数据填充数组

var array = [cellData(cell : 1,label : "",image : UIImage(named: ""))]

好的,让我们看一下这里,我们在结构中声明所有不同的标签和图像(您放置在 CollectionViewCell XIB 中的每个标签或图像都应该有一个标签或一个图像)

现在是时候使用 collectionView 的功能了

第 13 步。

您可能一直遇到错误,但我们即将修复它

将这 3 个函数添加到您的 viewController 函数中

func numberOfSections(in collectionView: UICollectionView) -> Int 
    return 1

func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int 
    return array.count

func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell 


-numberOfSections 表示你想要多少个不同的单元格部分

-numberOfItemsInSection 表示您的部分中需要多少个单元格

第 14 步。

collectionView 是一个函数,用于确定要在其中添加此代码的每个单元格中显示的内容

 if array[indexPath.row].cell == 1 
        //make sure this is the reuse identifier that you have set in your CollectionViewCell XIB
        let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "CollectionViewCell", for: indexPath) as! CollectionViewCell

        cell.image.image = array[indexPath.row].image
        cell.label.text = array[indexPath.row].label

        return cell
     else 
         let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "CollectionViewCell", for: indexPath) as! CollectionViewCell

        return cell
    

第 15 步。

也就是说,如果你想添加更多具有不同数据的单元格,只需将更多的单元格放入你的数组中

var array = [cellData(cell : 1,label : "",image : UIImage(named: "")),
             cellData(cell : 2,label : "",image : UIImage(named: "")),
             cellData(cell : 3,label : "",image : UIImage(named: ""))]

然后确保它与您的 collectionView 函数一起加载

if array[indexPath.row].cell == 1 
        //make sure this is the reuse identifier that you have set in your CollectionViewCell XIB
        let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "CollectionViewCell", for: indexPath) as! CollectionViewCell

        cell.image.image = array[indexPath.row].image
        cell.label.text = array[indexPath.row].label

        return cell
     
    if array[indexPath.row].cell == 2 
        //make sure this is the reuse identifier that you have set in your CollectionViewCell XIB
        let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "CollectionViewCell", for: indexPath) as! CollectionViewCell

        cell.image.image = array[indexPath.row].image
        cell.label.text = array[indexPath.row].label

        return cell
    
    if array[indexPath.row].cell == 3 
        //make sure this is the reuse identifier that you have set in your CollectionViewCell XIB
        let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "CollectionViewCell", for: indexPath) as! CollectionViewCell

        cell.image.image = array[indexPath.row].image
        cell.label.text = array[indexPath.row].label

        return cell
     else 
         let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "CollectionViewCell", for: indexPath) as! CollectionViewCell

        return cell
    

确保在您的数组中将 cell Int 设置为增加 Integer 值,否则单元格也不会加载以自定义每个单元格中的数据,只需填写数组中的空白即可

var array = [cellData(cell : 1,label : "Blank here",image : UIImage(named: "Blank here"))]

如果您有任何问题,请发表评论

【讨论】:

以上是关于collectionView 中的 Horizo​​ntal ScrollView 功能松散的主要内容,如果未能解决你的问题,请参考以下文章

如何在 CollectionView.Footer 中设置 XAML 按钮大小?

Horizo​​ntalScrollView 中的自定义视图不滚动

如何启用不在视图中的 Horizo​​ntalScrollView 中的特定按钮

leanback 库:如何为 VerticalGridView 或 Horizo​​ntalGridView 中的项目绘制焦点?

Horizo​​ntalPager 中的额外填充

包装在 Horizo​​ntalScrollView 中的 Android Listview 高度不正确,其中列表项的高度不同