首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >在UICollectionViewCell中添加UICollectionView

在UICollectionViewCell中添加UICollectionView
EN

Stack Overflow用户
提问于 2017-06-18 20:00:51
回答 4查看 12.9K关注 0票数 4

我正在使用Swift为我工作的医院构建一个iOS应用程序。

不知何故,在一个特定的特性中,我必须在UICollectionViewCell中放入一个UICollectionView。我想要实现的是,对于父UICollectionView的每个内容(垂直滚动),都会有几个子项(可以水平滚动),具体取决于父行。

为了说明,我必须显示医生的列表(姓名和照片),然后我必须在他们的姓名和照片下面显示他们的每个实践时间表。实习时间表将根据每个医生的不同而有所不同。因此,我必须将其放入UICollectionView中。

我已经尝试了几个我在网上找到的解决方案,但我仍然无法接近它。

我不能解决的最大问题是:我不知道在代码中哪里可以加载子数据源(doctor schedule),也不知道何时可以加载它,因为我不能拥有下面这样的两个函数:

代码语言:javascript
运行
复制
collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell

这就是我想要实现的目标

UIImage和医生姓名(UILabel)在父UICollectionViewCell中(垂直滚动),然后框中的所有内容(练习日和练习时间)都是子UICollectionView (水平滚动)

PS:有很多医生,每个医生都有几天的实习时间。

请教我怎么做

EN

回答 4

Stack Overflow用户

回答已采纳

发布于 2017-06-18 21:08:36

如果你真的想在collectionViewCell中插入一个collectionView,那么有一个非常简单的步骤。创建一个UICollectionView实例并将其添加到collectionViewCell。如果你愿意,你可以使用这个例子。

代码语言:javascript
运行
复制
//
//  ViewController.swift
//  StackOverFlowAnswer
//
//  Created by BIKRAM BHANDARI on 18/6/17.
//  Copyright © 2017 BIKRAM BHANDARI. All rights reserved.
//

import UIKit

class ViewController: UIViewController, UICollectionViewDelegate, UICollectionViewDataSource, UICollectionViewDelegateFlowLayout {

    let cellId = "CellId"; //Unique cell id

    override func viewDidLoad() {
        super.viewDidLoad()
        view.backgroundColor = .red; //just to test

        collectionView.register(Cell.self, forCellWithReuseIdentifier: cellId) //register collection view cell class
        setupViews(); //setup all views
    }

    func setupViews() {

        view.addSubview(collectionView); // add collection view to view controller
        collectionView.delegate = self; // set delegate
        collectionView.dataSource = self; //set data source

        collectionView.leftAnchor.constraint(equalTo: view.leftAnchor).isActive = true; //set the location of collection view
        collectionView.rightAnchor.constraint(equalTo:  view.rightAnchor).isActive = true; // top anchor of collection view
        collectionView.heightAnchor.constraint(equalTo: view.heightAnchor).isActive = true; // height
        collectionView.widthAnchor.constraint(equalTo: view.widthAnchor).isActive = true; // width

    }

    let collectionView: UICollectionView = { // collection view to be added to view controller
        let cv = UICollectionView(frame: .zero, collectionViewLayout: UICollectionViewFlowLayout()); //zero size with flow layout
        cv.translatesAutoresizingMaskIntoConstraints = false; //set it to false so that we can suppy constraints
        cv.backgroundColor = .yellow; // test
        return cv;
    }();

    //deque cell
    func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
        let cell = collectionView.dequeueReusableCell(withReuseIdentifier: cellId, for: indexPath);
//        cell.backgroundColor = .blue;
        return cell;
    }

    // number of rows
    func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
        return 5;
    }

    //size of each CollecionViewCell
    func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
        return CGSize(width: view.frame.width, height: 200);
    }
}

// first UICollectionViewCell
class Cell: UICollectionViewCell, UICollectionViewDataSource, UICollectionViewDelegate, UICollectionViewDelegateFlowLayout {

    let cellId = "CellId"; // same as above unique id

    override init(frame: CGRect) {
        super.init(frame: frame);

        setupViews();
        collectionView.register(UICollectionViewCell.self, forCellWithReuseIdentifier: cellId); //register custom UICollectionViewCell class.
        // Here I am not using any custom class

    }


    func setupViews(){
        addSubview(collectionView);

        collectionView.delegate = self;
        collectionView.dataSource = self;

        collectionView.leftAnchor.constraint(equalTo: leftAnchor).isActive = true;
        collectionView.rightAnchor.constraint(equalTo: rightAnchor).isActive = true;
        collectionView.topAnchor.constraint(equalTo: topAnchor).isActive = true;
        collectionView.bottomAnchor.constraint(equalTo: bottomAnchor).isActive = true;
    }

    let collectionView: UICollectionView = {
        let layout = UICollectionViewFlowLayout();
        layout.scrollDirection = .horizontal; //set scroll direction to horizontal
        let cv = UICollectionView(frame: .zero, collectionViewLayout: layout);
        cv.backgroundColor = .blue; //testing
        cv.translatesAutoresizingMaskIntoConstraints = false;
        return cv;
    }();

    func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
        let cell = collectionView.dequeueReusableCell(withReuseIdentifier: cellId, for: indexPath);
        cell.backgroundColor = .red;
        return cell;
    }

    func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
        return 5;
    }

    func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
        return CGSize(width: self.frame.width, height: self.frame.height - 10);
    }
    required init?(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
}

票数 11
EN

Stack Overflow用户

发布于 2019-03-11 13:19:50

这可能有点晚了,但对于仍在努力寻找答案的人来说。

经过一些研究和挖掘,我偶然发现了几个帖子,说明了为什么你不应该让你的细胞作为你的collectionView的代表。所以,我迷失了方向,因为我找到的几乎所有解决方案都是这样做的,直到我最终找到了我认为最好的嵌套collectionViews的方法。

为了提供一些背景知识,我的应用程序在另一个collectionViews的不同单元格中不仅包含了一个,而且包含了两个collectionView,所以使用标记和所有这些来设置委托并不是最好的方法,也不是正确的OO解决方案。

因此,最好的方法是:

首先,您必须创建一个不同的类作为内部collectionView的委托。我是这样做的:

代码语言:javascript
运行
复制
class InnerCollectionViewDelegate: NSObject, UICollectionViewDataSource, UICollectionViewDelegate, UICollectionViewDelegateFlowLayout {
 // CollectionView and layout delegate methods here
 // sizeForItemAt, cellForItemAt, etc...
}

现在,在内部collectionView (更确切地说,是内部collectionView所在的单元格)中创建一个允许您设置其委托的函数

代码语言:javascript
运行
复制
class InnerCell: UICollectionViewCell {

    var collectionView: UICollectionView

    init() {
        let layout = UICollectionViewFlowLayout()
        collectionView = UICollectionView(frame: CGRect(x: 0, y: 0, width: frame.width, height: frame.height), collectionViewLayout: layout)
     }

    func setCollectionViewDataSourceDelegate(dataSourceDelegate: UICollectionViewDataSource & UICollectionViewDelegate) {
            collectionView.delegate = dataSourceDelegate
            collectionView.dataSource = dataSourceDelegate
            collectionView.reloadData()
    }
}

最后,在拥有最外层(主) collectionView的ViewController中,执行以下操作:

首先实例化内部collectionView的委托

代码语言:javascript
运行
复制
var innerDelegate = InnerCollectionViewDelegate()

然后

代码语言:javascript
运行
复制
override func collectionView(_ collectionView: UICollectionView, willDisplay cell: UICollectionViewCell, forItemAt indexPath: IndexPath) {
        if let cell = cell as? InnerCell {
            cell.setCollectionViewDataSourceDelegate(dataSourceDelegate: innerDelegate)
        }
}

这可能并不完美,但至少您分离了关注点,因为您的单元不应该是代表。记住,你的单元格应该只负责显示信息,而不是试图计算出collectionView的大小,等等。

我确实找到了类似的答案,涉及设置collectionViews标签和诸如此类的东西,但我发现这使得单独处理每个collectionView变得更加困难,而且处理标签不会导致意大利面代码或意外行为。

我遗漏了单元的注册和出列,但我相信你们都很熟悉这一点。如果没有,请让我知道,我会试着告诉你。

票数 4
EN

Stack Overflow用户

发布于 2017-06-18 20:14:16

有多种方法可以解决水平集合在另一个垂直列表集合中的问题。

最简单的方法是使您呈现的ViewController成为dataSouce的主UICollectionView,并委托这两个集合视图。您可以将单元内的集合视图设置为从此处提供服务。

This article about placing collection view inside a table view以一种非常详细的方式和the code for the same can be found here解释了这个问题。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/44614743

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档