2017-05-26 43 views
2

只能選擇一個項目,我實現UICollectionViewController的子類,是水平滾動,我希望它能夠在一次只能選擇一個項目。在UICollectionViewController

當我改變當前屏幕上所選擇的項目,它工作正常。但是,例如,如果我在集合的最開始處選擇一個項目,然後向右滾動並選擇另一個,則第一個項目仍將被選中。

這裏的當前版本我的CollectionView的:

class GenresCollectionVC: UICollectionViewController { 

    var selectedIndexPath: IndexPath? 

    // MARK: UICollectionViewDataSource 
    override func numberOfSections(in collectionView: UICollectionView) -> Int { 
     return 1 
    } 

    override func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int { 
     return MockData.instance.genres.count 
    } 

    override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell { 
     let cell = collectionView.dequeueReusableCell(
      withReuseIdentifier: reuseIdentifier, for: indexPath) as! GenreCollectionViewCell 

     cell.genreNameLabel.text = MockData.instance.genres[indexPath.row] 
     if selectedIndexPath == indexPath { 
      redraw(selectedCell: cell) 
     } else { 
      redraw(deselectedCell: cell) 
     } 

     return cell 
    } 

    // MARK: UICollectionViewDelegate 
    override func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) { 
     guard let cell = collectionView.cellForItem(at: indexPath) as? GenreCollectionViewCell else { 
      return 
     } 
     redraw(selectedCell: cell) 
     selectedIndexPath = indexPath 
    } 

    override func collectionView(_ collectionView: UICollectionView, didDeselectItemAt indexPath: IndexPath) { 
     guard let cell = collectionView.cellForItem(at: indexPath) as? GenreCollectionViewCell else { 
      return 
     } 
     redraw(deselectedCell: cell) 
     selectedIndexPath = nil 
    } 

    private func redraw(selectedCell cell: GenreCollectionViewCell 
     ) { 
     cell.layer.borderWidth = 1.0 
     cell.layer.cornerRadius = cell.bounds.height/2 
     cell.layer.borderColor = UIColor.violetNeeoColor.cgColor 

     cell.genreNameLabel.textColor = UIColor.violetNeeoColor 
    } 

    private func redraw(deselectedCell cell: GenreCollectionViewCell) { 
     cell.layer.borderWidth = 0.0 
     cell.layer.cornerRadius = 0.0 

     cell.genreNameLabel.textColor = UIColor.white 
    } 
} 

我在做什麼錯?

回答

3

在你GenreCollectionViewCell類,重寫isSelected性質,即

override var isSelected: Bool{ 
    willSet{ 
     super.isSelected = newValue 
     if newValue 
     { 
      self.layer.borderWidth = 1.0 
      self.layer.cornerRadius = self.bounds.height/2 
      self.layer.borderColor = UIColor.violetNeeoColor.cgColor 
      self.genreNameLabel.textColor = UIColor.violetNeeoColor 
     } 
     else 
     { 
      self.layer.borderWidth = 0.0 
      self.layer.cornerRadius = 0.0 
      self.genreNameLabel.textColor = UIColor.white 
     } 
    } 
} 

現在你不需要選擇/取消選擇在didSelectItemAtdelegate方法的人工細胞。 isSelected屬性將自動處理它。

+0

酷,它幫助我!但是可以解釋爲什麼我們應該調用'super.isSelected = newValue'?刪除這一行代碼現在不會改變我的程序中的任何內容 – Legonaftik

+0

不改變任何東西意味着如果您刪除此行,程序無法工作? – PGDev

+0

不,一切正常,當我使用你的代碼。即使我刪除了'super.isSelected = newValue'這行,一切仍然有效。所以問題是:「爲什麼我應該寫這條線,它會發生什麼變化?」 – Legonaftik

1

選擇新indexPath

override func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) { 
    guard let cell = collectionView.cellForItem(at: indexPath) as? GenreCollectionViewCell else { 
     return 
    } 
    if selectedIndexPath != indexPath { 
     collectionView(collectionView, didDeselectItemAt: selectedIndexPath) 
    } 
    redraw(selectedCell: cell) 
    selectedIndexPath = indexPath 
} 

顯然取消委託方法稱爲細胞上每隔第二抽頭後手動取消選擇該小區。

2

在這樣的情況下保存IndexPath,然後使用該比較的基礎永遠是我最好的選擇。

先定義你的變量:

var _selectedIndexPath : IndexPath? = nil 

然後在您的didSelectItemAtIndexPath

func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath){ 

      if ((_selectedIndexPath) != nil){ 

       if indexPath.compare(_selectedIndexPath!) == ComparisonResult.orderedSame { 

        //if the user tap the same cell that was selected previously deselect it. 

        _selectedIndexPath = nil; 
       } 
       else 
       { 
\     // save the currently selected indexPath 

        _selectedIndexPath = indexPath 

       } 
      } 
      else{ 

       // else, savee the indexpath for future reference if we don't have previous selected cell 

       _selectedIndexPath = indexPath; 
     } 

     // and now only reload only the visible cells 

      collectionView.reloadItems(at: collectionView.indexPathsForVisibleItems) 
     } 

在上次檢查選定單元cellForItemAtIndexPath

func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell { 


     // Demo implementation 
     let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "cell", for: indexPath as IndexPath) 

     if _selectedIndexPath == indexPath{ 

      //If the cell is selected 
      cell.isSelected = true 
      cell.backgroundColor = UIColor.red 
     } 
     else{ 
      // If the cell is not selected 
      cell.isSelected=false 
      cell.backgroundColor = UIColor.gray 


     } 
     return cell 
    } 
+1

這是正確的答案,但didSelectItem有點不吉利。這是我的要點,更好的版本:https://gist.github.com/PeeJWeeJ/414897cfeba33a8ea8edb51239a07612 – PeejWeej

相關問題