Kā programmatiski izveidot Spotify klonu iOS ar AutoLayout

Šajā ziņojumā mēs mēģināsim programmatiski no jauna izveidot Spotify sākuma ekrāna izkārtojumu Swift. Kāpēc programmatiski? Es domāju, ka vienmēr ir labi zināt, kā veidot lietas dažādos veidos, un man patīk rakstīt kodu, lai lietas darītu programmatiski. Šīs prasmes ir īpaši noderīgas, ja strādājat ar komandu vai izmantojat versiju kontroli.

Šis ir Spotify mobilās lietotnes faktiskais sākuma ekrāns. Tātad, lai sasniegtu šāda veida izkārtojumu, mēs to izmantosim UICollectionView, un mēs varam arī izmantot TabBarController, lai izveidotu cilnes navigatoru.

Pamatprasība: Vispirms pārliecinieties, vai esat instalējis Xcode +10 un ātri +4.

Sāksim ar jauna Xcode projekta izveidi, izmantojot Xcode:

Pirmā lieta, kas mums jādara, ViewController.swiftir mainīt superklasi uz, UICollectionViewControllernevis   UIViewControllertāpēc, ka mūsu klase būs balstīta 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. } } 

Ja mēģināt palaist lietotni, būvēšana neizdosies. Mums pirms AppDelegate.swiftfaila ir jāpievieno fails failā, kas atrodas didFinishLaunchingWithOptionsgarām šim koda fragmentam   return:

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

Kodam vajadzētu izskatīties šādi:

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 }

Tagad jums vajadzētu būt iespējai palaist lietotni un redzēt backgroundColormainīto uz purple:

Nākamais solis ir izkārtojuma sadalīšana un telpas sadalīšana vienādi starp sekcijām.

Definēsim savas metodes CollectionView.

Darbības:

  • Reģistrējiet atkārtoti lietojamu šūnu ar unikālu identifikatoru
  • Sadaļā definējiet vienumu skaitu
  • Izmantojiet reģistrēto šūnu  

Lai izmantotu dažas CollectionViewmetodes, mums vienmēr ir jāatbilst UICollectionViewDelegateFlowLayoutsuperklasei un jāiegūst metožu automātiskā pabeigšana. Tātad sāksim ar CollectionViewCell reģistrāciju.

Iekšpusē View.DidLoad()mēs saucam collectionView.register()par atkārtoti izmantojamās šūnas reģistrēšanas metodi:

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

Tad mēs definējam šūnu skaitu, kas mums būs iekšpusē, collectionViewizmantojot numberOfItemsInSection. Pagaidām mums vienkārši jāpadara 5 vienumi:

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

Nākamais solis ir definēt atkārtoti lietojamu šūnu, izmantojot to, cellForItemAtkurai vajadzētu atgriezties UICollectionViewCellun kurai ir unikāls ID cellId. Kods izskatās šādi:

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

Pilnam kodam vajadzētu izskatīties šādi:

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

Jums vajadzētu būt iespējai ekrānā redzēt 5 vienumus ar sarkanu fonu:

Pievienojiet šūnām pielāgotu platumu un augstumu

Tagad mums ir jānovieto šūnas pareizā secībā un jādod tām widthun height. Katra šūna widthekrānā redzēs kā width.

Mums ir paveicies, ka sizeForItemAtmums ir metode, lai mēs varētu dot šūnām pielāgotu widthun height. Tā ir metode, kurai jāatgriež CGSizetips:

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

Tāpēc mēs veicām ekrāna   Celluzņemšanu width, izmantojot, view.frame.widthun pielāgotais heightir CGFloatveids.

Tagad jūs varat redzēt rezultātu zemāk savā simulatorā:

Pagaidām viss izskatās labi. Šoreiz izveidosim pielāgotu šūnu, kuru var izmantot atkārtoti. Izveidojiet jaunu Swift failu ar nosaukumu CustomCell:

CustomCell.swift vajadzētu izskatīties šādi zemāk:

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

Tagad nākamās lietas, kas mums jādara, ir pārveidot divas metodes, lai atbalstītu atkārtoti lietojamo šūnu, collectionView.registerun cellForItemAt. Vispirms modificēsim reģistra metodi. AizvietotUICollectionViewCell.selfar CustomCell:

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

Tālāk mums ir jāraida, cellForItemAtlai tie atbilstu CustomCellzemāk norādītajam:

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

Ja izmantojat lietotni, iespējams, nemanīsit nekādas izmaiņas, tāpēc piešķiriet CustomCell backgroundColor backgroundColor = .yellow. Neaizmirstiet noņemt līniju cell.backgroundColor = .red, kas cellForItemAt. Jums vajadzētu redzēt, ka fona krāsa ir mainīta uz dzeltenu?

Tagad ir pienācis laiks ielikt sāli CutomCell: D

Ja paskatās uz Spotify sākuma ekrānu, katra sadaļa, kas ir CustomCellmūsu piemērā, satur sadaļas virsrakstu, apakššūnas un ir horizontāla:

Pievienojiet sadaļas nosaukumu

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.

Pēdējās lietas, ko mēs varam darīt pirms šī raksta beigām, ir padarīt subCellssadaļas augstumu un platumu. Atkal mēs izmantojam sizeForItemAtdefinēt heightun widthšūnas.

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

Un šeit mēs esam:

JAUKS! Es apstāšos šajā brīdī, tāpēc šis ieraksts nav pārāk garš. Es izveidošu otro daļu, kur mēs pievienosim dažus izsmietos attēlus un aizpildīsim to ar dažiem datiem.

Pilns pirmkods? šeit

Lūdzu, lūdzu, ja jums ir kādi papildinājumi, jautājumi vai labojumi, ievietojiet to zemāk esošajos komentāros? vai iesit mani Twitter.

Abonējiet manu e-pasta sarakstu, lai saņemtu paziņojumu, kad tiks publicēta šīs apmācības otrā daļa