Выдвиньте новый UICollectionViewController из UICollectionViewCell, который находится внутри нескольких UICollectionVIews - PullRequest
0 голосов
/ 24 января 2019

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

Сценарий I Все в порядке:

Я создал UINavigationController , который содержит UICollectionViewController , называемый HomeController в качестве rootViewController. HomeController содержит пользовательский UICollectionViewCell , называемый CustomCell . Если я нажимаю на один из CustomCells , выполняется didSelectItem класса HomeController. Этот метод помещает новый UICollectionViewController в UINavigationController . Код работает отлично. Вот скелет моего кода:

class HomeController: UICollectionViewController{

 override func viewDidLoad() {
collectionView?.register(customCell.self, forCellWithReuseIdentifier: "cellId")

 }
 
 // Call methods to render the cell
  override func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
        return 2
    }
    
    override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
        
        let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "cellId", for: indexPath) 
        return cell
    }
    
 
    func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
        return CGSize(width: view.frame.width, height: 100)
    }
    

    override func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
            let layout = UICollectionViewFlowLayout()
            let controller = UserController(collectionViewLayout: layout)
            navigationController?.pushViewController(controller, animated: true)
        }
    }

}


class customCell: UICollectionViewCell{
.....
}

Мне очень нужна ваша помощь в отношении сценариев II и III.

Сценарий II:

Я создал UINavigationController , который содержит UICollectionViewConroller с именем MainController . MainController содержит четыре различных пользовательских ячейки ( CustomCell1, CustomCell2, CustomCell3, CustomCell4 ). Ячейки прокручиваются по горизонтали, а ширина и высота каждой ячейки занимает весь вид коллекции. enter image description here

CustomCell1 , CustomCell2 , CustomCell3 и CustomCell4 содержат collectionView , который принимает ширину ячеек и высота

class CustomCell1: UICollectionViewCell, UICollectionViewDataSource, UICollectionViewDelegate, UICollectionViewDelegateFlowLayout  {

//create a collectionView  
lazy var collectionView: UICollectionView = {
        let layout = UICollectionViewFlowLayout()
        let cv = UICollectionView(frame: .zero, collectionViewLayout: layout)
        cv.backgroundColor = UIColor.white
        cv.dataSource = self
        cv.delegate = self
        return cv
    }()

.....

}

Например: CollectionView CustomCell1 содержит 3 ячейки. Первая ячейка collectionView имеет две кнопки Button1 и Button2 . Если я нажму Button2 , я хочу, чтобы содержимое cell2 и cell3 , которые находятся внутри того же самого collectionView, изменилось. ВОПРОС 1: Как вы можете достичь этого в этом сценарии? Пример кода с моей конструкцией был бы очень очень очень полезен. enter image description here

Как упоминалось выше CustomCell2 также имеет collectionView, который принимает всю ширину и высоту ячейки. CollectionView CustomCell2 содержит три CustomCell. Первый и второй CustomCells имеют collectionView ( cell.indexPath == 0 cell.indexPath == 1 ).

Первый collectionView (который находится внутри первой ячейки) имеет четыре пользовательских ячейки. Если вы нажмете на одну из этих ячеек, я хочу, чтобы новый UICollectionViewController был передан в UINavigationController . ВОПРОС 2: Как вы можете это сделать, используя делегаты и протоколы?

Второй collectionView (который находится во второй ячейке) также имеет четыре пользовательских ячейки. Если вы щелкнете по одной из этих пользовательских ячеек, задача не будет передать новый UICollectionView в NavigationController, а скорее изменить содержимое ячейки 3 ВОПРОС 3: Может ли кто-нибудь дать мне пример с моим предоставленным скелетом?

enter image description here

1 Ответ

0 голосов
/ 24 января 2019

Я собираюсь помочь вам, вы очень мило спросили, так что вот пример того, как это делается.Я не буду отвечать на вопросы 2 и 3, потому что это в основном то же самое, что и вопрос 1, но с некоторыми изменениями в протоколе.Поэтому я постараюсь объяснить как можно лучше ваш первый вопрос:

Позвольте мне начать с полного примера, который вы можете скачать: https://github.com/galots/CollectionView

Теперь объяснение:

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

class ViewController: UIViewController, UICollectionViewDelegate, UICollectionViewDelegateFlowLayout, UICollectionViewDataSource {

    lazy var collectionView : UICollectionView = {
        let layout = UICollectionViewFlowLayout()
        layout.scrollDirection = .horizontal
        let collectionView = UICollectionView(frame: .zero, collectionViewLayout: layout)
        collectionView.backgroundColor = .white
        collectionView.dataSource = self
        collectionView.delegate = self
        return collectionView
    }()

    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.

        self.view.addSubview(collectionView)
        collectionView.anchor(top: self.view.safeAreaLayoutGuide.topAnchor, leading: self.view.leadingAnchor, bottom: self.view.bottomAnchor, trailing: self.view.trailingAnchor)
        collectionView.register(TopCell.self, forCellWithReuseIdentifier: "topCell")
    }

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

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

    func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
        return CGSize(width: self.collectionView.frame.size.width, height: self.collectionView.frame.size.height)
    }

}

Теперь внутри этих ячеек у вас есть другие коллекции CollectionView, которые одновременно отображают разные ячейки.Итак, пока все хорошо.BaseCell - это просто класс, который я создал, чтобы избежать постоянной инициализации ячеек.

class BaseCell : UICollectionViewCell {

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

    func setupViews() { }

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

}

class TopCell: BaseCell, UICollectionViewDataSource, UICollectionViewDelegate, UICollectionViewDelegateFlowLayout, ButtonCellDelegate {

    var model = "Text"

    lazy var collectionView : UICollectionView = {
        let layout = UICollectionViewFlowLayout()
        let collectionView = UICollectionView(frame: .zero, collectionViewLayout: layout)
        collectionView.backgroundColor = .white
        collectionView.dataSource = self
        collectionView.delegate = self
        return collectionView
    }()

    override func setupViews() {
        super.setupViews()
        self.backgroundColor = .green
        self.addSubview(collectionView)
        collectionView.anchor(top: self.topAnchor, leading: self.leadingAnchor, bottom: self.bottomAnchor, trailing: self.trailingAnchor)
        collectionView.register(ButtonsCell.self, forCellWithReuseIdentifier: "buttonsCell")
        collectionView.register(InnerCollectionViewCell.self, forCellWithReuseIdentifier: "cvCell")
    }

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

    func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
        if indexPath.item == 0 {
            let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "buttonsCell", for: indexPath) as! ButtonsCell
            cell.buttonCellDelegate = self
            return cell
        }
        let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "cvCell", for: indexPath) as! InnerCollectionViewCell
        cell.model = self.model
        return cell
    }

    func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
        return CGSize(width: self.frame.width, height: 150)
    }

    func didPressButton(sender: String) {

        switch sender {
        case "buttonOne":
            self.model = "Text"
            self.collectionView.reloadData()
        case "buttonTwo":
            self.model = "New Text"
            self.collectionView.reloadData()
        default:
            break
        }


    }
}

Теперь, вот где вы собираетесь делать большую часть вещей.

// Protocol for buttons

protocol ButtonCellDelegate : class { func didPressButton (sender: String) }

// Buttons Cell

class ButtonsCell : BaseCell {

    weak var buttonCellDelegate : ButtonCellDelegate?

    let buttonOne : UIButton = {
        let button = UIButton(frame: .zero)
        button.setTitle("Button 1", for: .normal)
        button.setTitleColor(.black, for: .normal)
        return button
    }()

    let buttonTwo : UIButton = {
        let button = UIButton(frame: .zero)
        button.setTitle("Button 2", for: .normal)
        button.setTitleColor(.black, for: .normal)
        return button
    }()

    override func setupViews() {
        super.setupViews()
        self.addSubview(buttonOne)
        buttonOne.anchor(top: self.topAnchor, leading: self.leadingAnchor, bottom: self.bottomAnchor, trailing: nil, size: .init(width: self.frame.width / 2, height: 0))
        buttonOne.addTarget(self, action: #selector(buttonOnePressed), for: .touchUpInside)
        self.addSubview(buttonTwo)
        buttonTwo.anchor(top: self.topAnchor, leading: buttonOne.trailingAnchor, bottom: self.bottomAnchor, trailing: self.trailingAnchor)
        buttonTwo.addTarget(self, action: #selector(buttonTwoPressed), for: .touchUpInside)
    }

    @objc func buttonTwoPressed (sender: UIButton) {
        self.buttonCellDelegate?.didPressButton(sender: "buttonTwo")
    }

    @objc func buttonOnePressed (sender: UIButton) {
        self.buttonCellDelegate?.didPressButton(sender: "buttonOne")
    }
}

// Mark

class InnerCollectionViewCell : BaseCell, UICollectionViewDataSource, UICollectionViewDelegate, UICollectionViewDelegateFlowLayout {

    var model : String? {
        didSet {
            self.collectionView.reloadData()
        }
    }

    lazy var collectionView : UICollectionView = {
        let layout = UICollectionViewFlowLayout()
        layout.scrollDirection = .horizontal
        let collectionView = UICollectionView(frame: .zero, collectionViewLayout: layout)
        collectionView.backgroundColor = .red
        collectionView.dataSource = self
        collectionView.delegate = self
        return collectionView
    }()

    override func setupViews() {
        super.setupViews()
        self.addSubview(collectionView)
        collectionView.anchor(top: self.topAnchor, leading: self.leadingAnchor, bottom: self.bottomAnchor, trailing: self.trailingAnchor)
        collectionView.register(InnerCollectionViewSubCell.self, forCellWithReuseIdentifier: "innerCell")
    }

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

    func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
        let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "innerCell", for: indexPath) as! InnerCollectionViewSubCell
        cell.model = self.model
        return cell
    }

    func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
        return CGSize(width: 100, height: 100)
    }

}

// Mark

class InnerCollectionViewSubCell : BaseCell {

    var model : String? {
        didSet { label.text = model }
    }

    let label : UILabel = {
        let label = UILabel(frame: .zero)
        label.textColor = .black
        label.textAlignment = .center
        return label
    }()

    override func setupViews() {
        super.setupViews()
        self.addSubview(label)
        label.anchor(top: self.topAnchor, leading: self.leadingAnchor, bottom: self.bottomAnchor, trailing: self.trailingAnchor)
    }
}

// Extensions

extension UIView {
    func anchor(top: NSLayoutYAxisAnchor?, leading: NSLayoutXAxisAnchor?, bottom: NSLayoutYAxisAnchor?, trailing: NSLayoutXAxisAnchor?, padding: UIEdgeInsets = .zero, size: CGSize = .zero) {
        translatesAutoresizingMaskIntoConstraints = false
        if let top = top { topAnchor.constraint(equalTo: top, constant: padding.top).isActive = true }
        if let leading = leading { leadingAnchor.constraint(equalTo: leading, constant: padding.left).isActive = true }
        if let bottom = bottom { bottomAnchor.constraint(equalTo: bottom, constant: -padding.bottom).isActive = true }
        if let trailing = trailing { trailingAnchor.constraint(equalTo: trailing, constant: -padding.right).isActive = true }
        if size.width != 0 { widthAnchor.constraint(equalToConstant: size.width).isActive = true }
        if size.height != 0 { heightAnchor.constraint(equalToConstant: size.height).isActive = true }
    }
}

Для ButtonsCell существует протокол, который может соответствовать верхней ячейке для обновления содержимого других collectionViewCells.Всякий раз, когда в кнопке buttonCell нажимается кнопка, вызывается делегат, и var model обновляется, эта модель также распространяется на внутренние ячейки из-за reloadData() и потому, что в методе topCell cellForItem я устанавливаю модельиз innerCells, чтобы быть таким же, как модель верхней ячейки.didSet во внутренней ячейке просто действует как наблюдатель, поэтому при обновлении модели пользовательский интерфейс ячейки также должен обновляться.

Теперь, что касается вопросов 2 и 3, я думаю, если вы посмотрите на пример, то это в основном та же самая реализация делегатов.Вам просто нужно внести некоторые изменения в функции протокола, чтобы добавить необходимые вам функции, и вы также можете вызвать делегат в других местах, например, в методе didSelectItem внутренних collectionViews.

Hopeэто помогает.

...