I am trying to implement following screen.
But in my code, it is displaying following way
following code I wrote,
import UIKit
class LunchViewController: UIViewController {
#IBOutlet weak var mainCollectionView: UICollectionView!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
}
}
extension LunchViewController:UICollectionViewDataSource,UICollectionViewDelegateFlowLayout,UICollectionViewDelegate {
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
return CGSize(width: 412, height: 180)
}
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
// return self.myLibraryArray.count
return 8
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
// let item = self.myLibraryArray[indexPath.row]
guard let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "RestaurantCollectionViewCell", for: indexPath) as? RestaurantCollectionViewCell else {
return UICollectionViewCell()
}
//cell.fillDetails(item)
return cell
}
}
Here is the complete project link
Can any one tell me, what is the issue? or what I have to write the code to get expected output?
Update:
Select collectionView and Change Estimate Size to none. In storyboard.
if you dont want space between two cells then set 0 to for lines in Min spacing
And i have given width as screen width
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
return CGSize(width: UIScreen.main.bounds.size.width, height: 180)
}
Output :-
Change sizeForItem method to this:
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
return CGSize(width: collectionView.frame.size.width, height: 180)
}
Also, make sure the mainCollectionView is constrained to the leading and trailing edges in the storyboard.
Related
I am new to Swift and I am trying to create a UICollectionViewCell. It builds successfully but the cells are not the size that I thought I was creating. There are supposed to be two columns and and it is supposed to contain an image, description and price. I know it is something simple but I cannot figure out what I am doing wrong. See the image below. I assume I need to fix something in the size inspector but I cannot figure out what.
import UIKit
class ProductsVC: UIViewController, UICollectionViewDelegate, UICollectionViewDataSource, UICollectionViewDelegateFlowLayout{
#IBOutlet weak var productsCollection: UICollectionView!
private(set) public var products = [Product]()
override func viewDidLoad() {
super.viewDidLoad()
productsCollection.dataSource = self
productsCollection.delegate = self
}
func initProducts(category: Category){
products = DataService.instance.getProducts(forCategoryTitle: category.title)
}
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return products.count
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
if let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "ProductCell", for: indexPath) as? ProductCell {
let product = products[indexPath.row]
cell.updateViews(product: product)
return cell
}
return ProductCell()
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
let height: CGFloat = 280
return CGSize(width: (collectionView.frame.size.width - 10) / 2, height: height)
//10 is minimum line spacing between two columns
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumLineSpacingForSectionAt section: Int) -> CGFloat {
return 10
}
}
FYI
Try this:
// MARK: - UICollectionViewDelegateFlowLayout
extension ViewController: UICollectionViewDelegateFlowLayout {
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
// You can change collection view cell height here, It's up to your design
let height: CGFloat = 150
let width: CGFloat = (collectionView.frame.size.width - 10 - a) / 2 // a is extra spacing of collection view (like leading or trailing constraints)
// Converting CGFloat to Int make sure the width of total cells are less than or equal the screen width
return CGSize(width: Int(width), height: Int(height)) // 10 is minimum line spacing between two columns
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumLineSpacingForSectionAt section: Int) -> CGFloat {
return 10
}
}
Please check extra spacings example with the below photo:
a = 20 with my example design (leading = 10, trailing = 10)
just provide the itemSize when you declare the collectionView:
let layout = UICollectionViewFlowLayout()
layout.itemSize = sizeForEachItem
let collectionView = UICollectionView(frame: .zero, collectionViewLayout: layout)
I'm trying to make images grid like the below image
I tried the below code
import UIKit
class ViewController: UIViewController,UICollectionViewDelegate, UICollectionViewDataSource {
#IBOutlet weak var collectionViw: UICollectionView!
var widthss = [59.0,59.0,59.0,121.0,59.0,59.0,59.0,59.0,59.0,59.0,28.0,28.0,59.0,59.0,] as [CGFloat]
var heights = [36.0,36.0,36.0,76.0,36.0,76.0,36.0,36.0,36.0,76.0,36.0,36.0,36.0,76.0,] as [CGFloat]
override func viewDidLoad() {
super.viewDidLoad()
}
func numberOfSections(in collectionView: UICollectionView) -> Int {
return 1
}
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return heights.count
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "cell", for: indexPath) as! UICustomCollectionViewCell
// Customize cell height
cell.frame = CGRect(x: cell.frame.origin.x, y: cell.frame.origin.y , width: widthss[indexPath.row], height: heights[indexPath.row])
return cell
}
}
extension ViewController: UICollectionViewDelegateFlowLayout {
func collectionView(_ collectionView: UICollectionView,
layout collectionViewLayout: UICollectionViewLayout,
sizeForItemAt indexPath: IndexPath) -> CGSize {
return CGSize(width: widthss[indexPath.row], height: heights[indexPath.row])
}
func collectionView(_ collectionView: UICollectionView,
layout collectionViewLayout: UICollectionViewLayout,
minimumInteritemSpacingForSectionAt section: Int) -> CGFloat {return 1.0
}
func collectionView(_ collectionView: UICollectionView, layout
collectionViewLayout: UICollectionViewLayout,
minimumLineSpacingForSectionAt section: Int) -> CGFloat {
return 1.0
}}
at the end, i found the result like the below image,
what I need is to make the collection view cells like the first image
Anyone have an idea where is my mistake
thanks in advance
I have collectionview with header.
This is the image
In this, i have display the questions in the UICollectionReusableView as header and answers in the collectionviewcell.
So the image is this way.But i need to scroll the collectionview horizontal only.
But that time it will become as :-
This is the header.
This is the cell.
But i need this in the first screen header and its answers. when user scroll it then need show 2nd question in header and its answers. How to implement it?
currently my code is as below:-
extension NH_DummyDataViewController: UICollectionViewDataSource {
func numberOfSections(in collectionView: UICollectionView) -> Int {
return self.questionViewModel.numberOfSections()
}
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return self.questionViewModel.numberOfRowsIn(section: section)
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = verticalCollectionView.dequeueReusableCell(withReuseIdentifier: "NH_Headercell", for: indexPath)as! NH_Headercell
// cell.options.text = "hello"
// let optionModel = self.questionViewModel.datafordisplay(atindex: indexPath)
cell.setReviewData(reviews:self.questionViewModel.datafordisplay(atindex: indexPath))
return cell
}
func collectionView(_ collectionView: UICollectionView, viewForSupplementaryElementOfKind kind: String, at indexPath: IndexPath) -> UICollectionReusableView {
let firstheader: NH_QuestionHeaderCell = collectionView.dequeueReusableSupplementaryView(ofKind: kind, withReuseIdentifier: "NH_QuestionHeaderCell", for: indexPath ) as! NH_QuestionHeaderCell
firstheader.setReviewData(reviews:questionViewModel.titleForHeaderInSection(atsection:indexPath.section))
return firstheader
}
}
// MARK: UICollectionViewDelegateFlowLayout
extension NH_DummyDataViewController: UICollectionViewDelegateFlowLayout {
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
return CGSize(width: collectionView.frame.width, height: 100)
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, referenceSizeForHeaderInSection section: Int) -> CGSize {
return CGSize(width: collectionView.frame.width, height: 100)
}
}
Set Collection view scroll direction Horizontal and set paging
yourCollectionview.pagingEnabled = true
I am implementing a UICollectionView that needs to page horizontally. The UICollectionViewCell needs to be the same size as the UICollectionView. The cell has 2 embedded rows. The first has a UITextView and a UIButton and the second has a UITextView.
The UICollectionviewCell and the constraints work in preview for different sizes of the iPhone (e.g. 4s, 8, 8plus) but when running in the simulator paging doesn't work correctly and the cell's width, I guess, isn't centered and the cell doesn't move far enough to reach the next cell making the cell look cutoff.
I have tried the solution at this url: UICollectionView Horizontal Paging not centered
but I can't seem to get the width and centering correct. The code I'm using is below.
internal class AccessViewController : UIViewController, UICollectionViewDataSource, UICollectionViewDelegate, UICollectionViewDelegateFlowLayout {
//...
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "Cell", for: indexPath) as! PagerContentCollectionViewCell
//Set the cell title
cell.txtTitle.text = "title"
//add a target for the call capability
cell.btnCall.addTarget(self, action: #selector(didButtonClick), for: .touchUpInside)
//description
cell.txtDescription.text = "description"
return cell
}
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
//let i = IndexPath(item: titles.count, section: 0)
collectionView.scrollToItem(at: indexPath, at: .right, animated: true)
print("Selected")
collectionView.reloadData()
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumLineSpacingForSectionAt section: Int) -> CGFloat {
return 0
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
let frameSize = collectionView.frame.size
return CGSize(width: frameSize.width, height: frameSize.height)
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
let frameSize = collectionView.frame.size
return CGSize(width: frameSize.width, height: frameSize.height)
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, insetForSectionAt section: Int) -> UIEdgeInsets {
return UIEdgeInsets(top: 0, left: 5, bottom: 0, right: 5)
}
The UICollectionView width and height are 267, 153.
The UICollectioViewCell width and height 262, 150
The Section Insets are 0,0,0,0.
Any help is much appreciated.
Thanks
Edit: I added in code I was trying to use for the layout. I am probably missing something else too.
I was able to fix using these two functions:
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumLineSpacingForSectionAt section: Int) -> CGFloat {
return 0
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
let frameSize = collectionView.frame.size
return CGSize(width: frameSize.width, height: frameSize.height)
}
I got two questions.
I am wondering why my collection view automatically load data without calling imageCollectionView.reloadData().
Solved. See comment
Why func collectionView(collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAtIndexPath indexPath: NSIndexPath) -> CGSize is not called? I didn't see the print("collectionViewLayout called") I am trying to modify the cell's size so the cell's height equals to the collection view height
Solved. See comment
Here is the codes
class ProductInternalDetailVC: UIViewController, UICollectionViewDataSource, UICollectionViewDelegate {
var selectedProduct: Product?
#IBOutlet weak var imageCollectionView: UICollectionView!
override func viewDidLoad() {
super.viewDidLoad()
imageCollectionView.delegate = self
imageCollectionView.dataSource = self
}
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return 2
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "Cell", for: indexPath as IndexPath) as! ProductInternalDetailCVC
if indexPath.row == 0 {
cell.productImage.image = selectedProduct!.image1
} else {
cell.productImage.image = selectedProduct!.image2
}
cell.productImage.frame = CGRect(x: 1, y: 1, width: cell.frame.size.width-2, height: cell.frame.size.height-2)
return cell
}
func collectionView(collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAtIndexPath indexPath: NSIndexPath) -> CGSize {
//return CGSize(width: collectionView.frame.size.height-1, height: collectionView.frame.size.height-1)
print("collectionViewLayout called")
return CGSize(width: 10, height: 10)
}
}
class ProductInternalDetailCVC: UICollectionViewCell {
#IBOutlet weak var productImage: UIImageView!
}
Thanks for the help.
Question 2: The function signature has changed a bit. Change the function signature with this:
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
...
}
And don't forget to implement the UICollectionViewDelegateFlowLayout protocol.
Question 1:
When entering the ViewController your collectionView loads the datasource of the collectionView automatically if this is your question.for example, make changes on datasource without changing the view (means without calling viewDidLoad method) you will not see the changes until you call imageCollectionView.reloadData().