2017-02-20 36 views
0

複数のセルを選択/タップまたは折りたたんで選択解除した後に展開できるコレクションビューを構築しようとしていますが、セルが画面上に残っているとすべて正常に動作します展開されたセルが画面から消えると、予期しない動作が発生します。複数のUICollectionViewCellをタップで展開する方法

たとえば、IndexPath 0のセルを選択してスクロールし、IndexPath 8のセルをタップし、IndexPath 0のセルにスクロールして戻します(既に折りたたまれています)。インデックスパス8を持つセルとそれを再びタップすると、IndexPath 10のセルも拡張されます。

CollectionViewもプログラムで実装されており、UICollectionViewCellもサブクラス化されています。

UICollectionViewを保持しているのViewController:

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:一度に一つのセルを展開し
注:例2カスタムセルに

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

    } 
} 

を拡大するbool変数を取る必要がありません: 複数のセルを展開

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に設定します。セル自体に保持しないでください。

関連する問題