I have UICollectionView that scrolls up vertically, and i want to change item height in tap. In default state, cell have a height of 2/3 screen height. I tried following:
override func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
let cell = collectionView.cellForItem(at: indexPath)
if let cell = cell as? TutorialCell {
let attribute = layout.layoutAttributesForItem(at: indexPath)
attribute?.frame = CGRect.init(x: 0, y: 0, width: UIScreen.main.bounds.size.width,
height: UIScreen.main.bounds.size.height)
collectionView.reloadItems(at: [indexPath])
}
print(indexPath.row)
}
But it's not working.
You can Achieve this by UICollectionViewDelegateFlowLayout method sizeForItemAt
Declare a variable
var selectIndex: Int = -1
In your didSelectItemAt add this
override func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
self.selectIndex = indexPath.row
collectionView.reloadData()
}
Add an extension for UICollectionViewDelegateFlowLayout
extension YourViewController: UICollectionViewDelegateFlowLayout {
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
let height = (self.selectIndex == indexPath.row ) ?
UIScreen.main.bounds.size.height :
(UIScreen.main.bounds.size.height * 2) / 3
return CGSize(width:UIScreen.main.bounds.size.width, height:height)
}
}
Related
I have a UICollectionView with a horizontal scroll that shows 3 cells for each page but when I get to the last page there is only one element and it does not let me scroll to show this last element.
This is my list:
var benefitIcons = ["ic_benefit_frappe", "ic_benefit_birthday", "ic_benefit_2x1", "ic_benefit_points", "ic_benefit_combo", "ic_benefit_cine", "ic_benefit_tickets", "ic_benefit_refill", "ic_benefit_klic", "ic_benefit_pay"]
This is the method for UICollectionView:
extension ProfileCCViewController: UICollectionViewDelegate, UICollectionViewDataSource, UICollectionViewDelegateFlowLayout {
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return benefitIcons.count
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
if let cell = benefitCollection.dequeueReusableCell(withReuseIdentifier: "BenefitCell", for: indexPath) as? UserBenefitsCell {
cell.benefitIcon.image = UIImage(named: benefitIcons[indexPath.row])
cell.benefitLbl.text = benefitDescriptions[indexPath.row]
return cell
} else {
return UICollectionViewCell()
}
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
return CGSize(width: collectionView.bounds.width/3, height: collectionView.bounds.height)
}
func collectionView(_ collectionView: UICollectionView, willDisplay cell: UICollectionViewCell, forItemAt indexPath: IndexPath) {
benefitControl.currentPage = indexPath.row
}
func scrollViewDidScroll(_ scrollView: UIScrollView) {
let offSet = scrollView.contentOffset.x
let width = scrollView.frame.width
let horizontalCenter = width / 2
benefitControl.currentPage = Int(offSet + horizontalCenter) / Int(width)
}
}
This how look like correctly:
But when I'm scrolling to the last item and is uneven doesn't scroll to this last section:
I have a collectionview cell, and need to filtering cell.
I'm trying to make cell height to 0. but not work.
this is my code.
extension ViewController: UICollectionViewDataSource, UICollectionViewDelegate{
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return self.numberOfCell
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
guard let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "cell", for: indexPath) as? data else {
return UICollectionViewCell()
}
let set1 = CoreDataManager.shared.getSetting(idx: indexPath.row).set1
if(set1){
return cell
}
else{
let none = collectionView.dequeueReusableCell(withReuseIdentifier: "none", for: indexPath)
none.frame.size.width = 100
none.frame.size.height = CGSize(width: 0, height: 100).width
return none
}
}
}
If you need to set a size of cell you need to conform to UICollectionViewDelegateFlowLayout and implement sizeForItemAt and give it the size.
extension viewController: UICollectionViewDelegateFlowLayout {
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
return CGSize(width: 100, height: 0)}
}
another solution to make height constrain for a view inside the your cell with identifier "cell" and give it to 0 before returning a cell in cellForItemAt.
override func viewDidLoad() {
let space:CGFloat = 10.0
let dimensionwidth = (view.frame.size.width - (2 * space))
let dimensionheight = (view.frame.size.height - (2 * space))
flowLayout.minimumInteritemSpacing = space
flowLayout.minimumLineSpacing = space
flowLayout.itemSize = CGSize(width: dimensionwidth, height: dimensionheight)
}
override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "CellMemeCollection", for: indexPath) as! CellMemeCollection
let Meme = self.memes[(indexPath as NSIndexPath).row]
// Set the name and image
cell.MemeImage?.image = Meme.memeImage
cell.MemeImage.sizeThatFits(flowLayout.itemSize)
return cell
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
// let height = view.frame.size.height
// let width = view.frame.size.width
return CGSize(width: 200, height:400)
}
I tried every thing that would make the photo looks bigger but nothing changing .. I played with the items size and I tried to call the function collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize but nothing is working , help please !
I am a new iOS programming. and now i am developing an app which display similar to appstore. But i have some problems which when user open the app so, i want cell of data should be display the second cell. for example, i have three cell then when user open the app the second cell should be automatically scrolled to that position.
Here is how i created header section: (programmatically)
/// banner section
override func collectionView(_ collectionView: UICollectionView, viewForSupplementaryElementOfKind kind: String, at indexPath: IndexPath) -> UICollectionReusableView {
let header = collectionView.dequeueReusableSupplementaryView(ofKind: kind, withReuseIdentifier: headerCellId, for: indexPath) as! HeaderBanner
header.sectionCategory = dashbordCell?[indexPath.item]
return header
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, referenceSizeForHeaderInSection section: Int) -> CGSize {
let size = CGSize(width: view.frame.width, height: 370)
return size
}
Here is I created HeaderBanner
let dataBannerCollectionView: UICollectionView = {
var scrollInterval: Int = 3
let flowLayout = UICollectionViewFlowLayout()
flowLayout.scrollDirection = .horizontal
let collectionView = UICollectionView(frame: .zero,collectionViewLayout: flowLayout)
collectionView.backgroundColor = UIColor.clear
collectionView.translatesAutoresizingMaskIntoConstraints = false
return collectionView
}()
func setupViewsCell(){
dataBannerCollectionView.showsHorizontalScrollIndicator = false
dataBannerCollectionView.dataSource = self
dataBannerCollectionView.delegate = self
dataBannerCollectionView.register(HeaderBannerDataCell.self, forCellWithReuseIdentifier: headerCellId)
addSubview(dataBannerCollectionView)
setupConstraintDataBannerCollectionView()
}
Here is behavior of HeaderBanner file.
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
if let count = sectionCategory?.dataBanner?.count {
return count
}
return 0
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: headerCellId, for: indexPath) as! HeaderBannerDataCell
cell.dataBannerCell = sectionCategory?.dataBanner![indexPath.item]
return cell
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
print(frame.width)
let size = CGSize(width: frame.width - 100 , height: 350)
return size
}
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
print("Banner selected")
}
As you can see the header section display the first cell of image. I just my app look like this when user opens the app .
Here is output of my sample app:
Here is my expectation which i want to display the middle cell of all cells.
You can use the scrollToItem function of UICollectionView:
if you have three cells for example:
dataBannerCollectionView.scrollToItem(at: IndexPath(item: 2, section: 0), at: UICollectionViewScrollPosition.centeredHorizontally, animated: false)
Add that code in setupViewsCell() function
I use UICollectionView (views with UIButtons) to book the time:
override func viewDidLoad() {
super.viewDidLoad()
collectionViewTime.register(UINib(nibName: "TimeCollectionViewCell", bundle: nil), forCellWithReuseIdentifier: "timecell")
collectionViewTime.dataSource = self
collectionViewTime.delegate = self
if let layout = collectionViewTime.collectionViewLayout as? UICollectionViewFlowLayout {
layout.scrollDirection = .vertical
}
}
func numberOfSections(in collectionView: UICollectionView) -> Int {
return 1
}
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return Timeline.count
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, insetForSectionAt section: Int) -> UIEdgeInsets {
let flowLayout = collectionViewLayout as! UICollectionViewFlowLayout
let numberOfItems = CGFloat(collectionView.numberOfItems(inSection: 0))
let combinedItemWidth = (numberOfItems * flowLayout.itemSize.width) + ((numberOfItems - 1) * flowLayout.minimumInteritemSpacing)
let padding = (collectionView.frame.width - combinedItemWidth) / 2
return UIEdgeInsets(top: 0, left: padding, bottom: 0, right: padding)
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "timecell", for: indexPath) as! TimeCollectionViewCell
let time = Timeline[indexPath.row][0]
cell.btnTime.setTitle(DateManager.dateToTime(date: time.0), for: .normal)
return cell
}
And I got all views (UIButtons) in one line:
How can I set automatically moving UIViews in new rows?
So, in my case (iPad) one row will contain 7 UIViews, iPhone will contain 4-5 UIViews in one row.
For that you need to implement UICollectionViewDelegateFlowLayout method collectionView(_:layout:sizeForItemAt:) and change the collectionView's Scroll direction to Vertical
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
let minCellSpace: CGFloat = 10 //Set minimum cell space that you want
if UIDevice.current.userInterfaceIdiom == .pad {
//For iPad return 7 cell as you mention in question
return CGSize(width: (collectionView.frame.size.width / 7) - minCellSpace, height: yourCellHeight)
}
else {
//For iPhone return 4 cell, if you want to return 5 cell divide width to 5
return CGSize(width: (collectionView.frame.size.width / 4) - minCellSpace, height: yourCellHeight)
}
}
Please use one more flow delegate method as below
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize;
------
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
return CGSize(width:(button width), height:button hieght);
}