ในโพสต์นี้ เราจะพยายามสร้างเค้าโครงหน้าจอหลักของ Spotify ใหม่ใน Swift โดยทางโปรแกรม ทำไมต้องเป็นโปรแกรม? ฉันคิดว่ามันดีเสมอที่รู้วิธีสร้างสิ่งต่าง ๆ ในรูปแบบต่างๆ และฉันชอบเขียนโค้ดเพื่อทำสิ่งต่าง ๆ โดยทางโปรแกรม ทักษะเหล่านี้มีประโยชน์อย่างยิ่งหากคุณทำงานกับทีมหรือใช้การควบคุมเวอร์ชัน
นี่คือหน้าจอหลักของแอพมือถือของ Spotify เพื่อให้ได้เลย์เอาต์แบบนี้ เราจะใช้ UICollectionView
และเราอาจใช้ TabBarController
เพื่อสร้างตัวนำทางแท็บด้วย
ข้อกำหนดพื้นฐาน :ก่อนอื่นตรวจสอบให้แน่ใจว่าคุณได้ติดตั้ง Xcode +10 และรวดเร็ว +4 แล้ว
เริ่มต้นด้วยการสร้างโปรเจ็กต์ Xcode ใหม่โดยใช้ Xcode:
และสิ่งแรกที่เราต้องทำใน ViewController.swift
คือเปลี่ยน superClass เป็น UICollectionViewController
แทน UIViewController
เพราะคลาสของเราจะขึ้นอยู่กับ 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.
}
}
หากคุณพยายามเรียกใช้แอป บิลด์จะล้มเหลว เราจำเป็นต้องเพิ่มโค้ดบางส่วนใน AppDelegate.swift
ภายในไฟล์ didFinishLaunchingWithOptions
ฟังก์ชันผ่านโค้ดชิ้นนี้ก่อน return
คำสั่ง:
let layout = UICollectionViewFlowLayout()
window = UIWindow()
window?.rootViewController = ViewController(collectionViewLayout: layout)
และโค้ดควรมีลักษณะดังนี้:
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
}
ตอนนี้คุณควรจะสามารถเรียกใช้แอปและดู backgroundColor
เปลี่ยนเป็น purple
:
ขั้นตอนต่อไปคือการกระจายเลย์เอาต์และแบ่งพื้นที่ว่างระหว่างส่วนเท่าๆ กัน
มากำหนดวิธีการของ CollectionView
. ของเรากัน .
ขั้นตอน:
- ลงทะเบียนเซลล์ที่ใช้ซ้ำได้ด้วยตัวระบุที่ไม่ซ้ำกัน
- กำหนดจำนวนรายการในส่วน
- ใช้เซลล์ที่ลงทะเบียน
การใช้งาน CollectionView
. บางส่วน วิธีที่เราต้องปฏิบัติตาม UICollectionViewDelegateFlowLayout
. เสมอ เป็น superClass และรับ autoComplete ของเมธอด เริ่มด้วยการลงทะเบียน CollectionViewCell
ข้างใน View.DidLoad()
เราเรียก collectionView.register()
วิธีการลงทะเบียนเซลล์ที่ใช้ซ้ำได้:
collectionView.register(UICollectionViewCell.self, forCellWithReuseIdentifier: cellId)
จากนั้นเราจะกำหนดจำนวนเซลล์ที่เราจะมีใน collectionView
โดยใช้ numberOfItemsInSection
. สำหรับตอนนี้เราแค่ต้องทำ 5 รายการ:
override func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return 5
}
ขั้นตอนต่อไปคือการกำหนดเซลล์ที่ใช้ซ้ำได้โดยใช้ cellForItemAt
ที่ควรส่งคืน UICollectionViewCell
และมีรหัสเฉพาะที่เรียกว่า cellId
. รหัสมีลักษณะดังนี้:
override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: cellId, for: indexPath)
cell.backgroundColor = .red
return cell
}
รหัสเต็มควรมีลักษณะดังนี้:
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
}
}
คุณควรจะเห็น 5 รายการที่มีพื้นหลังสีแดงบนหน้าจอ:
เพิ่มความกว้างและความสูงที่กำหนดเองให้กับเซลล์
ตอนนี้เราต้องจัดเซลล์ในลำดับที่ถูกต้องและให้ width
และ height
. แต่ละเซลล์จะใช้ width
ของหน้าจอเป็น width
.
เราโชคดีที่มี sizeForItemAt
วิธีการเพื่อให้เราสามารถกำหนด width
. ให้กับเซลล์ได้ และ height
. เป็นวิธีที่ควรส่งคืน CGSize
ประเภท:
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)
}
เราก็เลยสร้าง Cell
เอา width
ของหน้าจอโดยใช้ view.frame.width
และ height
custom ที่กำหนดเอง โดยมีเป็น CGFloat
ชนิด
ตอนนี้คุณสามารถเห็นผลด้านล่างในโปรแกรมจำลองของคุณ :
ทุกอย่างดูดีจนถึงตอนนี้ คราวนี้เรามาสร้างเซลล์แบบกำหนดเองที่สามารถนำกลับมาใช้ใหม่ได้ สร้างไฟล์ Swift ใหม่ชื่อ CustomCell
:
CustomCell.swift
ควรมีลักษณะดังนี้:
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")
}
}
สิ่งต่อไปที่เราต้องทำคือปรับเปลี่ยนสองวิธีเพื่อรองรับเซลล์ที่ใช้ซ้ำได้ collectionView.register
และ cellForItemAt
. มาแก้ไขวิธีการลงทะเบียนกันก่อน แทนที่ UICollectionViewCell.self
ด้วย CustomCell
:
collectionView.register(UICollectionViewCell.self, forCellWithReuseIdentifier: cellId)
ต่อไปเราต้องแคสต์ cellForItemAt
เพื่อให้เป็นไปตาม CustomCell
ชอบด้านล่าง:
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: cellId, for: indexPath) as! CustomCell
หากคุณเปิดแอปนี้ คุณจะไม่สังเกตเห็นการเปลี่ยนแปลงใดๆ ดังนั้นให้ CustomCell เป็น backgroundColor backgroundColor = .yellow
. อย่าลืมลบบรรทัด cell.backgroundColor = .red
ใน cellForItemAt
. คุณควรเห็นสีพื้นหลังเปลี่ยนเป็นสีเหลือง ?
ตอนนี้ได้เวลาใส่เกลือลงใน CutomCell
:D
หากคุณดูที่หน้าจอหลักของ Spotify แต่ละส่วนคือ CustomCell
ในตัวอย่างของเราประกอบด้วยชื่อส่วน เซลล์ย่อย และเป็นแนวนอน:
เพิ่มชื่อหัวข้อ
มาเพิ่มป้ายชื่อลงในเซลล์กันเถอะ สร้าง titleLabel
องค์ประกอบภายใน CutomCell
คลาส:
let titleLabel: UILabel = {
let lb = UILabel()
lb.text = "Section Title"
lb.font = UIFont.boldSystemFont(ofSize: 14)
lb.font = UIFont.boldSystemFont(ofSize: 14)
return lb
}()
จากนั้นเพิ่มองค์ประกอบในมุมมองภายใน init()
บล็อก:
addSubview(titleLabel)
หากคุณเรียกใช้แอป คุณจะไม่เห็นการเปลี่ยนแปลงใดๆ และนั่นเป็นเพราะเรายังไม่ได้กำหนดข้อจำกัดใดๆ ให้กับองค์ประกอบ มาเพิ่มข้อจำกัดบางอย่างกัน – เพิ่มคุณสมบัตินี้ lb.translatesAutoresizingMaskIntoConstraints = false
ถึง titleLabel
เพื่อให้สามารถใช้ข้อจำกัดกับองค์ประกอบได้:
หลังจากที่เราเพิ่ม titleLabel
สำหรับมุมมอง เรากำหนดข้อจำกัด:
addSubview(titleLabel)
titleLabel.topAnchor.constraint(equalTo: topAnchor, constant: 8).isActive = truetitleLabel.leftAnchor.constraint(equalTo: leftAnchor,constant: 8 ).isActive = true
อย่าลืมเพิ่ม .isActive = true
. ทุกครั้ง คุณสมบัติ – หากไม่มีข้อ จำกัด จะไม่ทำงาน!
ก่อนที่เราจะไปต่อในตอนต่อไป เรามาเปลี่ยนสีพื้นหลังของหน้าจอเป็นสีดำกันก่อนและเอาสีเหลืองของเซลล์ออกก่อน:
มาถึงส่วนสำคัญ:การวางเซลล์ย่อยลงในแต่ละเซลล์ เพื่อให้บรรลุเป้าหมายนั้น เราจะเพิ่ม CollectionView
ภายใน CustomCell
.
วิธีเพิ่ม CollectionView
ภายใน UICollectionViewCell
เราต้องเพิ่มคุณสมบัติ UICollectionViewDelegate
, UICollectionViewDelegateFlowLayout
และ UICollectionViewDataSource
เป็น superClass ถึง CustomCell
.
มาสร้าง collectionView
. กันเถอะ องค์ประกอบตามมุมมองง่ายๆ:
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
}()
สังเกตว่าเราเพิ่ม layout
ไปที่ collectionView
เป็นเลเยอร์ใน initializer เหมือนกับที่เราทำครั้งแรกกับ viewController.swift
. ที่นี่เรายังระบุทิศทางของ FlowLayout
เป็น .horizontal
.
มาเพิ่ม collectionView
. กัน องค์ประกอบไปยังมุมมองเป็นมุมมองย่อย
เราจะสร้างฟังก์ชันที่ทำอย่างนั้นเพื่อให้โค้ดสะอาดขึ้นเล็กน้อย
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
}
อย่าลืมตั้งค่าผู้รับมอบสิทธิ์เป็น self
สำหรับ collectionView
และแหล่งข้อมูลด้วย:
collectionView.dataSource = self
collectionView.delegate = self
จากนั้นเรียกใช้ฟังก์ชันภายใน init
บล็อก
Xcode จะแสดงข้อผิดพลาดบางอย่างหากคุณพยายามสร้างแอปเพราะเราไม่ปฏิบัติตาม UICollectionViewDelegate
และ UICollectionViewDelegateFlowLayout
โปรโตคอล ในการแก้ไขปัญหานี้ เราต้องลงทะเบียนเซลล์ย่อยเป็นเซลล์ที่ใช้ซ้ำได้ก่อน
สร้างตัวแปรที่ด้านบนของคลาสและตั้งชื่อ cellId
เพื่อให้เราใช้เมื่อเราต้องการตัวระบุเซลล์:
let cellId : String = "subCellID"
collectionView.register(UICollectionViewCell.self, forCellWithReuseIdentifier: cellId)
ตอนนี้เรายังขาดอีกสองวิธีในการแก้ไขข้อผิดพลาด:numberOfItemsInSection
ที่กำหนดจำนวนเซลล์ในส่วนและ cellForItemAt
ที่กำหนดเซลล์ที่ใช้ซ้ำได้ วิธีการเหล่านี้จำเป็นสำหรับ collectionView
เพื่อให้ทำงานได้อย่างถูกต้อง:
// 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
}
ผลลัพธ์ควรมีลักษณะดังนี้:
อย่างที่คุณเห็น collectionView
เป็นสีม่วงเป็นพื้นหลังและเซลล์ย่อยเป็นสีเหลือง
สิ่งสุดท้ายที่เราทำได้ก่อนจบบทความนี้คือทำ subCells
มีความสูงของส่วนและเป็นความกว้าง อีกครั้งที่เราใช้ sizeForItemAt
เพื่อกำหนด height
และ width
ของเซลล์ .
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)
}
แล้วเราล่ะ ?:
ดี! ฉันจะหยุดที่จุดนี้ เพื่อไม่ให้โพสต์นี้ยาวเกินไป ฉันจะทำส่วนที่สองที่เราจะเพิ่มรูปภาพจำลองและกรอกข้อมูลบางส่วน
รหัสที่มาแบบเต็ม ? ที่นี่
ได้โปรดโปรดถ้าคุณมีคำถามเพิ่มเติมหรือแก้ไขใด ๆ โพสต์ไว้ในความคิดเห็นด้านล่าง ? หรือติดต่อฉันทาง Twitter
สมัครสมาชิก ไปยังรายชื่ออีเมลของฉันเพื่อรับการแจ้งเตือนเมื่อมีการเผยแพร่ส่วนที่สองของบทช่วยสอนนี้