Выбор невозможен, когда UICollectionView вложен в UITableVIew

У меня есть UITableView где каждая клетка содержит UICollectionView,

Я могу прокрутить UITableView вертикально и прокручивать вложенные UICollectionView по горизонтали, однако я не могу выбрать UICollectionViewCell в UICollectionView,

Выбор отключен в UITableViewи включен (состояние по умолчанию) в UICcollectionView,

UICollectionView'scollectionView:didSelectItemAtIndexPath: просто никогда не звонил.

9 ответов

Все просмотры, которые у вас есть в кастомном UITableViewCellдолжны быть размещены относительно формата. Поэтому всегда добавляйте их как подвид к 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")
    }
}

Я только что заработал, поэтому решил, что поделюсь своим решением с вами, ребята.

После настройки необходимых делегатов и источников данных для 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;

Надеюсь это поможет!

Я смог решить эту проблему, добавив в ячейку распознаватель жестов касания, чтобы обрабатывать касание вручную, а не полагаться на didSelectRowAtIndexPath который не вызывается:

стриж

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,

В представленииконтроллере

      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
    }

}

Попробуй отключить delaysContentTouches за tableView и убедитесь, что delegate для вашей коллекции представления установлены правильно.

Я проверил как с раскадровкой, так и программно, и он работает, как ожидалось. Я получаю collectionView: didSelectItemAtIndexPath: или tableView: didSelectRowAtIndexPath в зависимости от нажатой области. Кажется, что, по крайней мере, в более новых SDK (у меня это 11.4), это исправлено.

Мой первый инстинкт заключается в том, что распознаватели жестов между двумя представлениями могут конфликтовать

более конкретно, GR UITableView для ответвления могут препятствовать получению касаний GR UICollectionView.

Сначала проверьте, пожалуйста, вы предоставили необходимый источник данных и делегатов. Затем, если вы используете коллекционное представление для определенного количества ячеек табличного представления, вы можете напрямую поместить его в ячейку прототипа. Пожалуйста, убедитесь, что ваша ячейка имеет надлежащие пределы (ширина)

Это не должно быть проблемой вообще! не нужны специальные распознаватели жестов. нет необходимости отключать выбор таблицы.

обязательно:

  1. настроить табличное представление в раскадровке или коде и установить его источник данных и делегировать
  2. в cellforrowatindexpath после освобождения ячейки tableview получите ссылку на соответствующий view collection и установите его источник данных (collectionviews) и делегата
  3. реализовывать методы tablesev и collectionviews делегата didselect и регистрировать их вызовы, чтобы увидеть, как это работает

Я просто реализовал небольшой пример проекта, прежде чем написал этот ответ, чтобы убедиться, что нет проблем. Я могу загрузить его, если он все еще не работает для вас!

удачи!

Другие вопросы по тегам