Як зробити простий вид колекції за допомогою Swift


181

Я намагаюся навчитися користуватися UICollectionView. Документація трохи важко зрозуміти , і уроки , які я знайшов , були або в Objective C або довго складних проектів.

Коли я вчився користуватися UITableView, ми «❤ Swift» Як зробити простий перегляд таблиці за допомогою iOS 8 та Swift мали дуже базові налаштування та пояснення, щоб змусити мене йти. Чи є щось подібне UICollectionView?

Відповідь нижче - моя спроба навчитися це робити.

Відповіді:


500

Цей проект був протестований з Xcode 10 та Swift 4.2.

Створіть новий проект

Це може бути лише додаток Single View.

Додайте код

Створіть новий файл класу какао-дотику (Файл> Новий> Файл ...> iOS> Какао-сенсорний клас). Назвіть це MyCollectionViewCell. У цьому класі будуть розміщені розетки для представлень даних, які ви додаєте до своєї комірки в таблиці розмов.

import UIKit
class MyCollectionViewCell: UICollectionViewCell {
    
    @IBOutlet weak var myLabel: UILabel!
}

Ми підключимо цю розетку пізніше.

Відкрийте ViewController.swift і переконайтеся, що у вас є такий вміст:

import UIKit
class ViewController: UIViewController, UICollectionViewDataSource, UICollectionViewDelegate {
    
    let reuseIdentifier = "cell" // also enter this string as the cell identifier in the storyboard
    var items = ["1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12", "13", "14", "15", "16", "17", "18", "19", "20", "21", "22", "23", "24", "25", "26", "27", "28", "29", "30", "31", "32", "33", "34", "35", "36", "37", "38", "39", "40", "41", "42", "43", "44", "45", "46", "47", "48"]
    
    
    // MARK: - UICollectionViewDataSource protocol
    
    // tell the collection view how many cells to make
    func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
        return self.items.count
    }
    
    // make a cell for each cell index path
    func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
        
        // get a reference to our storyboard cell
        let cell = collectionView.dequeueReusableCell(withReuseIdentifier: reuseIdentifier, for: indexPath as IndexPath) as! MyCollectionViewCell
        
        // Use the outlet in our custom class to get a reference to the UILabel in the cell
        cell.myLabel.text = self.items[indexPath.item]
        cell.backgroundColor = UIColor.cyan // make cell more visible in our example project
        
        return cell
    }
    
    // MARK: - UICollectionViewDelegate protocol
    
    func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
        // handle tap events
        print("You selected cell #\(indexPath.item)!")
    }
}

Примітки

  • UICollectionViewDataSourceі UICollectionViewDelegateє протоколами, з яких випливає подання колекції. Ви також можете додати UICollectionViewFlowLayoutпротокол, щоб змінити розмір переглядів програмно, але це не обов'язково.
  • Ми просто вкладаємо прості рядки в нашу сітку, але ви, звичайно, могли робити зображення пізніше.

Налаштуйте дошку

Перетягніть подання колекції до контролера перегляду на вашій дошці. Ви можете додати обмеження, щоб воно заповнило батьківський вигляд, якщо хочете.

введіть тут опис зображення

Переконайтеся, що ваші за замовчуванням в інспекторі атрибутів також є

  • Предмети: 1
  • Макет: потік

Маленька скринька у верхньому лівому куті перегляду колекції - це комірка перегляду колекції. Ми будемо використовувати його як наш осередок прототипу. Перетягніть мітку в клітинку і відцентруйте її. Ви можете змінити розмір меж комірок і додати обмеження, щоб центрировать мітку, якщо хочете.

введіть тут опис зображення

Напишіть "комірок" (без лапок) у поле "Ідентифікатор" інспектора атрибутів для комірки "Перегляд колекції". Зауважте, що це те саме значення, що і let reuseIdentifier = "cell"у ViewController.swift.

введіть тут опис зображення

А в інспекторі ідентичності для комірки встановіть ім'я класу MyCollectionViewCell, наш спеціальний клас, який ми створили.

введіть тут опис зображення

Підключіть торгові точки

  • Гачок написи в осередку колекції , щоб myLabelв MyCollectionViewCellкласі. (Ви можете перетягнути Control ).
  • Підключіть вигляд колекції delegateта dataSourceконтролер перегляду. (Клацніть правою кнопкою миші Перегляд колекції в Контур документа. Потім натисніть та перетягніть стрілку плюс до контролера перегляду.)

введіть тут опис зображення

Готово

Ось як це виглядає після додавання обмежень для центру мітки в комірці та закріплення перегляду колекції на стінах батьків.

введіть тут опис зображення

Вдосконалення

Наведений вище приклад працює, але це досить некрасиво. Ось кілька речей, з якими можна пограти:

Колір фону

У Інструменті інтерфейсів перейдіть до перегляду колекції> Ревізор атрибутів> Перегляд> Фон .

Міжрядковий інтервал

Якщо змінити мінімальний проміжок між клітинками на менше значення, це виглядає краще. У програмі Interface Builder перейдіть до перегляду колекції> Інспектор розмірів> Міні-інтервал та зменшіть значення. "Для комірок" - горизонтальна відстань, а "Для ліній" - вертикальна відстань.

Форма клітини

Якщо ви хочете закруглені кути, облямівку тощо, ви можете пограти разом із коміркою layer. Ось приклад коду. Ви поставите це безпосередньо після cell.backgroundColor = UIColor.cyanв коді вище.

cell.layer.borderColor = UIColor.black.cgColor
cell.layer.borderWidth = 1
cell.layer.cornerRadius = 8

Дивіться цю відповідь щодо інших речей, які ви можете зробити з шаром (наприклад, тінь).

Зміна кольору при натисканні

Це сприяє кращому користуванню, коли клітини візуально реагують на крани. Один із способів досягти цього - змінити колір тла під час торкання клітини. Для цього додайте до ViewControllerкласу такі два методи :

// change background color when user touches cell
func collectionView(_ collectionView: UICollectionView, didHighlightItemAt indexPath: IndexPath) {
    let cell = collectionView.cellForItem(at: indexPath)
    cell?.backgroundColor = UIColor.red
}

// change background color back when user releases touch
func collectionView(_ collectionView: UICollectionView, didUnhighlightItemAt indexPath: IndexPath) {
    let cell = collectionView.cellForItem(at: indexPath)
    cell?.backgroundColor = UIColor.cyan
}

Ось оновлений вигляд:

введіть тут опис зображення

Подальше навчання

UITableView версія цього запитання


1
я отримую cell.myLabel як нуль, і він руйнується. будь-яка ідея чому? Я використовую власну верстку
Джеральд

4
Якщо ви не підключили розетку, перетягуючи її з мітки в дошці розкадрування до коду @IBOutletfor myLabelin, ви отримаєте такий збій.
Сурагч

3
якщо ви використовуєте конструктор інтерфейсів і посилаєтесь на комірку за допомогою розетки, не реєструйте спеціальний клас комірок у своєму контролері. дивіться це
Джеральд

1
якщо розетка UICollectionViewCell дорівнює нулю, вам доведеться її видалити self.collectionView.registerClass(MyCollectionViewCell.self, forCellWithReuseIdentifier: "Cell"). Якщо у вас все-таки виникають проблеми, перевірте, чи reuseIdentifierне те саме в dequeueReusableCellWithReuseIdentifierта в розкадровці
Ashok R

40
Я б хотів, щоб документація Apple була такою ж простою для читання, як це пояснення
elmarko

3

Делегати та джерела даних UICollectionView

//MARK: UICollectionViewDataSource

override func numberOfSectionsInCollectionView(collectionView: UICollectionView) -> Int {
    return 1     //return number of sections in collection view
}

override func collectionView(collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
    return 10    //return number of rows in section
}

override func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
    let cell = collectionView.dequeueReusableCellWithReuseIdentifier("collectionCell", forIndexPath: indexPath)
    configureCell(cell, forItemAtIndexPath: indexPath)
    return cell      //return your cell
}

func configureCell(cell: UICollectionViewCell, forItemAtIndexPath: NSIndexPath) {
    cell.backgroundColor = UIColor.blackColor()


    //Customise your cell

}

override func collectionView(collectionView: UICollectionView, viewForSupplementaryElementOfKind kind: String, atIndexPath indexPath: NSIndexPath) -> UICollectionReusableView {
    let view =  collectionView.dequeueReusableSupplementaryViewOfKind(UICollectionElementKindSectionHeader, withReuseIdentifier: "collectionCell", forIndexPath: indexPath) as UICollectionReusableView
    return view
}

//MARK: UICollectionViewDelegate
override func collectionView(collectionView: UICollectionView, didSelectItemAtIndexPath indexPath: NSIndexPath) {
      // When user selects the cell
}

override func collectionView(collectionView: UICollectionView, didDeselectItemAtIndexPath indexPath: NSIndexPath) {
     // When user deselects the cell
}

3

Для swift 4.2-

//MARK: UICollectionViewDataSource

func numberOfSectionsInCollectionView(collectionView: UICollectionView) -> Int {
    return 1     //return number of sections in collection view
}

func collectionView(collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
    return 10    //return number of rows in section
}

func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
    let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "collectionCell", for: indexPath as IndexPath)
    configureCell(cell: cell, forItemAtIndexPath: indexPath)
    return cell      //return your cell
}

func configureCell(cell: UICollectionViewCell, forItemAtIndexPath: NSIndexPath) {
    cell.backgroundColor = UIColor.black


    //Customise your cell

}

func collectionView(collectionView: UICollectionView, viewForSupplementaryElementOfKind kind: String, atIndexPath indexPath: NSIndexPath) -> UICollectionReusableView {
    let view =  collectionView.dequeueReusableSupplementaryView(ofKind: UICollectionElementKindSectionHeader, withReuseIdentifier: "collectionCell", for: indexPath as IndexPath) as UICollectionReusableView
    return view
}

//MARK: UICollectionViewDelegate
func collectionView(collectionView: UICollectionView, didSelectItemAtIndexPath indexPath: NSIndexPath) {
    // When user selects the cell
}

func collectionView(collectionView: UICollectionView, didDeselectItemAtIndexPath indexPath: NSIndexPath) {
    // When user deselects the cell
}

1

Впровадження UICollectionView досить цікаве. Ви можете скористатися простим вихідним кодом і переглянути відео-посібник за цими посиланнями:

https://github.com/Ady901/Demo02CollectionView.git

https://www.youtube.com/watch?v=5SrgvZF67Yw

extension ViewController : UICollectionViewDataSource {

    func numberOfSections(in collectionView: UICollectionView) -> Int {
        return 2
    }

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

    func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
        let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "DummyCollectionCell", for: indexPath) as! DummyCollectionCell
        cell.titleLabel.text = nameArr[indexPath.row]
        cell.userImageView.backgroundColor = .blue
        return cell
    }

}

extension ViewController : UICollectionViewDelegate {

    func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
        let alert = UIAlertController(title: "Hi", message: "\(nameArr[indexPath.row])", preferredStyle: .alert)
        let action = UIAlertAction(title: "OK", style: .default, handler: nil)
        alert.addAction(action)
        self.present(alert, animated: true, completion: nil)
    }

}

0

UICollectionView такий же, як UITableView, але він надає нам додаткову функціональність просто створити подання сітки, що в UITableView трохи проблематично. Це буде дуже довгий пост, я згадую посилання, звідки ви отримаєте все простими кроками.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.