当UICollectionView嵌套在UITableVIew中时,无法进行选择

23

我有一个包含UICollectionViewUITableView

我可以垂直滚动UITableView,并水平滚动嵌套的UICollectionView,但是我无法选择UICollectionView中的UICollectionViewCell

UITableView禁用了选择功能,而UICcollectionView启用了(默认状态下)。

UICollectionViewcollectionView:didSelectItemAtIndexPath:从未被调用。


UICollectionViewDelegate已设置吗? - Sean Kladek
集合视图中的单元格是否有任何点击响应(例如变暗或类似的效果)?也许UITableView的单元格正在取消集合视图的点击。 - gabriel_vincent
3
约翰,你解决这个问题了吗? - Dave Haigh
你找到解决方案让它工作了吗?水平和垂直滚动的组合总是一个问题,因为每个UIScrollView都有自己的行为,而一起使用时响应性不太好,我对解决方案很感兴趣! - Alex Cio
9个回答

0
我解决这个问题的方法是在单元格中添加一个轻拍手势识别器来手动处理点击,而不是依赖于未被调用的didSelectRowAtIndexPath方法:

Swift

let tapRecognizer = UITapGestureRecognizer(target: self, action: "cellTapped:")
tapRecognizer.numberOfTapsRequired = 1
cell.addGestureRecognizer(tapRecognizer)

Objective-C

UITapGestureRecognizer *tapRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(cellTapped:)];
tapRecognizer.numberOfTapsRequired = 1;
[cell addGestureRecognizer:tapRecognizer];

现在你可以在 cellTapped: 方法中处理单元格被点击的事件,并且通过 tapRecognizer.view 获取到被点击的单元格的引用。

0

我刚刚让这个工作起来了,所以我想和大家分享我的解决方案。

在为UITableView和嵌套的UICollectionView设置必要的代理和数据源之后,您可以像这样将您的UICollectionView设为第一个可选择的视图

- (UITableViewCell *) tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath  {
    ...
    [tableViewCell bringSubviewToFront:tableViewCell.yourCollectionView];
    return cell;
}

这将使得通过代理选择的第一件事情是UICollectionView

- (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath; 

使用UITableView代理选择视图的任何其他部分

- (UITableViewCell *) tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath;

希望这能帮到你!


0

在视图控制器中

import UIKit

class ViewController: UIViewController {
    
    @IBOutlet weak var tableView: UITableView!{
        didSet{
            tableView.delegate = self
            tableView.dataSource = self
            tableView.register(UINib(nibName: "TableViewCell", bundle: nil), forCellReuseIdentifier: TableViewCell.cellId)
        }
    }
    
    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view.
    }
}

extension ViewController : UITableViewDelegate, UITableViewDataSource {
    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return 5
    }
    
    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell =  tableView.dequeueReusableCell(withIdentifier: TableViewCell.cellId, for: indexPath) as! TableViewCell
        return cell
    }
}

在TableViewCell文件中

import UIKit

class TableViewCell: UITableViewCell {
    
    static let cellId = "TableViewCell"
    
    @IBOutlet weak var collectionView: UICollectionView!  {
        didSet{
            collectionView.delegate = self
            collectionView.dataSource = self
            collectionView.register(UINib(nibName: "CollectionViewCell", bundle: nil), forCellWithReuseIdentifier: CollectionViewCell.cellId)
        }
    }
    

    override func awakeFromNib() {
        super.awakeFromNib()
        // Initialization code
    }

    override func setSelected(_ selected: Bool, animated: Bool) {
        super.setSelected(selected, animated: animated)
        
        // Configure the view for the selected state
    }
}


extension TableViewCell : UICollectionViewDelegate, UICollectionViewDataSource {
    
    func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
        return 5
    }
    
    
    func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
        let cell = collectionView.dequeueReusableCell(withReuseIdentifier: CollectionViewCell.cellId, for: indexPath) as! CollectionViewCell
        cell.labelThing.text = "samples text"
        return cell
    }
    
    func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
        print("Hello world")
    }
}

在CollectionView文件中

import UIKit

class CollectionViewCell: UICollectionViewCell {
    
    static let cellId = "CollectionViewCell"

    @IBOutlet weak var labelThing: UILabel!
    
    override func awakeFromNib() {
        super.awakeFromNib()
        // Initialization code
    }

}

0
所有在自定义UITableViewCell中的视图都应该相对于contentView进行布局。因此,始终将它们作为contentView的子视图添加,并确保选择功能正常工作。
class CustomTableViewCell: UITableViewCell {
    override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
        super.init(style: style, reuseIdentifier: reuseIdentifier)

        let view = UIView()
        contentView.addSubview(view)

        // layout
    }

    required init?(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
}

-1

首先请检查您是否提供了必要的数据源和委托。如果您正在使用集合视图在特定数量的表格视图单元格上,您可以直接将其放在原型单元格中。请确保您的单元格具有适当的限制(宽度)。


-1

我的第一反应是两个视图之间的手势识别器可能会发生冲突

更具体地说,UITableView的GR(手势识别器)可能会阻止UICollectionView GRs接收触摸事件


-1
尝试禁用tableViewdelaysContentTouches,并确保您的集合视图的delegate已正确设置。

-1

我已经使用Storyboard和编程方式进行了测试,它按照预期工作。根据所点击的区域,我会收到collectionView:didSelectItemAtIndexPath:或tableView:didSelectRowAtIndexPath。看来至少在较新的SDK(我的是11.4)中,这个问题得到了解决。


-3

这应该不是问题!不需要自定义手势识别器。也不需要禁用tableview的选择。

请确保:

  1. 在Storyboard或代码中设置您的tableview并设置其数据源和委托
  2. 在cellforrowatindexpath中,获取对应collectionview的引用(dequeuing tableviewcell后),并设置其(collectionviews)数据源和委托
  3. 实现tableviews和collectionviews delegate didselect方法,并记录它们的调用以查看是否有效

我在回答之前实现了一个小示例项目,以确保没有问题。如果仍然无法正常工作,我可以上传它!

祝你好运!


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接