UIcollectionview display different cell after certain row - ios

I need to create a UIcollectionview with grids of cells with 3 cells per row. After a certain amount of cells, lets say 60, I need to display a big cell with image view cell 61(different set of data). But with creating this 61st cell of image, my normal data on 61st will be merged into this image cell, is there any way to calculate it without compromising my array of data . Thanks.

Here's the data source part:
var items = [Item]()
func numberOfSections(in collectionView: UICollectionView) -> Int {
let numberOfSections = 60/(items.count+1) + 1
return numberOfSections
}
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
let numberOfSections = 60/(items.count+1) + 1
if section != numberOfSections - 1 {
return 60
}
let numberOfItems = items.count%60
return numberOfItems
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let itemIndex = indexPath.section * 60 + indexPath.row
let item = items[itemIndex]
// set cell from item …
}
Then you need to provide the header cell using UICollectionViewDelegate:
func collectionView(_ collectionView: UICollectionView, willDisplaySupplementaryView view: UICollectionReusableView, forElementKind elementKind: String, at indexPath: IndexPath)
Search SO for 'willDisplaySupplementaryView' will show you how to implement this. Good luck!

Related

Double direction scrolling collectionView with multiple sections data issue

I have a double direction scrolling collectionView with 50 sections, 10 items per section and 3 showing cells per section and filling the collectionView with the same data array.
the problem is the collectionView duplicate data in every section and I want to show different data in appearing sections to the user.
Any help please!
this is my code:
func numberOfSections(in collectionView: UICollectionView) -> Int {
return 50
}
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return 10
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: contentCellIdentifier,
for: indexPath) as! UserCollectionCell
cell.userImageView.kf.setImage(with: URL.init(string: String().loadCorrectUrl(url:firebaseUsers[indexPath.row].image)))
cell.userNameLabel.text=firebaseUsers[indexPath.row].name
if(selectedIndexPaths.contains(indexPath) ){
cell.userBackgroudView.isHidden=false
}
else{
cell.userBackgroudView.isHidden=true
}
}
return cell
}
Implement prepareForReuse in UserCollectionCell and clear the imageView and label text to prevent showing duplicate data on scroll
class UserCollectionCell: UICollectionViewCell {
override func prepareForReuse() {
super.prepareForReuse()
self.userImageView.image = nil
self.userNameLabel.text = nil
}
}
Hope it helps

Deque custom cells from specific indexpath SWIFT

I have UICollectionView, I am downloading images and displaying them in the cells. My first cell is of screen width and contains a button, rest are the general cells. The application only deques the first 2 cells, There are supposed to be 3 cells.
My cellForItemAtIndexPath function:
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
if indexPath.row == 0 {
print("yay")
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "UploadNewCell", for: indexPath) as! UploadNewCell
return cell
}else if indexPath.row > 0 {
let userImages = userposts[indexPath.row]
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "ProfileCell", for: indexPath) as! ProfileCell
cell.fillCells(uid: uid!, userPost: userImages)
return cell
}else{
return ProfileCell()
}
}
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
if indexPath.row == 0 {
print("hellowold")
} else {
let selecteditem : String!
selecteditem = userposts[indexPath.row]
performSegue(withIdentifier: "lol", sender: selecteditem)
}
}
func numberOfSections(in collectionView: UICollectionView) -> Int {
return 1
}
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return userposts.count
}
my view:
There are supposed to be 3 images down there in the cells, One of them is dequed in the first index.
I am out of Ideas, Any ideas on the solution?
let userImages = userposts[indexPath.row]
At this point in your code, indexPath.row is > 0.
Arrays are 0-based, so the first cell (indexPath.row == 1) is getting the second item in your array (user posts[1]), which is the second image you wanted.
I can think of a couple of simple changes:
Change the index you're accessing, such as:
let userImages = userposts[indexPath.row - 1]
Add 1 to your userposts.count value in numberOfItemsInSection:
Split your collectionView into having multiple sections, so the top cell (UploadNewCell) is section 0, and the bottom three ProfileCells are a second section: this allows you to check the indexPath.section, and assign directly from row:
let userImages = userposts[indexPath.row]
Note: I would actually advise further modifying the code for the second option to create an enum for SectionType. That allows you to perform a switch over the potential values, allowing you to avoid that nasty default implementation, and boosts the readability of your code.

Multiple selections on collection view cells

I am trying to make an app with similar functionality to the Photos app that comes with iOS, I have the functionality that allows you to tap on a cell which expands the image to fit the screen, then tap the image to dismiss it. I now want to add the select button so that you can select multiple images that can be downloaded. I'm fairly new to this and have looked around but can't find an example that does both of these things. Any help would be great.
Update:
My current code:
func numberOfSections(in collectionView: UICollectionView) -> Int {
return 1
}
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return imagesURLArray.count
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "photoCell", for: indexPath) as! PhotoCell
cell.backgroundColor = .clear
cell.imageView.image = UIImage(contentsOfFile: imagesURLArray[indexPath.row].path)
cell.checkmarkView.isHidden = true
return cell
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout,sizeForItemAt indexPath: IndexPath) -> CGSize {
let paddingSpace = sectionInsets.left * (itemsPerRow + 1)
let availableWidth = view.frame.width - paddingSpace
let widthPerItem = availableWidth / itemsPerRow
return CGSize(width: widthPerItem, height: widthPerItem)
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout,insetForSectionAt section: Int) -> UIEdgeInsets {
return sectionInsets
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumLineSpacingForSectionAt section: Int) -> CGFloat {
return sectionInsets.left
}
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
addZoomedImage(indexPath.row)
addGestureToImage()
addBackGroundView()
view.addSubview(selectedImage)
}
Im not sure whereto go from here, whether its easier to add long tap gestures to select multiple images to download or to have the select button in the photos app both of which im a little clueless on where to start.
OK - one approach:
Design a custom button (or find one already made) that provides "CheckMark" functionality (tap to check/uncheck)
Add that button to your PhotoCell - maybe upper-left or upper-right corner
When the cell is tapped on the CheckMark button, toggle it checked/unchecked and send a message back to your controller to track its state
If the cell is tapped but not on the checkmark button, handle it as you do now with didSelectItemAt indexPath:
That's the general idea. A good next place for you is probably to take a look at some examples found by searching for uicollectionviewcell check mark
//works in swift 3.3 Hope it helps
//my model struct
struct Brands {
var brandId: Int = 0
var productId: Int = 0
var name: String = ""
var isChecked:Bool = false
}
var arrBrands = []//initialise arr of model
func collectionView(_ collectionView: UICollectionView,
numberOfItemsInSection section: Int) -> Int {
return arrBrands.count
}
func collectionView(_ collectionView: UICollectionView,cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let identifier: String = "brandCell"
let cell: YourCustomCell? =
collectionView.dequeueReusableCell(withReuseIdentifier: identifier,
for: indexPath) as? YourCustomCell;
let isChecked = arrBrands[indexPath.row].isChecked
cell?.brandName.font = (isChecked) ?fontForTimesRoman(withStyle:"bold", andFontsize: 14):fontForTimesRoman(withStyle: "regular",
andFontsize: 14)
cell?.brandName.text = arrBrands[indexPath.row].name
cell?.brandCheckButt.setImage((isChecked) ?UIImage(named:"filled_checkmark.png"):UIImage(named:"empty_checkmark.png"), for: .normal)
return cell!
}
func numberOfSections(in collectionView: UICollectionView) -> Int {
return 1
}
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
checkUncheckBrand(index: indexPath.row)
}
func collectionView(_ collectionView: UICollectionView,
didDeselectItemAt indexPath: IndexPath) {
checkUncheckBrand(index: indexPath.row)
}
func checkUncheckBrand(index:Int){
arrBrands[index].isChecked = ! (arrBrands.isChecked)
brandFilterCV.reloadData()
}

Populating each section of collection view independently Swift

I have a collection view embedded in a table view so it scrolls vertically and horizontally. It has four sections, Today, This Week, This Month, This Year. I am having trouble understanding how to populate each section with its own data. Right now I am using the below code to populate the collection view but all sections have the same data. How can I populate each section with with its own data?
So if I had an array of images for Today, an array of images for This Week, an array of images for This Month, and and array of images for This Year, how can I set the image view in its section to the items in the corresponding array? So Today should have the images in the todayImageArray, This Week should have the images in the thisWeekImageArray and so on.
Also I have the delegate and data source of the collection view set to the table view.
Any help is much appreciated!
let images: [[UIImage]] = [
[image_1, image_2, image_3, image_4],
[image_5, image_6, image_7, image_8],
[image_9, image_10, image_11, image_12],
[image_13, image_14, image_15, image_16]
]
func numberOfSections(in collectionView: UICollectionView) -> Int {
return images.count
}
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return images[section].count
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "imageCell", for: indexPath) as! ImageCollectionViewCell
cell.imageView.image = images[indexPath.section][indexPath.row]
return cell
}
You need a structured data source. Currently, from your code, it looks like you have a single array called images and you're using that to both provide the number of items and also to update cell content. But if you need separate sections, you need to model your datasource as such and provide logical responses to datasource and delegate methods in collectionView.
Example simple data source:
let simpleDataSource: [[UIImage]] = [
[image1, image2],
[image3, image4],
[image5, image6]
]
Example of using this in collectionView methods:
func numberOfSections(in collectionView: UICollectionView) -> Int {
return simpleDataSource.count
}
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return simpleDataSource[section].count
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "imageCell", for: indexPath) as! ImageCollectionViewCell
cell.imageView.image = simpleDataSource[indexPath.section][indexPath.row]
return cell
}
You should also read through the documentation for UICollectionView.
Set up an array that has all your images, or better yet structs designed to organize your information better, or image names as in my example, and then use the numberOfSections and indexPath.section properties to assign those images:
let images = [
["imageA1", "imageA2"],
["imageB1", "imageB2"]
]
override func numberOfSections(in collectionView: UICollectionView) -> Int {
return images[section]
}
override func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return images[section].count
}
override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "imageCell", for: indexPath) as! ImageCollectionViewCell
cell.imageView.image = UIImage(named: images[indexPath.section][indexPath.row])
return cell
}

Collectionview inside tableview cell with 1 data source

I want to put collection view inside tableview cell. Every tableview cell contains 2 collectionviewCell. Let say I have 8 pic in my data model, I want the collection view looks like the image. How to do this?
Instead Of Using Collection View inside tableview , Use only collection view with vertical scroll and in the method
#pragma mark ------------Collection View Delegates-----------------
override func numberOfSectionsInCollectionView(collectionView:
UICollectionView!) -> Int {
return 1
}
override func collectionView(collectionView: UICollectionView!,
numberOfItemsInSection section: Int) -> Int {
return 4
}
override func collectionView(collectionView: UICollectionView!,
cellForItemAtIndexPath indexPath: NSIndexPath!) ->
UICollectionViewCell! {
let cell = collectionView.dequeueReusableCellWithReuseIdentifier(reuseIdentifier,
forIndexPath: indexPath) as !MyCollectionViewCell
// Configure the cell
let image = UIImage(named: Images[indexPath.row])
cell.imageView.image = image
return cell
}
func collectionView(collectionView: UICollectionView,
layout collectionViewLayout: UICollectionViewLayout,
sizeForItemAtIndexPath indexPath: NSIndexPath) -> CGSize {
return CGSizeMake(_collectionViewToAddImages.frame.size.width/2, _collectionViewToAddImages.frame.size.height/2);
}
In this way you will have view like this, just add the pading and you will get the results

Resources