Kuinka rakentaa Spotify-klooni ohjelmallisesti iOS: lle AutoLayoutilla

Tässä viestissä yritämme luoda Spotifyn aloitusnäyttöasettelun uudelleen ohjelmallisesti. Miksi ohjelmallisesti? Mielestäni on aina hyvä osata rakentaa asioita eri tavoin, ja haluan kirjoittaa koodia tehdäksesi asioita ohjelmallisesti. Nämä taidot ovat erityisen hyödyllisiä, jos työskentelet tiimin kanssa tai käytät versionhallintaa.

Tämä on Spotifyn mobiilisovelluksen todellinen aloitusnäyttö. Joten tällaisen asettelun saavuttamiseksi käytämme UICollectionView, ja voimme käyttää TabBarControllermyös välilehdenavigaattorin luomiseen.

Perusvaatimus: Varmista ensin, että Xcode +10 on asennettu ja nopea +4.

Aloitetaan luomalla uusi Xcode-projekti Xcode: lla:

Ja ensimmäinen asia, joka meidän on tehtävä, ViewController.swifton vaihtaa superluokka sen UICollectionViewControllersijaan,   että luokkamme UIViewControllerperustuu collectionView.

// // ViewController.swift // spotifyAutoLayout // // Created by admin on 10/31/19. // Copyright © 2019 Said Hayani. All rights reserved. // import UIKit class ViewController: UICollectionViewController { override func viewDidLoad() { super.viewDidLoad() collectionView.backgroundColor = .purple // Do any additional setup after loading the view. } } 

Jos yrität käyttää sovellusta, rakennus epäonnistuu. Meidän on lisättävä koodia funktiossa olevaan AppDelegate.swifttiedostoon didFinishLaunchingWithOptionstämän koodikappaleen ohi ennen   returnlausetta:

 let layout = UICollectionViewFlowLayout() window = UIWindow() window?.rootViewController = ViewController(collectionViewLayout: layout)

Ja koodin pitäisi näyttää tältä:

func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { // Override point for customization after application launch. let layout = UICollectionViewFlowLayout() window = UIWindow() window?.rootViewController = ViewController(collectionViewLayout: layout) return true }

Nyt sinun pitäisi pystyä ajaa sovellus ja nähdä backgroundColormuutettu purple:

Seuraava vaihe on jakaa asettelu ja jakaa tila tasaisesti osioiden välillä.

Määritetään menetelmämme CollectionView.

Askeleet:

  • Rekisteröi uudelleenkäytettävä solu, jolla on yksilöllinen tunniste
  • Määritä osan kohteiden määrä
  • Käytä rekisteröityä solua  

Joidenkin CollectionViewmenetelmien käyttämiseksi meidän on aina noudatettava UICollectionViewDelegateFlowLayoutsuperluokkaa ja hankittava menetelmien automaattinen täydennys. Joten aloitetaan rekisteröimällä CollectionViewCell.

Sisällä View.DidLoad()kutsumme collectionView.register()menetelmää uudelleenkäytettävän solun rekisteröimiseksi:

 collectionView.register(UICollectionViewCell.self, forCellWithReuseIdentifier: cellId)

Sitten määritämme solujen lukumäärän, joka meillä on collectionViewkäytön aikana numberOfItemsInSection. Nyt meidän on vain tehtävä siitä 5 tuotetta:

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

Seuraava vaihe on määritellä uudelleenkäytettävä solu käyttämällä sitä, cellForItemAtjonka pitäisi palata UICollectionViewCellja jolla on yksilöllinen tunnus cellId. Koodi näyttää tältä:

 override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell { let cell = collectionView.dequeueReusableCell(withReuseIdentifier: cellId, for: indexPath) cell.backgroundColor = .red return cell }

Koko koodin pitäisi näyttää tältä:

import UIKit class ViewController: UICollectionViewController, UICollectionViewDelegateFlowLayout { let cellId : String = "cellId" override func viewDidLoad() { super.viewDidLoad() collectionView.backgroundColor = .purple collectionView.register(UICollectionViewCell.self, forCellWithReuseIdentifier: cellId) } override func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int { return 5 } override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell { let cell = collectionView.dequeueReusableCell(withReuseIdentifier: cellId, for: indexPath) cell.backgroundColor = .red return cell } }

Sinun pitäisi pystyä näkemään 5 punaisella taustalla olevaa kohdetta näytöllä:

Lisää mukautettu leveys ja korkeus soluihin

Nyt meidän on sijoitettava solut oikeaan järjestykseen ja annettava niille widthja height. Kukin solu ottaa widthruudun muodossa width.

Olemme onnekkaita, että sizeForItemAtmeillä on menetelmä, jotta voimme antaa soluille mukautetun widthja height. Se on menetelmä, jonka pitäisi palauttaa CGSizetyyppi:

 func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize { let width = view.frame.width let height = CGFloat(200) return CGSize(width: width, height: height) }

Joten teimme   Cellottaa widthnäytön avulla view.frame.widthja mukautetun heightjossa on CGFloattyyppiä.

Nyt näet alla olevan tuloksen Simulaattorissasi:

Kaikki näyttää toistaiseksi hyvältä. Luodaan tällä kertaa mukautettu solu, joka voidaan käyttää uudelleen. Luo uusi Swift-tiedosto nimeltä CustomCell:

CustomCell.swift pitäisi näyttää tältä alla:

 import UIKit class CustomCell: UICollectionViewCell { override init(frame: CGRect) { super.init(frame: frame) } required init?(coder aDecoder: NSCoder) { fatalError("init(coder:) has not been implemented") } } 

Seuraavat asiat, jotka meidän on tehtävä, on muokata kahta menetelmää uudelleenkäytettävän solun tukemiseksi collectionView.registerja cellForItemAt. Muutetaan ensin rekisterimenetelmää. KorvataUICollectionViewCell.selfkanssa CustomCell:

 collectionView.register(UICollectionViewCell.self, forCellWithReuseIdentifier: cellId) 

Seuraavaksi meidän on valettava cellForItemAtnoudattamaan CustomCellalla olevaa:

 let cell = collectionView.dequeueReusableCell(withReuseIdentifier: cellId, for: indexPath) as! CustomCell

Jos käytät sovellusta, et todennäköisesti huomaa mitään muutoksia, joten anna CustomCellille backgroundColor backgroundColor = .yellow. Älä unohda poistaa linjaa cell.backgroundColor = .redsisään cellForItemAt. Sinun pitäisi nähdä taustaväri muuttunut keltaiseksi?

Nyt on aika laittaa suolaa CutomCell: D

Jos tarkastelet Spotify-aloitusnäyttöä, jokainen CustomCellesimerkissämme oleva osa sisältää osan otsikon, alisolut ja vaakasuoran:

Lisää osan otsikko

Let's add a title label to the cell. Create the titleLabel element inside the CutomCell class:

let titleLabel: UILabel = { let lb = UILabel() lb.text = "Section Title" lb.font = UIFont.boldSystemFont(ofSize: 14) lb.font = UIFont.boldSystemFont(ofSize: 14) return lb }()

Then add the element to the view inside init() block:

addSubview(titleLabel)

If you run the app you won't see any changes, and that's because we didn't put any constraint to the element yet. So let's add some constraints – add this property              lb.translatesAutoresizingMaskIntoConstraints = falsetotitleLabel to be able to apply constraints to the element:

After we add titleLabel to the view, we define the constraints:

 addSubview(titleLabel) titleLabel.topAnchor.constraint(equalTo: topAnchor, constant: 8).isActive = truetitleLabel.leftAnchor.constraint(equalTo: leftAnchor,constant: 8 ).isActive = true

Always make sure to add .isActive = true property – without it the constraint won't work!

Before we move on to the next part, let's first change the background color of the screen to black and also remove the yellow color for the cells:

Now comes the big part: putting sub cells into each cell. To achieve that we are going to add a CollectionView inside CustomCell.

To add a CollectionView inside UICollectionViewCell we need to add  properties UICollectionViewDelegate, UICollectionViewDelegateFlowLayout, and UICollectionViewDataSource as superClass to CustomCell.

Let's create the collectionView element as any simple view:

 let collectionView : UICollectionView = { // init the layout let layout = UICollectionViewFlowLayout() // set the direction to be horizontal layout.scrollDirection = .horizontal // the instance of collectionView let cv = UICollectionView(frame: .zero, collectionViewLayout: layout) // Activate constaints cv.translatesAutoresizingMaskIntoConstraints = false return cv }()

Notice that we add layout to the collectionView as layer in the initializer as we did the first time with the viewController.swift. Here we also specify the direction of the FlowLayout to be .horizontal.

Let's add the collectionView element to the view as subView.

We gonna make a function that do that for us to make the code a little bit cleaner.

 fileprivate func setupSubCells(){ // add collectionView to the view addSubview(collectionView) collectionView.dataSource = self collectionView.delegate = self // setup constrainst // make it fit all the space of the CustomCell collectionView.topAnchor.constraint(equalTo: titleLabel.bottomAnchor).isActive = true collectionView.leftAnchor.constraint(equalTo: leftAnchor).isActive = true collectionView.bottomAnchor.constraint(equalTo: bottomAnchor).isActive = true collectionView.rightAnchor.constraint(equalTo: rightAnchor).isActive = true } 

Make sure to set delegate to self for the collectionView and the dataSource as well:

 collectionView.dataSource = self

  collectionView.delegate = self

Then call the function within init block.

Xcode will display some errors if you trying to build the app because we are not conforming to UICollectionViewDelegate and UICollectionViewDelegateFlowLayout protocols. To fix that we need first to register the sub cell as a reusable cell.

Create a variable at the top of the class and give it a name of cellId so we can use it when we need the cell identifier:

let cellId : String = "subCellID"

collectionView.register(UICollectionViewCell.self, forCellWithReuseIdentifier: cellId)

Now we're missing two more methods to make the errors go away: numberOfItemsInSection that define the number of cells in the section and cellForItemAt that define the reusable cell. These methods are necessary for  collectionView to work properly:

 // number of cells func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int { return 4 } // reusable Cell func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell { let cell = collectionView.dequeueReusableCell(withReuseIdentifier: cellId, for: indexPath) cell.backgroundColor = .yellow return cell }

The results should look like this:

As you can see, the collectionView are in purple as background and sub cells are yellow.

Viimeiset asiat, jotka voimme tehdä ennen tämän artikkelin lopettamista, on tehdä subCells, että osan korkeus ja leveys ovat. Jälleen käytämme sizeForItemAtmääritellä heightja widthsolun.

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

Ja tässä me olemme?:

KIVA! Aion lopettaa tässä vaiheessa, joten tämä viesti ei ole liian pitkä. Teen toisen osan, johon aiomme lisätä pilkattuja kuvia ja täyttää se joillakin tiedoilla.

Koko lähdekoodi? tässä

Ole hyvä, jos sinulla on lisäyksiä, kysymyksiä tai korjauksia, lähetä se alla oleviin kommentteihin? tai löi minua Twitterissä.

Tilaa sähköpostiosoitteeni, niin saat ilmoituksen tämän opetusohjelman toisen osan julkaisemisesta