Подтвердить что ты не робот

UICollectionView Выберите и снимите флажок

Итак, у меня есть основной объект, у которого есть много изображений, связанных с ним. Изображение также является объектом.

Скажите, что у вас есть контроллер представления коллекции, и в этом контроллере у вас есть

cellForItemAtIndexPath

основанный на главном объекте, если у него есть текущее изображение, связанное с ним, я хочу установить значение selected в true. Но я хочу, чтобы пользователь мог "отменить" эту текущую ячейку в любое время, чтобы удалить ее связь с основным объектом.

Я считаю, что если вы установите "selected to true" - если есть связь между основным объектом и изображением в cellForItemAtIndexPath, отмена выбора больше не является опцией.

в

didDeselectItemAtIndexPath

и

didSelectItemAtIndexPath

Я тестирую журнал, чтобы узнать, вызваны ли они. Если ячейка настроена на выбранную - nether вызывается, но если я никогда не устанавливал ячейку для выбора в cellForItemAtIndexPath, я могу выбрать и отменить выбор всего, что я хочу.

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

Это также показывает, что контроллер настроен правильно и использует соответствующие методы делегата.... hmmmm

4b9b3361

Ответ 1

У меня была та же проблема, т.е. установите cell.selected = YES в [UICollectionView collectionView:cellForItemAtIndexPath:], затем не сможете отменить выбор ячейки, нажав на нее.

Решение на данный момент: я вызываю как [UICollectionViewCell setSelected:], так и [UICollectionView selectItemAtIndexPath:animated:scrollPosition:] в [UICollectionView collectionView:cellForItemAtIndexPath:].

Ответ 2

У вас есть собственный метод setSelected в вашем классе Cell? Вы вызываете [super setSelected:selected] в этом методе?

У меня была таинственная проблема, когда я использовал множественный выбор, я не мог отменить выбор клеток после их выбора. Вызов метода супер устранил проблему.

Ответ 3

У меня была проблема с выбором UICollectionView, и я обнаружил, что не допускаю множественного выбора в collectionView. Поэтому, когда я тестировал, я всегда старался в одной и той же ячейке, и если один выбор включен, вы не можете отменить выбор уже выбранной ячейки.

Мне пришлось добавить:

myCollectionView.allowsMultipleSelection = YES;

Ответ 4

Это своего рода старый, но, так как я сталкиваюсь с той же проблемой, используя swift, я добавлю свой ответ. При использовании:

 collectionView.selectItemAtIndexPath(indexPath, animated: true, scrollPosition: [])

Ячейка не была выбрана вообще. Но при использовании:

cell.selected = true

Он был выбран, но я больше не мог выбирать/отменять выделение.

Мое решение (используйте оба метода):

cell.selected = true
collectionView.selectItemAtIndexPath(indexPath, animated: true, scrollPosition: .None)

При вызове этих двух методов:

func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell

Это сработало отлично!

Ответ 5

Я не знаю, почему UICollectionView настолько беспорядочен, как это по сравнению с UITableViewController... Несколько вещей, которые я узнал.

Причина, по которой setSelected: вызывается несколько раз, вызвана вызванными методами последовательности. Последовательность очень похожа на последовательность методов UITextFieldDelegate.

Метод collectionView:shouldSelectItemAtIndexPath: вызывается до того, как collectionView действительно выбирает ячейку, потому что она действительно запрашивает "следует ли ее выбрать"?

collectionView:didSelectItemAtIndexPath: фактически вызывается после того, как collectionView выбирает ячейку. Следовательно, имя "сделал выбор".

Итак, это то, что происходит в вашем случае (и мой случай, и мне пришлось бороться за это время).

Выбранная ячейка снова коснется пользователя, чтобы отменить выбор. Вызывается shouldSelectItemAtIndexPath:, чтобы проверить, следует ли выбирать ячейку. collectionView выбирает ячейку, а затем вызывается didSelectItemAtIndexPath. Независимо от того, что вы делаете в этот момент, после свойства ячейки selected установлено значение YES. Что-то вроде cell.selected = !cell.selected не будет работать.

TL; DR - отмените выделение collectionView ячейки в методе делегата collectionView:shouldSelectItemAtIndexPath:, вызвав deselectItemAtIndexPath:animated: и верните NO.

Короткий пример того, что я сделал:

- (BOOL)collectionView:(OPTXListView *)collectionView shouldSelectItemAtIndexPath:(NSIndexPath *)indexPath {
    NSArray *selectedItemIndexPaths = [collectionView indexPathsForSelectedItems];

    if ([selectedItemIndexPaths count]) {
        NSIndexPath *selectedIndexPath = selectedItemIndexPaths[0];

        if ([selectedIndexPath isEqual:indexPath]) {
            [collectionView deselectItemAtIndexPath:indexPath animated:YES];

            return NO;
        } else {
            [collectionView selectItemAtIndexPath:indexPath animated:YES scrollPosition:UICollectionViewScrollPositionCenteredHorizontally];

            return YES;
        }
    } else {
        [collectionView selectItemAtIndexPath:indexPath animated:YES scrollPosition:UICollectionViewScrollPositionCenteredHorizontally];

        return YES;
    }
}

Ответ 6

Вот мой ответ для Swift 2.0.

Мне удалось установить следующее в viewDidLoad()

collectionView.allowsMultipleSelection = true;

то я реализовал эти методы

func collectionView(collectionView: UICollectionView, didSelectItemAtIndexPath indexPath: NSIndexPath) {
    let cell = collectionView.cellForItemAtIndexPath(indexPath) as! MyCell
    cell.toggleSelected()
}

func collectionView(collectionView: UICollectionView, didDeselectItemAtIndexPath indexPath: NSIndexPath) {
    let cell = collectionView.cellForItemAtIndexPath(indexPath) as! MyCell
    cell.toggleSelected()
}

наконец,

class MyCell : UICollectionViewCell {

    ....

    func toggleSelected ()
    {
        if (selected){
            backgroundColor = UIColor.orangeColor()
        }else {
            backgroundColor = UIColor.whiteColor()
        }
    }

}

Ответ 7

 func collectionView(collectionView: UICollectionView, didSelectItemAtIndexPath indexPath: NSIndexPath) {

    let cell = collectionView.cellForItemAtIndexPath(indexPath)
    if cell?.selected == true{
        cell?.layer.borderWidth = 4.0
         cell?.layer.borderColor = UIColor.greenColor().CGColor
    }   
}func collectionView(collectionView: UICollectionView, didDeselectItemAtIndexPath indexPath: NSIndexPath) {
    let cell = collectionView.cellForItemAtIndexPath(indexPath)
    if cell?.selected == false{
            cell?.layer.borderColor = UIColor.clearColor().CGColor
    }

}

Простое решение, которое я нашел

Ответ 8

Жизнь в возрасте iOS 9, здесь есть несколько вещей.

  • Проверьте, есть ли у вас collectionView.allowsSelection значение YES
  • У вас установлен collectionView.allowsMultipleSelection на YES (если вам нужна эта способность)

Теперь идет часть вентилятора. Если вы слушаете Apple и устанавливаете backgroundColor на cell.contentView вместо cell, то вы только что скрыли ее selectedBackgroundView от видимости. Потому что:

(lldb) po cell.selectedBackgroundView
<UIView: 0x7fd2dae26bb0; frame = (0 0; 64 49.5); autoresize = W+H; layer = <CALayer: 0x7fd2dae26d20>>

(lldb) po cell.contentView
<UIView: 0x7fd2dae22690; frame = (0 0; 64 49.5); gestureRecognizers = <NSArray: 0x7fd2dae26500>; layer = <CALayer: 0x7fd2dae1aca0>>

(lldb) pviews cell
<MyCell: 0x7fd2dae1aa70; baseClass = UICollectionViewCell; frame = (0 0; 64 49.5); clipsToBounds = YES; hidden = YES; opaque = NO; layer = <CALayer: 0x7fd2dae1ac80>>
   | <UIView: 0x7fd2dae26bb0; frame = (0 0; 64 49.5); autoresize = W+H; layer = <CALayer: 0x7fd2dae26d20>>
   | <UIView: 0x7fd2dae22690; frame = (0 0; 64 49.5); gestureRecognizers = <NSArray: 0x7fd2dae26500>; layer = <CALayer: 0x7fd2dae1aca0>>
   |    | <UIView: 0x7fd2dae24a60; frame = (0 0; 64 49.5); clipsToBounds = YES; alpha = 0; autoresize = RM+BM; userInteractionEnabled = NO; layer = <CALayer: 0x7fd2dae1acc0>>
   |    | <UILabel: 0x7fd2dae24bd0; frame = (0 0; 64 17.5); text = '1'; opaque = NO; autoresize = RM+BM; userInteractionEnabled = NO; layer = <_UILabelLayer: 0x7fd2dae240c0>>
   |    | <UILabel: 0x7fd2dae25030; frame = (0 21.5; 64 24); text = '1,04'; opaque = NO; autoresize = RM+BM; userInteractionEnabled = NO; layer = <_UILabelLayer: 0x7fd2dae25240>>

(lldb) po cell.contentView.backgroundColor
UIDeviceRGBColorSpace 0.4 0.4 0.4 1

Итак, если вы хотите использовать selectedBackgroundView (который включается/выключается с помощью cell.selected и selectItemAtIndexPath...), выполните следующее:

cell.backgroundColor = SOME_COLOR;
cell.contentView.backgroundColor = [UIColor clearColor];

и он должен работать нормально.

Ответ 9

Я не знаю, что я понимаю проблему, но выбранный статус установлен на ячейку и будет включать в себя все подпункты внутри ячейки. Вы не объясняете, что вы подразумеваете под "основным объектом связано много образов". Связан как в подпунктах? Или какую именно связь вы имеете в виду?

Это звучит как проблема дизайна для меня. Возможно, вам нужен подкласс UIView, который содержит все связанные с ним объекты, которые вам нужны; этот подкласс может быть установлен как представление содержимого. Я делаю это, например, где у меня есть изображение, описание и звуковая запись, связанные с изображением. Все они определены в подклассе, и каждый из этих подклассов становится представлением содержимого для одной ячейки.

Я также использовал компоновку для связанных изображений в папку, которая их содержит. В рамках этой настройки папки и изображения имеют подкласс, и каждый может быть прикреплен к ячейке в качестве представления содержимого (они хранятся в основных данных как единое целое).

Возможно, вы сможете объяснить свою проблему?

Ответ 10

Вы посмотрели:

- (BOOL)collectionView:(PSTCollectionView *)collectionView shouldDeselectItemAtIndexPath:(NSIndexPath *)indexPath;

Пожалуйста, сформулируйте свою проблему более четко и, возможно, мы сможем разобраться с ней. Я только что провел некоторое время с UICollectionView.

Я думаю, что ваша проблема может возникнуть из-за путаницы в том, что если вы программно устанавливаете cell.selected = YES, причина didSelectItemAtIndexPath: не вызывается, потому что она используется, только когда сам collectionView отвечает за выбор ячейки (например. через кран).

Ответ 11

Я использую пользовательский кластерный подкласс, для меня мне просто нужно установить self.selected = false в prepareForReuse() в подкласс.

Ответ 12

Этому вопросу шесть лет, но мне все равно; приземлившись здесь и обнаружив, что ни один из ответов не решил мою конкретную проблему, я в конце концов наткнулся на то, что считаю лучшим ответом на этот вопрос. Итак, я выкладываю это здесь для потомков.

Выбор ячеек в cellForItemAtIndexPath проблематичен из-за способа, которым UICollectionView вызывает этот метод. Он не просто вызывается при первоначальной настройке представления коллекции. Он вызывается непрерывно, поскольку представление коллекции прокручивается, потому что представление коллекции только когда-либо запрашивает у своего источника данных видимые ячейки, тем самым экономя много накладных расходов.

Поскольку представления коллекции не хранят все свои ячейки в памяти, им нужно управлять выбранным состоянием своих собственных ячеек. Они не ожидают, что вы предоставите им ячейки, для которых установлено свойство isSelected. Они ожидают, что вы предоставите им ячейки, и при необходимости установят для них выбранное свойство.

Вот почему Apple предупреждает вас не устанавливать напрямую свойство isSelected объекта UICollectionViewCell. UICollectionView ожидает, что позаботится об этом за вас.

Итак, ответ НЕ пытаться выбрать ячейки в методе cellForItemAtIndexPath. Лучшее место для выбора ячеек, которые вы хотите выбрать изначально, - это метод viewWillAppear в UICollectionViewController. В этом методе выберите все нужные ячейки, вызвав UICollectionView.selectItem(at: animated: scrollPosition :), и НЕ устанавливайте isSelected непосредственно на ваши ячейки.

Ответ 13

При вызове [UICollectionViewCell setSelected:] и [UICollectionView selectItemAtIndexPath:animated:scrollPosition:] в [UICollectionView collectionView:cellForItemAtIndexPath:] не работает попытка вызвать их внутри dispatch_async(dispatch_get_main_queue(), ^{}); блок.

Что, наконец, исправило это для меня.

Ответ 14

Выбор ячейки и отмена выбора лучше всего обрабатывать путем установки backgroundView и выбранного фонового представления. Я рекомендую убедиться, что оба кадра этого представления правильно установлены в методе layoutSubviews (если вы выбрали выбранный и фоновый вид через IB).

Не забудьте установить свой контентный образ (если у вас есть) цвет фона, чтобы очистить его, чтобы увидеть правильный вид фона.

Никогда не устанавливайте выбор ячейки напрямую (т.е. через cell.selected = YES), используйте методы, предназначенные для этой цели, в виде коллекции. Это ясно объясняется в документах, хотя я соглашусь, что информация несколько фрагментирована в руководствах.

Вам не нужно указывать цвета фона ячейки непосредственно в источнике данных коллекции.

Кроме того, в качестве заключительной заметки не забудьте вызвать [super prepareForReuse] и [super setSelected: selected], если вы реализуете их в своем классе ячеек, так как вы могли бы запретить суперкласс класса делать выбор ячейки.

Поразите меня, если вам потребуются дополнительные разъяснения по этому вопросу.