2013-03-11 4 views
35

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

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

cellForItemAtIndexPath

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

Я нахожу, что если вы установите «selected to true» - если существует связь между основным объектом и изображением в cellForItemAtIndexPath, отмена выбора больше не является вариантом.

в

didDeselectItemAtIndexPath 

и

didSelectItemAtIndexPath 

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

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

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

ответ

1

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

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

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

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

+1

Кто-нибудь использовал представление коллекции, установленное в YES в cellForItemAtIndexPath и смог отменить эту ячейку? Я создал два тестовых проекта, и оба они работают одинаково. Как только вы установите значение true в cellForItemAtIndexPath, выбор не будет снова вызван. – bworby

+0

Нет, я не думаю, что вы можете это сделать. Если я установил ячейку, выбранную в celLForItemAtIndexPath, элементы (ы) ведут себя как выбранные из начального отображения вида коллекции (т. Е. Выбранного фона); однако, если я посмотрю на значение [collectionView indexPathsForSelectedItems], я получаю nil - это говорит о том, что не было бы способа отменить его с помощью обычных средств. Возможно, вы сможете установить значение cell.selected == NO, поскольку я этого не пытался. Но если вы не можете получить индексный путь для выбранных элементов, это определенно сделает работу с коллекцией более сложной. – RegularExpression

+0

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

1

Вы смотрели на:

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

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

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

75

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

решение сейчас: я называю как[UICollectionViewCell setSelected:] и [UICollectionView selectItemAtIndexPath:animated:scrollPosition:] в [UICollectionView collectionView:cellForItemAtIndexPath:].

+2

Странно, что это необходимо, но это работает .. И это не вызывает бесконечные петли с делегатом didSelectItemAtIntexPath. –

+5

С кем-нибудь было найдено лучшее решение, так как это было предложено? Это решение также работает для меня, но это может быть ошибка. – itslittlejohn

+1

Ты СКАНТ! СКАНТ Я СКАЗАЛ ВАС! Не определен в отношении перечисления ScrollPosition, но его работа. (Y) – MrOli3000

39

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

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

+6

Не могу поверить, что я пропустил что-то настолько очевидное после 5 лет жесткого программирования iOS. Duh! – Linasses

+0

Это была моя проблема! – NickDK

+0

это легко пропустить – 2cupsOfTech

35

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

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

myCollectionView.allowsMultipleSelection = YES; 
+0

это ПРАВИЛЬНЫЙ ответ – naz

+0

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

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; 
    } 
} 
+0

Уникальный и правильный ответ. Без set collectionView.allowsMultipleSelection = YES; – WINSergey

20

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

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 

Он работал отлично!

+0

Это исправление моей проблемы. Большое спасибо. – Ismail

+0

Другие варианты не сработали для меня, эта работа отлично работала. – Stuart

0

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

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

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

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

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

Ударьте меня, если вам нужно уточнить эту тему.

4

Вот мой ответ для 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() 
     } 
    } 

} 
+0

Это работает, но мне нужно изменить цвет рамки выбранной ячейки, которая не работает в классе ячеек. Можете ли вы предложить что-нибудь по этому поводу? –

+0

@ArpitDhamane Это тоже не работает для меня, и я использую Swift 3 Xcode 8.1. Я могу изменить стиль ячейки внутри «collectionView: UICollectionView, cellForItemAt indexPath:» – user30646

1
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 
    } 

} 

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

2

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

  1. Проверьте у вас есть collectionView.allowsSelection набор для YES
  2. Проверьте у вас есть 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]; 

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

+1

Откуда вы получаете 'pviews'? Я получаю сообщение об ошибке: Unrecognized command 'pview'.' на Xcode 7.2.1, lldb-340.4.119.1 –

+0

https://github.com/facebook/chisel –

+2

'pviews cell' является просто ярлыком для' po [cell recursiveDescription] ', который вы можете сделать на любом представлении в консоли lldb –

0

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

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

1

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

Смежные вопросы