Użyj tej metody, aby ustawić niestandardową szerokość wysokości komórki.
Pamiętaj, aby dodać te protokoły
UICollectionViewDelegate
UICollectionViewDataSource
UICollectionViewDelegateFlowLayout
Jeśli używasz Swift 5 lub Xcode 11 i później trzeba ustawić Estimate Size
do none
korzystania storyboard, aby to działało poprawnie. Jeśli tego nie ustawisz, poniższy kod nie będzie działał zgodnie z oczekiwaniami.
Swift 4 lub później
extension YourViewController: UICollectionViewDelegate {
}
extension YourViewController: UICollectionViewDataSource {
}
extension YourViewController: UICollectionViewDelegateFlowLayout {
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
return CGSize(width: screenWidth, height: screenWidth)
}
}
Cel C
@interface YourViewController : UIViewController<UICollectionViewDelegate,UICollectionViewDataSource,UICollectionViewDelegateFlowLayout>
- (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath
{
return CGSizeMake(CGRectGetWidth(collectionView.frame), (CGRectGetHeight(collectionView.frame)));
}
Pamiętaj, aby dodać protokół
UICollectionViewDelegateFlowLayout
w swojejclass
deklaracjiclass MyCollectionViewController: UICollectionViewController, UICollectionViewDelegateFlowLayout { //MARK: - UICollectionViewDelegateFlowLayout func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize { return CGSize(width: 100.0, height: 100.0) } }
źródło
Jeśli ktoś korzysta ze scenorysu i przesłania UICollectionViewDelegateFlowLayout, wówczas w Swift 5 i Xcode 11 również ustaw Szacunkowy rozmiar na Brak
źródło
UICollectionViewFlowLayout
wydaje się domyślnieestimatedItemSize
doUICollectionViewFlowLayout.automaticSize
przy użyciu IB mimo że dokumentacja mówi, powinien on domyślnieCGSizeZero
. Jak stwierdza Apple,automaticSize
„włącza samodopasowanie rozmiaru komórek do widoku kolekcji”. Dlatego inne zmiany rozmiaru w IB nic nie robią.Wreszcie otrzymałem odpowiedź. Powinieneś rozszerzyć
UICollectionViewDelegateFlowLayout
To powinno działać z odpowiedziami powyżej.
źródło
Masz 2 sposoby, aby zmienić rozmiar CollectionView.
Pierwszy sposób -> dodaj ten protokół UICollectionViewDelegateFlowLayout
for W moim przypadku chcę podzielić komórkę na 3 części w jednej linii. Zrobiłem ten kod poniżej
extension ViewController: UICollectionViewDelegate, UICollectionViewDataSource ,UICollectionViewDelegateFlowLayout{ func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize { // In this function is the code you must implement to your code project if you want to change size of Collection view let width = (view.frame.width-20)/3 return CGSize(width: width, height: width) } func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int { return collectionData.count } func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell { let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "CollectionViewCell", for: indexPath) if let label = cell.viewWithTag(100) as? UILabel { label.text = collectionData[indexPath.row] } return cell } }
Drugi sposób -> nie musisz dodawać UICollectionViewDelegateFlowLayout, ale zamiast tego musisz napisać kod w funkcji viewDidload jako kod poniżej
class ViewController: UIViewController { @IBOutlet weak var collectionView1: UICollectionView! var collectionData = ["1.", "2.", "3.", "4.", "5.", "6.", "7.", "8.", "9.", "10.", "11.", "12."] override func viewDidLoad() { super.viewDidLoad() let width = (view.frame.width-20)/3 let layout = collectionView.collectionViewLayout as! UICollectionViewFlowLayout layout.itemSize = CGSize(width: width, height: width) } }
extension ViewController: UICollectionViewDelegate, UICollectionViewDataSource { func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int { return collectionData.count } func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell { let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "CollectionViewCell", for: indexPath) if let label = cell.viewWithTag(100) as? UILabel { label.text = collectionData[indexPath.row] } return cell } }
Cokolwiek napiszesz jako pierwszy lub drugi sposób, otrzymasz taki sam wynik jak powyżej. Napisałem to. U mnie to zadziałało
źródło
Stosunek rozmiaru w zależności od rozmiaru iPhone'a:
Oto, co możesz zrobić, aby mieć różną szerokość i wysokość komórek w odniesieniu do rozmiaru iPhone'a:
func collectionView(collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAtIndexPath indexPath: NSIndexPath) -> CGSize { let width = (self.view.frame.size.width - 12 * 3) / 3 //some width let height = width * 1.5 //ratio return CGSize(width: width, height: height) }
A może powinieneś również wyłączyć ograniczenia Autoukładu w komórce, aby ta odpowiedź zadziałała.
źródło
Widok kolekcji zawiera obiekt układu . W twoim przypadku jest to prawdopodobnie układ przepływu ( UICollectionViewFlowLayout ). Ustaw właściwość układu przepływu
itemSize
.źródło
w Swift3 i Swift4 możesz zmienić rozmiar komórki, dodając UICollectionViewDelegateFlowLayout i implementując to tak:
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize { return CGSize(width: 100, height: 100) }
lub jeśli programowo utworzysz UICollectionView, możesz to zrobić w ten sposób:
let layout = UICollectionViewFlowLayout() layout.scrollDirection = .horizontal //this is for direction layout.minimumInteritemSpacing = 0 // this is for spacing between cells layout.itemSize = CGSize(width: view.frame.width, height: view.frame.height) //this is for cell size let collectionView = UICollectionView(frame: self.view.bounds, collectionViewLayout: layout)
źródło
swift4 swift 4 widok kolekcji ios przykład Collectionview najnowszy kod roboczy xcode
Dodaj to w sekcji Delegat na górze
UICollectionViewDelegateFlowLayout
i użyj tej funkcji
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize { let width = (self.view.frame.size.width - 20) / 3 //some width let height = width * 1.5 //ratio return CGSize(width: width, height: height) }
///// przykładowy pełny kod
utwórz w widoku kolekcji i komórce widoku kolekcji w scenorysie podaj odniesienie do kolekcji jako
@IBOutlet słaby var cvContent: UICollectionView!
wklej to w widoku kontrolera
import UIKit class ViewController: UIViewController, UICollectionViewDelegate, UICollectionViewDataSource, UICollectionViewDelegateFlowLayout { var arrVeg = [String]() var arrFruits = [String]() var arrCurrent = [String]() @IBOutlet weak var cvContent: UICollectionView! override func viewDidLoad() { super.viewDidLoad() arrVeg = ["Carrot","Potato", "Tomato","Carrot","Potato", "Tomato","Carrot","Potato", "Tomato","Carrot","Potato", "Tomato"] arrVeg = ["Mango","Papaya","Orange","Mango","Papaya","Orange","Mango","Papaya","Orange","Mango","Papaya","Orange","Mango","Papaya","Orange","Mango","Papaya","Orange","Mango","Papaya","Orange","Mango","Papaya","Orange","Mango","Papaya","Orange","Mango","Papaya","Orange","Mango","Papaya","Orange","Mango","Papaya","Orange","Mango","Papaya","Orange","Mango","Papaya","Orange","Mango","Papaya","Orange","Mango","Papaya","Orange","Mango","Papaya","Orange","Mango","Papaya","Orange","Mango","Papaya","Orange","Mango","Papaya","Orange"] arrCurrent = arrVeg } //MARK: - CollectionView func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize { let width = (self.view.frame.size.width - 20) / 3 //some width let height = width * 1.5 //ratio return CGSize(width: width, height: height) } func numberOfSections(in collectionView: UICollectionView) -> Int { return 1 } func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int { return arrCurrent.count } func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell { let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "cell", for: indexPath) as! ContentCollectionViewCell cell.backgroundColor = UIColor.green return cell } }
źródło
Wypróbuj poniższą metodę
func collectionView(collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAtIndexPath indexPath: NSIndexPath) -> CGSize { return CGSize(width: 100.0, height: 100.0) }
źródło
Swift 5 programowo
lazy var collectionView: UICollectionView = { let layout = UICollectionViewFlowLayout() layout.scrollDirection = .horizontal //Provide Width and Height According to your need let cellWidth = UIScreen.main.bounds.width / 10 let cellHeight = UIScreen.main.bounds.height / 10 layout.itemSize = CGSize(width: cellWidth, height: cellHeight) //You can also provide estimated Height and Width layout.estimatedItemSize = CGSize(width: cellWidth, height: cellHeight) //For Setting the Spacing between cells layout.minimumInteritemSpacing = 0 layout.minimumLineSpacing = 0 return UICollectionView(frame: self.view.frame, collectionViewLayout: layout) }()
źródło
**Swift 5** To make this work you have to do the following. Add these protocols - UICollectionViewDelegate - UICollectionViewDataSource - UICollectionViewDelegateFlowLayout Your code will then look like this extension YourViewController: UICollectionViewDelegate { //Write Delegate Code Here } extension YourViewController: UICollectionViewDataSource { //Write DataSource Code Here } extension YourViewController: UICollectionViewDelegateFlowLayout { func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize { return CGSize(width: screenWidth, height: screenWidth) } } Now the final and crucial step to see this take effect is to go to your viedDidLoad function inside your Viewcontroller. override func viewDidLoad() { super.viewDidLoad() collection.dataSource = self // Add this collection.delegate = self // Add this // Do any additional setup after loading the view. } Without telling your view which class the delegate is it won't work.
źródło
# Absolutnie prosty sposób:
class YourCollection: UIViewController, UICollectionViewDelegate, UICollectionViewDataSource {
# Musisz dodać „UICollectionViewDelegateFlowLayout” lub nie ma autouzupełniania:
class YourCollection: UIViewController, UICollectionViewDelegate, UICollectionViewDataSource, UICollectionViewDelegateFlowLayout {
#Type „sizeForItemAt ...”. Jesteś skończony!
class YourCollection: UIViewController, UICollectionViewDelegate, UICollectionViewDataSource, UICollectionViewDelegateFlowLayout { func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize { return CGSize(width: 37, height: 63) }
Otóż to.
Na przykład, jeśli chcesz, aby „każda komórka wypełniała cały widok kolekcji”:
guard let b = view.superview?.bounds else { .. } return CGSize(width: b.width, height: b.height)
źródło
Innym sposobem jest ustawienie wartości bezpośrednio w układzie przepływu
let layout = collectionView.collectionViewLayout as! UICollectionViewFlowLayout layout.itemSize = CGSize(width: size, height: size)
źródło
Musisz więc ustawić z storyboardu dla atrybutu dla collectionView w sekcji komórki oszacowanie Size na none, aw swoim ViewController potrzebujesz metody delegata do implementacji tej metody:
optional func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize
źródło
Spróbuj użyć metody UICollectionViewDelegateFlowLayout. W Xcode 11 lub nowszym musisz ustawić Szacowany rozmiar na żaden z serii ujęć.
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize { let padding: CGFloat = 170 let collectionViewSize = advertCollectionView.frame.size.width - padding return CGSize(width: collectionViewSize/2, height: collectionViewSize/2) }
źródło
Prosty sposób:
Jeśli potrzebujesz tylko prostego stałego rozmiaru :
class SizedCollectionView: UIICollectionView { override func common() { super.common() let l = UICollectionViewFlowLayout() l.itemSize = CGSize(width: 42, height: 42) collectionViewLayout = l } }
To wszystko.
W scenorysie po prostu zmień klasę z UICollectionView na SizedCollectionView.
Ale !!!
Zwróć uwagę, że klasa bazowa to „UI 'I' CollectionView”. „I” dla inicjatora.
Nie jest łatwo dodać inicjator do widoku kolekcji. Oto typowe podejście:
Widok kolekcji ... z inicjatorem:
import UIKit class UIICollectionView: UICollectionView { private var commoned: Bool = false override func didMoveToWindow() { super.didMoveToWindow() if window != nil && !commoned { commoned = true common() } } internal func common() { } }
W większości projektów potrzebny jest „widok kolekcji z inicjatorem”. Więc prawdopodobnie i tak będziesz miał
UIICollectionView
(zwróć uwagę na dodatkowe I dla inicjatora!) W swoim projekcie.źródło
Swift 5, Programmatic UICollectionView ustawianie szerokości i wysokości komórki
// MARK: MyViewController final class MyViewController: UIViewController, UICollectionViewDataSource, UICollectionViewDelegateFlowLayout { private lazy var collectionViewLayout: UICollectionViewFlowLayout = { let layout = UICollectionViewFlowLayout() let spacing: CGFloat = 1 let numOfColumns: CGFloat = 3 let itemSize: CGFloat = (UIScreen.main.bounds.width - (numOfColumns - spacing) - 2) / 3 layout.itemSize = CGSize(width: itemSize, height: itemSize) layout.minimumInteritemSpacing = spacing layout.minimumLineSpacing = spacing layout.sectionInset = UIEdgeInsets(top: spacing, left: spacing, bottom: spacing, right: spacing) return layout }() private lazy var collectionView: UICollectionView = { let collectionView = UICollectionView(frame: view.bounds, collectionViewLayout: collectionViewLayout) collectionView.backgroundColor = .white collectionView.dataSource = self collectionView.delegate = self collectionView.translatesAutoresizingMaskIntoConstraints = false return collectionView }() override func viewDidLoad() { super.viewDidLoad() configureCollectionView() } private func configureCollectionView() { view.addSubview(collectionView) NSLayoutConstraint.activate([ collectionView.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor), collectionView.bottomAnchor.constraint(equalTo: view.safeAreaLayoutGuide.bottomAnchor), collectionView.leadingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.leadingAnchor), collectionView.trailingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.trailingAnchor) ]) collectionView.register(PhotoCell.self, forCellWithReuseIdentifier: "PhotoCell") } // MARK: UICollectionViewDataSource func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int { return 20 } func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell { let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "PhotoCell", for: indexPath) as! PhotoCell cell.backgroundColor = .red return cell } } // MARK: PhotoCell final class PhotoCell: UICollectionViewCell { lazy var imageView: UIImageView = { let imageView = UIImageView() imageView.contentMode = .scaleAspectFill imageView.translatesAutoresizingMaskIntoConstraints = false imageView.layer.masksToBounds = true return imageView }() override init(frame: CGRect) { super.init(frame: frame) setupViews() } required init?(coder aDecoder: NSCoder) { fatalError("init?(coder:) not implemented") } func setupViews() { addSubview(imageView) NSLayoutConstraint.activate([ topAnchor.constraint(equalTo: topAnchor), bottomAnchor.constraint(equalTo: bottomAnchor), leadingAnchor.constraint(equalTo: leadingAnchor), trailingAnchor.constraint(equalTo: trailingAnchor) ]) } }
źródło
Jeśli, tak jak ja, trzeba zachować swój układ niestandardowy przepływu jest
itemSize
dynamicznie aktualizowana w oparciu o szerokości kolekcji widoku danych, należy zastąpić swójUICollectionViewFlowLayout
„sprepare()
metody. Oto wideo WWDC demonstrujące tę technikę .class MyLayout: UICollectionViewFlowLayout { override func prepare() { super.prepare() guard let collectionView = collectionView else { return } itemSize = CGSize(width: ..., height: ...) } }
źródło
To jest moja wersja, znajdź odpowiedni stosunek, aby uzyskać rozmiar komórki zgodnie z wymaganiami.
- (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath { return CGSizeMake(CGRectGetWidth(collectionView.frame)/4, CGRectGetHeight(collectionView.frame)/4); }
źródło