प्रोग्रामेटिक रूप से ऑटोलाउट के साथ स्पॉटिफाई यूआई क्लोन बनाने पर एक लेख का यह दूसरा भाग है। यदि आप पहले भाग से चूक गए हैं, तो कोई चिंता नहीं - बस कृपया जाकर इसे अभी देखें।
इस लेख में, हम कुछ नकली तस्वीरें जोड़ने जा रहे हैं और UI को Spotify के समान बनाने का प्रयास करेंगे।
आज हम यही करने जा रहे हैं?
पहले भाग में हमें यही छोड़ दिया गया था:
अगला कदम अनुकूलित सेल बनाना है। तो चलिए SubCustomCell
. नाम से एक बनाकर शुरू करते हैं ।
सबसे पहले, प्रोजेक्ट फ़ोल्डर के अंदर एक नई स्विफ्ट फ़ाइल बनाएं और इसे SubCustomCell.swift
. नाम दें . इस फ़ाइल में हमारा कस्टम सेल होगा जो प्लेलिस्ट का प्रतिनिधित्व करेगा। फ़ाइल बनाने के बाद, नीचे दिए गए कोड में जोड़ने का प्रयास करें और सेल को प्रारंभ करें, शायद backgroundColor
. के साथ , जब हम सेल को collectionView
. के साथ पंजीकृत करते हैं तो UI परिवर्तन देखने के लिए .
import UIKit
class SubCustomCell: UICollectionViewCell {
override init(frame: CGRect) {
super.init(frame: frame)
backgroundColor = .red
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}
फिर हम SubCustomCell
. रजिस्टर करते हैं अंदर CustomCell.swift
init
. के अंदर खंड मैथा। बदलें UICollectionViewCell.self
नीचे की तरह।SubCustomCell
. के साथ
collectionView.register(SubCustomCell.self, forCellWithReuseIdentifier: cellId)
साथ ही हमें cellForItemAt
. में संशोधन करने की आवश्यकता है विधि और इसे SubCustomCell
. के अनुरूप बनाएं निम्नलिखित की तरह।
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: cellId, for: indexPath) as! SubCustomCell
// cell.backgroundColor = .yellow
return cell
}
आपको देखना चाहिए backgroundColor
red
. में बदला गया ।
इस बिंदु तक सब कुछ सीधा और स्पष्ट होना चाहिए।
अब हम कुछ नकली चित्रों के साथ कोशिकाओं को भरने जा रहे हैं और एक ImageView
बना रहे हैं प्रत्येक कोशिका के अंदर। मैंने पहले से ही pexels.com से कुछ यादृच्छिक चित्र डाउनलोड कर लिए हैं, लेकिन बेझिझक अपनी पसंद की किसी भी तस्वीर (इनमें से) का उपयोग कर सकते हैं। आप उन्हें Github पर प्रोजेक्ट फ़ाइलों में पा सकते हैं।
आइए बनाते हैं UIImageView
अंदर SubCustomCell.swift
और कुछ बाधाएँ बनाएँ।
let ImageView : UIImageView = {
let iv = UIImageView()
iv.backgroundColor = .yellow
return iv
}()
और इसे view
. में जोड़ें init
. के अंदर addSubView
. का उपयोग करके ब्लॉक करें ।
override init(frame: CGRect) {
super.init(frame: frame)
addSubview(ImageView)
}
अब चलिए ImageView
बनाते हैं सेल के भीतर सभी जगह नीचे की बाधाओं के साथ लें।
ImageView.translatesAutoresizingMaskIntoConstraints = false
ImageView.topAnchor.constraint(equalTo: topAnchor).isActive = true
ImageView.leftAnchor.constraint(equalTo: leftAnchor).isActive = true
ImageView.rightAnchor.constraint(equalTo: rightAnchor).isActive = true
ImageView.bottomAnchor.constraint(equalTo: bottomAnchor).isActive = true
LeftAnchor
सेल के बाएं एंकर का प्रतिनिधित्व करता हैrightAnchor
सेल के दाहिने एंकर का प्रतिनिधित्व करता हैbottomAnchor
सेल के निचले एंकर का प्रतिनिधित्व करता हैtopAnchor
सेल के शीर्ष एंकर का प्रतिनिधित्व करता है
और ImageView
बनाकर का शीर्ष एंकर सेल के शीर्ष एंकर के बराबर है (और ImageView
. के लिए भी ऐसा ही कर रहा है बाएँ, दाएँ, और निचला लंगर) यह ImageView
बनाता है SubCustomCell
. का पूरा स्थान ले लें (सेल)।
नोट:सबसे पहले आपको translatesAutoresizingMaskIntoConstraints
. का उपयोग करना होगा तत्वों के लिए बाधाओं को लागू करने में सक्षम होने के लिए। साथ ही isActive
. पर कॉल करना न भूलें संपत्ति और इसे true
. पर असाइन करें - ऐसा किए बिना बाधाएं काम नहीं करेंगी और कुछ भी नहीं बदलेगा।
ImageView
एक छवि होनी चाहिए, तो चलिए एक जोड़ते हैं।
let ImageView : UIImageView = {
let iv = UIImageView()
iv.backgroundColor = .yellow
// we have >image1< file inside the project
iv.image = UIImage(named: "image1")
iv.contentMode = .scaleAspectFill
iv.clipsToBounds = true
return iv
}()
और यदि आप ऐप बनाते और चलाते हैं, तो आपको हमारे द्वारा SubCustomCell
में जोड़े गए परिणाम और चित्र देखने चाहिए ।
ठंडा ?। अब एक तत्व है जिसे हमें SubCustomCell
. में जोड़ना चाहिए खत्म करने के लिए। हमें एक शीर्षक चाहिए जो प्लेलिस्ट के शीर्षक का प्रतिनिधित्व करे:UILabel
।
शीर्षक के लिए यह इस प्रकार होगा:
let TitleLabel : UILabel = {
let lb = UILabel()
lb.textColor = UIColor.lightGray
lb.font = UIFont.systemFont(ofSize: 16)
lb.font = UIFont.boldSystemFont(ofSize: 20)
lb.text = "Evening Music"
return lb
}()
मैं बस वहां कुछ यादृच्छिक पाठ डालता हूं - आप जो चाहें डाल सकते हैं। अगला कदम तत्व को दृश्य में जोड़ना और इसे कुछ बाधाएं देना है। शीर्षक ImageView
. के नीचे रखा जाएगा ।
देखने के लिए जोड़ें:
addSubview(TitleLabel)
ImageView
दोनों के लिए बाधाओं को लागू करना और TitleLabel
ImageView.translatesAutoresizingMaskIntoConstraints = false
ImageView.topAnchor.constraint(equalTo: topAnchor).isActive = true
ImageView.leftAnchor.constraint(equalTo: leftAnchor).isActive = true
ImageView.rightAnchor.constraint(equalTo: rightAnchor).isActive = true
ImageView.heightAnchor.constraint(equalToConstant: 240).isActive = true
ImageView.bottomAnchor.constraint(equalTo: TitleLabel.topAnchor).isActive = true
TitleLabel.translatesAutoresizingMaskIntoConstraints = false
TitleLabel.topAnchor.constraint(equalTo: ImageView.bottomAnchor,constant: 10).isActive = true
TitleLabel.leftAnchor.constraint(equalTo: leftAnchor, constant: 5).isActive = true
TitleLabel.rightAnchor.constraint(equalTo: rightAnchor, constant: -5).isActive = true
और ये रहा!
हमने चित्र को सेल में अधिकांश स्थान पर कब्जा कर लिया है, और शेष शीर्षक द्वारा लिया गया है। जैसा कि आप देख सकते हैं, आप प्रत्येक अनुभाग में क्षैतिज रूप से और संपूर्ण स्क्रीन में लंबवत रूप से स्क्रॉल कर सकते हैं।
अब हम कोशिकाओं में कुछ नकली डेटा डालते हैं ताकि यह महसूस हो सके कि यह वास्तविक है। उसके लिए मैंने एक JSON
बनाया है फ़ाइल जिसमें अनुभागों और प्लेलिस्ट के लिए कुछ यादृच्छिक डेटा होता है।
पहले दो स्ट्रक्चर बनाते हैं, Section
और Playlist
. हम प्रत्येक संरचना के लिए एक अलग फ़ाइल बनाते हैं।
section.swift
import Foundation
struct Section {
var title : String
var playlists : NSArray
init(dictionary:[String : Any]) {
self.title = dictionary["title"] as? String ?? ""
self.playlists = dictionary["playlists"] as? NSArray ?? []
}
}
playlist.swift
//
// playlist.swift
// spotifyAutoLayout
//
// Created by admin on 12/6/19.
// Copyright © 2019 Said Hayani. All rights reserved.
//
import Foundation
struct PlayList {
var title: String
var image : String
init(dictionary : [String : Any]) {
self.title = dictionary["title"] as? String ?? ""
self.image = dictionary["image"] as? String ?? ""
}
}
और फिर ViewController.swift
. के अंदर हम एक फ़ंक्शन बनाते हैं जो हमारे लिए JSON प्राप्त करता है और परिणामों को एक सरणी में संग्रहीत करता है।
print("attempt to fetch Json")
if let path = Bundle.main.path(forResource: "test", ofType: "json") {
do {
let data = try Data(contentsOf: URL(fileURLWithPath: path), options: .mappedIfSafe)
let jsonResult = try JSONSerialization.jsonObject(with: data, options: .mutableLeaves)
if let jsonResult = jsonResult as? [ Any] {
// do stuff
jsonResult.forEach { (item) in
let section = Section(dictionary: item as! [String : Any])
// print("FEtching",section.playlists)
self.sections.append(section)
}
self.collectionView.reloadData()
}
} catch {
// handle error
}
}
}
fetchJson
फ़ंक्शन को ViewDidLoad
. के भीतर कॉल किया जाता है तरीका। हमारे पास sections
. नामक एक वेरिएबल भी है जहां हम परिणाम संग्रहीत करते हैं:
var sections = [Section]()
अगला कदम ViewController
. से डेटा पास करना है से CustomCell
. उसके लिए हम CustomCell
. के अंदर एक वेरिएबल बनाते हैं जो प्रत्येक अनुभाग के लिए डेटा प्राप्त करेगा:
var section : Section?{
didSet{
print("section ✅",self.section)
}
}
हम cellForItemAt
. का उपयोग करते हैं ViewController
. के अंदर डेटा को सीधे CustomCell
. पर भेजने की विधि ।
override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: cellId, for: indexPath) as! CustomCell
cell.section = sections[indexPath.item]
return cell
}
नोट:हम हमेशा self
. पर कॉल करते हैं .collectionView.reloadData()
हर बार fetchJson
इसलिए नीचे दिए गए ब्लॉक को CustomCell
. के अंदर कहा जाता है , को भी बुलाया जाएगा। कंसोल की जाँच करें, shift
+ कमांड + सी:
var section : Section? {
didSet{
print("section ✅",self.section)
}
}
पहली चीज़ जो हम बदलते हैं वह है अनुभाग का शीर्षक सेट करना:
var section : Section? {
didSet{
print("section ✅",self.section)
guard let section = self.section else {return}
self.titleLabel.text = section.title
}
}
और फिर आपको यह देखना चाहिए कि स्क्रीन पर प्रत्येक अनुभाग का एक विशिष्ट शीर्षक है?.
अब डेटा को SubCustomCell
. पर भेजने का समय आ गया है . हम वही करते हैं जो हमने ऊपर किया था। हमें playlists
. पास करना होगा सरणी, इसलिए हम playlists
. नामक एक चर बनाते हैं अंदर CustomCell
।
var playlists : [PlayList]() //empty
सबसे पहले, हम playlists
. के माध्यम से मैप करते हैं JSON
. से . फिर हम प्रत्येक प्लेलिस्ट को playlists
. के साथ जोड़ते हैं वर.
var section : Section? {
didSet{
print("section ✅",self.section)
guard let section = self.section else {return}
self.titleLabel.text = section.title
// append to playlists array
self.section?.playlists.forEach({ (item) in
let playlist = PlayList(dictionary: item as! [String : Any])
self.playlists.append(playlist)
})
self.collectionView.reloadData()
}
}
ध्यान! यदि आप ऐप को चलाने का प्रयास करते हैं तो यह क्रैश हो सकता है। ऐसा इसलिए है क्योंकि हम अनुभागों की संख्या निर्धारित करना भूल गए हैं। चूंकि अब हम JSON से डेटा प्राप्त कर रहे हैं, इसलिए हमारे पास मौजूद अनुभागों की संख्या के आधार पर संख्या गतिशील होनी चाहिए। अनुभागों की संख्या JSON
. के अंदर अनुभागों की संख्या के बराबर होनी चाहिए , इसलिए हमें numberOfItemsInSection
. को संशोधित करने की आवश्यकता है अंदर ViewController
नीचे के लिए:
override func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return sections.count
}
हम CustomCell.swift
. के अंदर उसी तरीके से वही काम करते हैं - लेकिन यहां हम playlists
. की संख्या पर विचार करते हैं इसके बजाय।
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return self.playlists.count
}
अंतिम चरण जो हमें पूरा करना है वह है प्रत्येक एकल प्लेलिस्ट को पास करना Object
से SubCustomCell
cellForItemAt
. के भीतर CustomCell.swift
. में .
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: cellId, for: indexPath) as! SubCustomCell
// here ?
cell.playlist = playlists[indexPath.item]
return cell
}
और हम उस डेटा को SubCustomCell
. के अंदर प्राप्त करने जा रहे हैं playlist
. के माध्यम से चर और अंत में प्लेलिस्ट का शीर्षक और छवि प्रदर्शित करें।
var playlist : PlayList? {
didSet{
print("Playlist ?",self.playlist)
guard let playlist = self.playlist else {return}
// The Image ?
self.ImageView.image = UIImage(named: playlist.image)
// the playlist title ?
self.TitleLabel.text = self.playlist?.title
}
}
मुझे लगता है कि अब सब कुछ ठीक काम करना चाहिए, ठीक नीचे की तरह ?
UI के लिए एक आखिरी अपडेट:हमें section
. में कुछ पैडिंग और मार्जिन जोड़ना होगा और playlist
शीर्षक और प्लेलिस्ट को थोड़ा छोटा करें।
आइए पहले अनुभाग शीर्षकों के लिए कुछ पैडिंग जोड़ें। ऐसा करने के लिए, हमें केवल constant
. देना होगा संपत्ति अनुभाग सेल के अंदर कुछ संख्या मान CustomCell
और setupSubCells
. के भीतर :
collectionView.topAnchor.constraint(equalTo: titleLabel.bottomAnchor,constant: 15).isActive = true
और अगर आपको पूरा collectionView
दिखाई देता है titleLabel
में सबसे नीचे आएं , हमें केवल 15
. जोड़कर अधिक स्थान जोड़ने की आवश्यकता है :
इसके बाद हम playlist
. के शीर्षक पर आते हैं . यह SubCustomCell
. के अंदर होगा , और हमें केवल ImageView के निचले भाग में अधिक स्थान जोड़ने की आवश्यकता है।
ImageView.bottomAnchor.constraint(equalTo: TitleLabel.topAnchor,constant: -15).isActive = true
हमारे पास पहले से ही स्थिर है। इसके काम करने के लिए, मान -15
. होना चाहिए
अंत में प्लेलिस्ट को थोड़ा छोटा करने की जरूरत है। यह आसान है:हम सिर्फ playlist
. बनाते हैं सेल की ऊंचाई और चौड़ाई section
. के बराबर है सेल की ऊंचाई 2 से विभाजित, ठीक नीचे की तरह:
CustomCell.swift
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
let width = frame.height / 2
let height = frame.height / 2
return CGSize(width: width, height: height)
}
ImageView की ऊंचाई 150
. के बराबर बनाएं साथ ही।
//SubCutomCell.swift
ImageView.heightAnchor.constraint(equalToConstant: 150).isActive = true
और यहाँ हम चलते हैं?.
उत्तम! मुझे लगता है कि आज के लिए इतना ही काफी है - मैं इस लेख को बहुत लंबा नहीं बनाना चाहता। तो हमारे पास एक और हिस्सा होगा जहां हम TabBar
जोड़ेंगे और विवरण, साथ ही प्लेलिस्ट के लिए कुछ आइकन।
देखें GitHub पर पूर्ण स्रोत कोड ?.
आपके समय के लिए धन्यवाद। मुझे आशा है कि मैंने कुछ भी याद नहीं किया है। अगर मैंने ट्विटर पर मेरा @ उल्लेख किया है, या यदि आपके कोई प्रश्न हैं या इस पोस्ट के अलावा कोई भी है तो दरवाजे हमेशा किसी के लिए खुले हैं। धन्यवाद??.
सदस्य बनें इस ट्यूटोरियल का तीसरा भाग प्रकाशित होने पर अधिसूचित होने के लिए मेरी ईमेल सूची में।
वैसे, मैंने हाल ही में अपने एक मोबाइल एप्लिकेशन के लिए सॉफ्टवेयर इंजीनियरों के एक मजबूत समूह के साथ काम किया है। संगठन बहुत अच्छा था, और उत्पाद को अन्य फर्मों और फ्रीलांसरों की तुलना में बहुत तेज़ी से वितरित किया गया था, और मुझे लगता है कि मैं ईमानदारी से उन्हें अन्य परियोजनाओं के लिए अनुशंसा कर सकता हूं। अगर आप संपर्क करना चाहते हैं तो मुझे ईमेल करें — [email protected].