ios dersleri

iOS CollectionView Kullanımı

Merhaba Arkadaşlar, mobilhanem.com da iOS Uygulama Geliştirme eğitim serimize kaldığımız yerden iOS CollectionView Kullanımı  dersi ile devam ediyoruz. Bir önceki derste iOS TableView Kullanımı konusunu işledik. Collection View’lar bugüne kadar kullandığınız birçok uygulamada karşınıza çıkan ve iOS uygulamalarımızı geliştirirken de sıklıkla kullanacağımız bir yapıdır. Uygulamalarınızı geliştirirken sıklıkla kullanacağınız bu temel yapıyı gelin hep beraber derinlemesine inceleyelim.

Çok sayıda içerik gördüğümüz uygulamalarda CollectionView sıklıkla kullanılır. Aşağıda neredeyse her gün kullandığımız iPhone’un Fotoğraflar uygulaması ve kullanılan CollectionView’ı görüyorsunuz.

CollectionView konusunu daha iyi anlayabilmek için önceki derslerimizde anlattığımız gibi yeni bir proje oluşturalım. Ben örnek uygulama için internetten bulduğum resimleri kullanacağım. Siz de dilerseniz örnek projedeki resimleri kullanabilir ya da kendi resimlerinizi indirebilirsiniz.

UICollectionView

İlk olarak Main.storyboard içine resimdeki gibi yeni bir UICollectionView ekliyoruz.

Ardından UICollectionView’ın tüm ekranımızı kaplamasını istediğimiz için aşağıdaki constraintleri tanımlıyoruz.

CollectionView’ı storyboard içine yerleştirdik. Şimdiyse CollectionView içinde yer alacak CollectionViewCell’leri oluşturacağız. Bunun için resimdeki gibi yeni bir UICollectionViewCell oluşturup ‘Also Create XIB file‘ seçili olduğundan emin olalım. Bu view ve class’ı collectionView içindeki gözükecek her bir cell için oluşturuyoruz.

Biraz önce cell’imizin layout’u için oluşturduğumuz PhotoCell.xib açalım. Ben örnekte bir resim ve bir yazı kullanacağım için cell’in içini aşağıdaki  gibi düzenledim.

Cell’in içinde bulunan resmi ve yazıyı değiştirebilmek için outlet’lerini oluşturmamız gerekiyor.

Not: İlgili cell’e ait Swift dosyasını açmak için kullanabileceğiniz Xcode kısayolu kntrl + ⌥(alt) +⌘ (cmd) + ↩(enter)

Daha önceki derslerimizde gördüğümüz  iOS TableView konusundan hatırlayacağınız üzere oluşturduğumuz cell’e benzersiz bir tanımlayıcı vermemiz gerekiyor. Bunun için xib dosyanız açıkken Size Inspector içinde bulunan kısmı dolduralım.

UICollectionViewDelegate ve UICollectionViewDataSource metodlarını kullanabilmemiz için gerekli delegation’ları aşağıdaki gibi viewDidLoad() metodu içine ekleyelim.

    override func viewDidLoad() {
        super.viewDidLoad()
        collectionView.delegate = self
        collectionView.dataSource = self
    }

UICollectionView Delegate Methodları

numberOfSections(in: ) metodunun implement edilmesi

Implement edeceğimiz ilk delegate metodumuz numberOfSections(in: ). Collection View birden fazla bölüme yani section’a ayrılabilir. Bunun en sık karşılaştığınız örneği her gün kullandığımız iPhone fotoğraflar uygulamasıdır. Fotoğraflar uygulamasında resimler tarihe göre ayrıldığında her bir tarihin altında bulunan fotoğraflar bir section’u oluşturur. Bu örnek uygulama için bir section’umuz olacak. Ben kodumuzun temiz ve anlaşılır olması için UICollectionViewDelegate ve UICollectionViewDataSource metodlarını ViewController’a ait bir extension içinde tanımlayacağım. Onun için kodumuz şöyle gözükmeli;

extension ViewController: UICollectionViewDelegate, UICollectionViewDataSource {
    func numberOfSections(in collectionView: UICollectionView) -> Int {
        return 1
    }
}

numberOfItemsInSection metodunun implement edilmesi

Bu metod CollectionView’ın her bir section’unda toplam kaç adet CollectionViewCell göstereceğimizi belirler. Resim objelerimizi bulundurmak için ilk olarak aşağıdaki gibi bir struct tanımlayalım.

struct PhotoAlbum {
    var image: String
    var text: String
}

Ardından bu struct’ları bulunduracak bir array’i ve örnek uygulamamızda resimlerin altındaki label’lara yazmak için kategoriler arrayini hemen ViewController.swift içindeki  CollectionView outlet’inin hemen altına oluşturalım.

let categories = ["Doğa", "Manzara", "İnsan", "Bilgisayar", "Kültür", "Ekonomi"]
var photoAlbum = [PhotoAlbum]()

Son olarak oluşturduğumuz bu array’in içini resim objelerimizle doldurmak için viewDidLoad() metodunun içine aşağıdaki kodu yazalım. Örnek projede 37 tane resim olduğundan for döngüsünü 1’den 37’ye kadar tanımladım. Kategoriler ise categories array’i içinden rastgele seçilecek.

for photo in 1...37 {
    photoAlbum.append(PhotoAlbum(image: "\(photo)", text: categories.randomElement()!))
}

CollectionViewCell  sayımız resimlerimizin sayısında olacağı için numberOfItemsInSection metodunu hemen numberOfSections(in: ) metodunun altına  aşağıdaki gibi tanımlayalım.

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

collectionView(_:cellForItemAt indexPath:) metodunun implement edilmesi

Evet, gelelim sıradaki collection view cell’lerin içindeki veriyi göstermemize yardımcı olan önemli metodlardan bir diğerine, ilk olarak aşağıdaki metodu ekleyelim.

func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
}
  • Bu metodun ilk parametresi olan collectionView biraz sonra çağıracağımız collectionView’ımızın bir değişkeni
  • indexPath ise bizim bölümlerimizin (section) ve itemlarımızın tanımlayıcı index değerleri.
  • Geri dönüş tipimiz olan UICollectionViewCell ise collection view’ın üzerinde göstereceğimiz UICollectionView tarafından kullanılan itemlardır.

Uygulamamız içinde kullanıcı her yukarı aşağı gittiği durumda cellForItemAt metodu çağrılır. Ancak bir önceki dersimizde table view için anlattığımız dequeue mekanizması burada da aynı şekilde çalışır.

func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
    // 1
    guard let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "photoCell", for: indexPath) as? PhotoCell else { return UICollectionViewCell() }
    let photo = photoAlbum[indexPath.row]
    // 2
    cell.cellImageView.image = UIImage(named: "\(photo.image)")
    // 3
    cell.cellLbl.text = photo.text
    // 4
    return cell
}
  1. İlk olarak cell’i biraz önce PhotoCell.xib üzerindeki cell’e verdiğimiz benzersiz değeri yani identifier’ı (photoCell) kullanarak dequeue ediyoruz ve cell isimli bir değişkene atıyoruz.
  2. Ardından photoAlbum isimli obje array’imizin image değişkenini cell’imizin içine koyduğumuz resme veriyoruz.
  3. Ardından photoAlbum isimli obje array’imizin text değişkenini cell’imizin içine koyduğumuz label’a veriyoruz.
  4. İlk adımda oluşturduğumuz cell’i return ediyoruz.

Çalıştırdığımızda uygulamamızın crash olduğunu göreceksiniz. Çünkü en başta oluşturduğumuz PhotoCell isimli xib dosyamızı henüz collection view’a kayıt etmedik. Gelin hemen bunu düzeltip kodu tekrar çalıştıralım. Bunun için viewDidLoad() metodunun içine aşağıdaki kodu yazmamız gerekiyor.

collectionView.register(UINib(nibName: "PhotoCell", bundle: nil), forCellWithReuseIdentifier: "photoCell")

Ancak uygulamamızı çalıştırdığımızda bu sefer crash almasak da pek istediğimiz gibi gözükmüyor. Peki ama neden?

Collection View kullanırken table view’da olduğu gibi her satırda bir item gösterebileceğimiz gibi her satırda birden fazla item da gösterebiliriz. Yukarıdaki görünümü düzeltmek ve her bir satırda birden fazla item göstermemiz için ihtiyacımız olan şey UICollectionViewFlowLayout.

UICollectionViewFlowLayout collection view’da kullanılan bir düzen nesnesi olup göstermek istediğimiz öğeleri grid olarak göstermemizi sağlar. Örnek kodu eklediğimizde daha iyi anlayacaksınız ondan hemen örneğe geçelim. Bunun için viewDidLoad() metodumuzun en altına aşağıdaki kodu yazalım.

let layout = UICollectionViewFlowLayout()
layout.scrollDirection = .vertical
layout.minimumLineSpacing = 5
layout.minimumInteritemSpacing = 5
collectionView.setCollectionViewLayout(layout, animated: true)

Kodu şimdi çalıştırdığımızda ise görüntü hala tam olarak istediğimiz gibi olmasa da grid yapısına kavuştu. Bundan sonra yapmamız gereken tek işlem ise her bir item’ın boyutunu (height ve width’ini) ayarlamak.

Apple’ın dokümantasyonunda ‘UICollectionViewDelegateFlowLayout protokolü grid tabanlı bir düzen uygulamak için UICollectionViewFlowLayout nesnesini kullanmanızı sağlayan metodlar tanımlar. Bu protokolün metodları öğelerin boyutunu ve grid üzerindeki itemların arasındaki boşluğu tanımlar’ açıklaması var.

Açıklamadan da anlaşılacağı üzere UICollectionViewDelegateFlowLayout tam olarak bizim işimizi yapmamız için gereken metodları içeriyor. O zaman gelin biz de item’ların boyutunu ayarlamak için UICollectionViewDelegate, UICollectionViewDataSource protokollerinin hemen yanına bir de UICollectionViewDelegateFlowLayout protokolünü ekleyelim ve ardından aşağıdaki kodları yazalım.

extension ViewController: UICollectionViewDelegate, UICollectionViewDataSource, UICollectionViewDelegateFlowLayout {
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, insetForSectionAt section: Int) -> UIEdgeInsets {
    return UIEdgeInsets(top: 1.0, left: 1.0, bottom: 1.0, right: 1.0)
}

func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
    let gridLayout = collectionViewLayout as! UICollectionViewFlowLayout
    let widthPerItem = collectionView.frame.width / 2 - gridLayout.minimumInteritemSpacing
    return CGSize(width:widthPerItem, height:300)
}
}

Bu metodlardan ilki olan insetForSectionAt delegate’e her bir item’ın aşağı, yukarı, sağ ve solundan ne kadar boşluk istediğini bildirir. İkinci metod olan sizeForItemAt ise her bir item’ın boyutunu belirler. Ben bu örnek için her bir satırda iki tane item göstermek istediğim için 2 – gridLayout.minimumInteritemSpacing formülünü kullandım ancak eğer sizler 3 veya 4 tane göstermek isterseniz bu 2 sayısını değiştirebilirsiniz.

Çalıştırdığımızda her şeyi doğru yaptıysanız uygulamamızın aşağıdaki gibi görünecektir.

Projenin tamamlanmış halinin kodlarına buradan ulaşabilirsiniz.

ÖZET

Bu yazımızda iOS uygulamalarımızda sıklıkla kullandığımız temel komponentlerden birisi olan Collection View’ın tanımını, nasıl oluşturulduğunu ve UICollectionViewCell’in nasıl yeniden boyutlandırıldığını anlattık. iOS Collection View yazımızla alakalı değerli görüşlerinizi, soru veya yorumlarınızı yorumlar kısmına ya da buradan soru cevap kısmına yazabilirsiniz. Diğer derste görüşmek dileğiyle.

Tüm iOS Dersleri için tıklayınız.

6

Atalay Aşa

Yorum Yaz

Haftalık Bülten

Mobilhanem'de yayınlanan dersleri haftalık mail almak ister misiniz?