2017-02-20 108 views
0

我想構建一個collectionView,可以擴展多個單元格後,他們已被選中/點擊或摺疊,當他們被取消選中時,一切工作正常,當單元格保持在屏幕上,但一旦擴大的細胞脫離屏幕,我會得到意想不到的行爲。如何擴展多個UICollectionViewCells水龍頭

例如,如果我選擇一個IndexPath爲0的單元格,然後向下滾動,請點擊IndexPath爲8的單元格,回滾到IndexPath爲0的單元格(它已經摺疊),我會點擊它並滾動回到單元格與索引路徑8並再次點擊它擴展+ IndexPath 10的單元格也會擴大。

CollectionView已以編程方式實現,並且UICollectionViewCell已被分類。

的ViewController持有的UICollectionView:

import UIKit 

class CollectionViewController: UIViewController { 

    // MARK: - Properties 
    fileprivate var collectionView: UICollectionView! 

    var manipulateIndex: NSIndexPath? { 
     didSet { 
      collectionView.reloadItems(at: collectionView.indexPathsForSelectedItems!) 
     } 
    } 

    // MARK: - Lifecycle 
    override func viewDidLoad() { 
     super.viewDidLoad() 

     let layout: UICollectionViewFlowLayout = UICollectionViewFlowLayout() 
     layout.sectionInset = UIEdgeInsets(top: 20, left: 10, bottom: 10, right: 10) 

     collectionView = UICollectionView(frame: self.view.frame, collectionViewLayout: layout) 
     collectionView.dataSource = self 
     collectionView.delegate = self 
     collectionView.register(CustomCell.self, forCellWithReuseIdentifier: "Cell") 
     collectionView.backgroundColor = UIColor.white 
     self.view.addSubview(collectionView) 
    } 

} 

// MARK: - UICollectionViewDataSource 
extension CollectionViewController: UICollectionViewDataSource { 

    func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int { 
     return 13 
    } 

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

     cell.textLabel.text = "\(indexPath.item)" 
     cell.backgroundColor = UIColor.orange 

     return cell 
    } 
} 

// MARK: - UICollectionViewDelegate 
extension CollectionViewController: UICollectionViewDelegate { 

    func collectionView(_ collectionView: UICollectionView, shouldSelectItemAt indexPath: IndexPath) -> Bool { 
     let cell = collectionView.cellForItem(at: indexPath) as! CustomCell 
     cell.expanded = !cell.expanded 

     manipulateIndex = indexPath as NSIndexPath 

     return false 
    } 
} 

// MARK: - UICollectionViewDelegateFlowLayout 
extension CollectionViewController: UICollectionViewDelegateFlowLayout { 

    func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize { 

     if let cell = collectionView.cellForItem(at: indexPath) as? CustomCell { 
      if cell.expanded == true { 
       return CGSize(width: self.view.bounds.width - 20, height: 300) 
      } 

      if cell.expanded == false { 
       return CGSize(width: self.view.bounds.width - 20, height: 120.0) 
      } 
     } 

     return CGSize(width: self.view.bounds.width - 20, height: 120.0) 

    } 
} 

而子類的自定義UICollectionViewCell:

import UIKit 

class CustomCell: UICollectionViewCell { 

    var expanded: Bool = false 
    var textLabel: UILabel! 

    override init(frame: CGRect) { 
     super.init(frame: frame) 

     textLabel = UILabel(frame: CGRect(x: 0, y: 0, width: frame.size.width, height: frame.size.height/3)) 
     textLabel.font = UIFont.systemFont(ofSize: UIFont.smallSystemFontSize) 
     textLabel.textAlignment = .center 
     contentView.addSubview(textLabel) 
    } 

    required init?(coder aDecoder: NSCoder) { 
     fatalError("init(coder:) has not been implemented") 
    } 
} 

請幫忙,謝謝你這麼多的了不起的人,誰可以幫我! :)

回答

1

嘗試這種情況:
實施例1:在一個時間展開只有一個小區
注:沒有必要採取膨脹的布爾變量定製細胞

var section:Int? 
var preSection:Int? 
var expand:Bool = false 


extension ViewController: UICollectionViewDataSource { 

    func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int { 
     return 13 
    } 

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

     cell.textLabel.text = "\(indexPath.item)" 
     cell.backgroundColor = UIColor.orange 

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

     if (self.section != nil) { 
      self.preSection = self.section 
     } 

     self.section = indexPath.row 

     if self.preSection == self.section { 
      self.preSection = nil 
      self.section = nil 
     }else if (self.preSection != nil) { 
      self.expand = false 
     } 
     self.expand = !self.expand 
     self.collectionView.reloadItems(at: collectionView.indexPathsForSelectedItems!) 

    } 

} 


// MARK: - UICollectionViewDelegateFlowLayout 
extension ViewController: UICollectionViewDelegateFlowLayout { 

    func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize { 

     if self.expand, let row = self.section, row == indexPath.row { 
      return CGSize(width: self.view.bounds.width - 20, height: 300) 
     }else{ 
      return CGSize(width: self.view.bounds.width - 20, height: 120.0) 
     } 

    } 
} 

實施例2: 展開多種細胞

import UIKit 

class ViewController: UIViewController { 


    // MARK: - Properties 
    fileprivate var collectionView: UICollectionView! 
    var expandSection = [Bool]() 
    var items = [String]() 

    override func viewDidLoad() { 
     super.viewDidLoad() 

     self.items = ["A","B","C","D","E","F","G","H","J","K"] 
     let layout: UICollectionViewFlowLayout = UICollectionViewFlowLayout() 
     layout.sectionInset = UIEdgeInsets(top: 20, left: 10, bottom: 10, right: 10) 

     collectionView = UICollectionView(frame: self.view.frame, collectionViewLayout: layout) 
     collectionView.dataSource = self 
     collectionView.delegate = self 
     collectionView.register(CustomCell.self, forCellWithReuseIdentifier: "Cell") 
     collectionView.backgroundColor = UIColor.white 
     self.expandSection = [Bool](repeating: false, count: self.items.count) 

     self.view.addSubview(collectionView) 
    } 

    override func didReceiveMemoryWarning() { 
     super.didReceiveMemoryWarning() 
     // Dispose of any resources that can be recreated. 
    } 
} 

extension ViewController: UICollectionViewDataSource { 

    func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int { 
     return self.items.count 
    } 

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

     cell.textLabel.text = self.items[indexPath.row] 
     cell.backgroundColor = UIColor.orange 

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

     self.expandSection[indexPath.row] = !self.expandSection[indexPath.row] 
     self.collectionView.reloadItems(at: collectionView.indexPathsForSelectedItems!) 
    } 

} 


// MARK: - UICollectionViewDelegateFlowLayout 
extension ViewController: UICollectionViewDelegateFlowLayout { 

    func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize { 

     if self.expandSection[indexPath.row] { 
      return CGSize(width: self.view.bounds.width - 20, height: 300) 
     }else{ 
      return CGSize(width: self.view.bounds.width - 20, height: 120.0) 
     } 
    } 
} 
0

UICollectionView將重用您的單元格用於數據模型中的多個對象。您無法控制哪些單元格在reloadItems期間得到重用您不應該假設給定單元格中的expanded狀態對應於您的數據模型的狀態。相反,您應該在數據模型中以某種方式保持expanded狀態,並在每次調用cellForItemAt時重新設置該狀態。

換句話說,在你的模型中保持你的狀態,並在cellForItemAt中設置單元狀態,不要將它保存在單元本身中。