我正在使用Swift为我工作的医院构建一个iOS应用程序。
不知何故,在一个特定的特性中,我必须在UICollectionViewCell中放入一个UICollectionView。我想要实现的是,对于父UICollectionView的每个内容(垂直滚动),都会有几个子项(可以水平滚动),具体取决于父行。
为了说明,我必须显示医生的列表(姓名和照片),然后我必须在他们的姓名和照片下面显示他们的每个实践时间表。实习时间表将根据每个医生的不同而有所不同。因此,我必须将其放入UICollectionView中。
我已经尝试了几个我在网上找到的解决方案,但我仍然无法接近它。
我不能解决的最大问题是:我不知道在代码中哪里可以加载子数据源(doctor schedule),也不知道何时可以加载它,因为我不能拥有下面这样的两个函数:
collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell这就是我想要实现的目标

UIImage和医生姓名(UILabel)在父UICollectionViewCell中(垂直滚动),然后框中的所有内容(练习日和练习时间)都是子UICollectionView (水平滚动)
PS:有很多医生,每个医生都有几天的实习时间。
请教我怎么做
发布于 2017-06-18 21:08:36
如果你真的想在collectionViewCell中插入一个collectionView,那么有一个非常简单的步骤。创建一个UICollectionView实例并将其添加到collectionViewCell。如果你愿意,你可以使用这个例子。
//
// 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")
}
}

发布于 2019-03-11 13:19:50
这可能有点晚了,但对于仍在努力寻找答案的人来说。
经过一些研究和挖掘,我偶然发现了几个帖子,说明了为什么你不应该让你的细胞作为你的collectionView的代表。所以,我迷失了方向,因为我找到的几乎所有解决方案都是这样做的,直到我最终找到了我认为最好的嵌套collectionViews的方法。
为了提供一些背景知识,我的应用程序在另一个collectionViews的不同单元格中不仅包含了一个,而且包含了两个collectionView,所以使用标记和所有这些来设置委托并不是最好的方法,也不是正确的OO解决方案。
因此,最好的方法是:
首先,您必须创建一个不同的类作为内部collectionView的委托。我是这样做的:
class InnerCollectionViewDelegate: NSObject, UICollectionViewDataSource, UICollectionViewDelegate, UICollectionViewDelegateFlowLayout {
// CollectionView and layout delegate methods here
// sizeForItemAt, cellForItemAt, etc...
}现在,在内部collectionView (更确切地说,是内部collectionView所在的单元格)中创建一个允许您设置其委托的函数
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的委托
var innerDelegate = InnerCollectionViewDelegate()然后
override func collectionView(_ collectionView: UICollectionView, willDisplay cell: UICollectionViewCell, forItemAt indexPath: IndexPath) {
if let cell = cell as? InnerCell {
cell.setCollectionViewDataSourceDelegate(dataSourceDelegate: innerDelegate)
}
}这可能并不完美,但至少您分离了关注点,因为您的单元不应该是代表。记住,你的单元格应该只负责显示信息,而不是试图计算出collectionView的大小,等等。
我确实找到了类似的答案,涉及设置collectionViews标签和诸如此类的东西,但我发现这使得单独处理每个collectionView变得更加困难,而且处理标签不会导致意大利面代码或意外行为。
我遗漏了单元的注册和出列,但我相信你们都很熟悉这一点。如果没有,请让我知道,我会试着告诉你。
发布于 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解释了这个问题。
https://stackoverflow.com/questions/44614743
复制相似问题