2013-03-11 103 views
35

所以我有一個主要的對象,有許多圖像與它關聯。圖像也是一個對象。UICollectionView選擇和取消選擇問題

說你有一個集合視圖控制器,並在控制器,你有

cellForItemAtIndexPath

以及基於主要對象,如果有與它相關我想當前的圖像來設置選擇爲真。但是我希望用戶能夠隨時「取消」當前單元格,以消除它與主要對象的關聯。

我發現如果你設置「選擇爲真」 - 如果cellForItemAtIndexPath中的主對象和圖像之間存在關係,取消選擇不再是一個選項。

didDeselectItemAtIndexPath 

didSelectItemAtIndexPath 

我有一個記錄測試,看看他們是否被調用。如果一個單元格被設置爲選中 - 下一個被調用,但如果我從來沒有設置一個單元格在cellForItemAtIndexPath中被選中,我可以選擇和取消選擇所有我想要的。

這是集合視圖應該工作的預期方式嗎?我閱讀了文檔,似乎沒有談論這是如此。我將文檔解釋爲表示它以表格視圖單元格的方式工作。有幾個明顯的變化

這也顯示了控制器設置正確,並使用相應的委託方法.... hmmmm

回答

1

我不知道我理解的問題,但選擇的狀態設置每個單元格幷包含單元格內的所有子視圖。你不能解釋你的意思是「主對象有許多與之相關的圖像」。在子視圖中關聯?或者你的意思是什麼樣的聯繫?

這聽起來像是一個設計問題。也許你需要一個包含你需要的任何關聯對象的UIView子類;該子類可以被設置爲內容視圖。例如,我在這裏做了一個圖像,一個描述和一個與圖像相關的錄音。所有都在子類中定義,然後每個這些子類成爲單個單元格的內容視圖。

我也使用了一種安排來將相關圖像放到包含它們的文件夾中。在此設置下,文件夾和圖像每個都有一個子類,並且可以將任一個作爲內容視圖附加到單元格(這些內容視圖以單個實體的形式存儲在覈心數據中)。

也許你可以進一步解釋你的問題?

+1

有沒有人使用過集合視圖,在cellForItemAtIndexPath中將選擇設置爲YES並且能夠取消選擇該單元格?我已經建立了兩個測試項目,兩者的工作原理都是一樣的。只要在ce​​llForItemAtIndexPath中將selected設置爲true,就不會再次調用取消選擇。 – bworby 2013-03-12 04:46:44

+0

不,我認爲你不能這樣做。如果我在cellLForItemAtIndexPath中設置了一個單元格,則該項目的行爲與集合視圖(即所選背景)的初始顯示中所選擇的相同。然而,如果我查看[collectionView indexPathsForSelectedItems]的值,我會得到零 - 這表明我不會有通過常規手段取消選擇它的方式。 您可能可以設置cell.selected == NO的值,因爲我沒有嘗試過。但是,如果你無法獲得所選項目的索引路徑,那肯定會使集合視圖更難以使用。 – RegularExpression 2013-03-12 05:03:26

+0

這看起來不奇怪嗎?我可能會考慮錯誤,但我可以肯定地看到,允許某些單元格按照選定的方式啓動並能夠被取消選擇的用途很多。 – bworby 2013-03-13 21:55:53

1

你有沒有看:

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

請詳細寫明您的問題,也許我們可以得到它的底部。我剛剛花了一些時間與UICollectionView。

我認爲你的問題可以從混亂被制止,如果你設置cell.selected = YES編程,原因didSelectItemAtIndexPath:是沒有得到所謂的是因爲這是隻使用時的CollectionView本身負責細胞的選擇(例如,通過自來水)。

75

我有同樣的問題,即。在[UICollectionView collectionView:cellForItemAtIndexPath:]中設置cell.selected = YES然後不能通過點擊選擇單元格。

現在的解決方案:我打電話[UICollectionViewCell setSelected:][UICollectionView selectItemAtIndexPath:animated:scrollPosition:][UICollectionView collectionView:cellForItemAtIndexPath:]

+2

奇怪的,它應該是必要的 - 但它的工作原理..它不會導致無限循環與didSelectItemAtIntexPath委託.. – 2013-07-30 09:58:36

+5

有沒有人發現,因爲這更好的解決辦法,提出了?這個解決方案也適用於我,但這可能是一個錯誤。 – itslittlejohn 2014-02-20 20:32:33

+1

您是SAINT!我告訴你!不確定在ScrollPosition枚舉的具體情況,但它的工作。 (Y) – MrOli3000 2014-09-05 11:00:45

39

您的Cell類中是否有自定義的setSelected方法?你用那種方法打電話給[super setSelected:selected]

我有一個神祕的問題,我正在使用多個選擇,一旦他們被選中,我無法取消選擇單元格。調用超級方法解決了這個問題。

+6

我無法相信,經過5年的艱難的iOS編程,我錯過了如此明顯的東西。咄! – Linasses 2013-11-19 12:56:42

+0

這是我的問題! – NickDK 2015-02-20 16:31:32

+0

這可以很容易錯過 – 2cupsOfTech 2016-02-25 17:29:55

35

我有一個取消選擇問題UICollectionView,我發現我不允許在collectionView上進行多重選擇。所以當我測試的時候,我總是在同一個單元格上嘗試,如果單選是ON,你不能取消已經選擇的單元格。

我不得不添加:

myCollectionView.allowsMultipleSelection = YES; 
+0

這是正確的答案 – naz 2014-09-30 10:27:04

+0

我想大多數人錯過的原因,是因爲它沒有暴露在IB收集意見,對不對?我已經找到它了,在IB的任何地方都找不到它。 – 2016-12-21 12:12:37

5

我不知道爲什麼UICollectionView是如此凌亂這樣比較UITableViewController ... 有幾件事情我發現。

多次調用setSelected:的原因是因爲序列方法被調用。該序列與UITextFieldDelegate方法非常相似。

collectionView實際選擇單元之前調用方法collectionView:shouldSelectItemAtIndexPath:,因爲它實際上是在詢問「它應該被選中」嗎?

collectionView:didSelectItemAtIndexPath:實際上是在collectionView選擇了該單元之後調用的。因此,名稱「確實選擇了」。

所以這就是你的情況發生了什麼(和我的情況,我不得不在這方面搏鬥幾個小時)。

用戶再次觸摸選定的單元格以取消選擇。調用shouldSelectItemAtIndexPath:來檢查是否應該選擇單元格。 collectionView選擇該單元,然後調用didSelectItemAtIndexPath。無論你在這一點做什麼,在單元的selected屬性設置爲YES之後。這就是爲什麼像cell.selected = !cell.selected這樣的東西不起作用。

TL; DR - 請collectionView通過調用deselectItemAtIndexPath:animated:取消選擇委託方法collectionView:shouldSelectItemAtIndexPath:中的單元格,並返回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

獨特而正確的答案。沒有設置collectionView.allowsMultipleSelection = YES; – WINSergey 2016-10-21 08:31:37

20

這是慈祥的老人,但由於我使用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 

它完美!

+0

這解決了我的問題。非常感謝。 – Ismail 2015-11-16 12:04:21

+0

其他選項並不適合我,這一個完美工作。 – Stuart 2016-08-03 08:51:21

0

單元格選擇和取消選擇最好通過設置backgroundView和選定的背景視圖來處理。我建議確保在layoutSubviews方法中正確設置這兩個視圖的框架(如果您通過IB設置選定視圖和背景視圖)。

不要忘記設置你的contentView的(如果你有)背景顏色清除,以便正確的背景視圖顯示。

不要直接設置單元格的選擇(即通過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

這可以工作,但我需要更改所選單元格的邊框顏色,這在單元類中不起作用。你能提出一些建議嗎? – 2016-12-20 13:00:56

+0

@ArpitDhamane這不適用於我,我使用的是Swift 3 Xcode 8.1。我只能在「collectionView:UICollectionView,cellForItemAt indexPath」裏面改變單元格樣式:「 – user30646 2017-04-22 18:34:45

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並將其設置爲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.selectedselectItemAtIndexPath...的一個),那麼這樣做:

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

,它應該只是罰款。

+1

」你從哪裏得到'pviews'?我得到一個錯誤:在Xcode 7.2.1上無法識別的命令'pview'.',lldb-340.4.119.1 – 2016-04-25 18:15:03

+0

https://github.com/facebook/chisel – 2016-04-26 07:28:48

+2

'pviews cell'只是'po [cell recursiveDescription]'調用,你可以在任何視圖上做lldb console – 2016-04-26 07:31:31

0

當調用[UICollectionViewCell setSelected:][UICollectionView selectItemAtIndexPath:animated:scrollPosition:][UICollectionView collectionView:cellForItemAtIndexPath:]不起作用嘗試調用他們dispatch_async(dispatch_get_main_queue(), ^{}); 塊內。

這就是最終爲我解決的問題。

1

我使用的是自定義單元格子類,對於我來說,我只需要在子類中設置。