Multiple selections on collection view cells - ios

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()
}

Related

Why my UICollectionView doesn't scroll to the last item of my list?

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:

DidSelect a cell in Collection View implemented in Collection View cell

Have an issue with collection view cell.
i've got a collection view (vertical scroll) with 2 sections (1st is ServiceCell and the 2nd is OfferCell as ). First section is with 1 item - another collection view that is set in class ServiceCell: UIcollectionViewCell {} (horizontal scroll) with multiply subcells (ServiceSubCell).
i can't understand where i have to implement didselect method for subcells
main view conroller looks like this:
extension HomeScreenViewController: UICollectionViewDelegate, UICollectionViewDataSource, UICollectionViewDelegateFlowLayout {
func numberOfSections(in collectionView: UICollectionView) -> Int {
2
}
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
if section == 0 {
return 1
}
return offers.count
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
if indexPath.section == 0 {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: ServiceCell.reuseId, for: indexPath) as! ServiceCell
return cell
}
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: OfferCellSubCell.reuseId, for: indexPath) as! OfferCellSubCell
cell.backgroundColor = .white.withAlphaComponent(0.6)
cell.layer.cornerRadius = 20
cell.setup(with: offers[indexPath.row])
return cell
}
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
if indexPath.section == 0 {
// this part doesn't work
let serviceVC = ServiceScreenViewController() as ServiceScreenViewController
serviceVC.category = servicesCategoriesArray[indexPath.row]
self.navigationController?.pushViewController(serviceVC, animated: true)
} else {
let offerVC = OfferScreenViewController() as OfferScreenViewController
offerVC.offerNew = offers[indexPath.row]
self.navigationController?.pushViewController(offerVC, animated: true)
}
}
}
Service cell with extension
class ServiceCell: UICollectionViewCell, UICollectionViewDelegate, UICollectionViewDelegateFlowLayout, UICollectionViewDataSource {
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return servicesCategoriesArray.count
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: ServiceCellSubCell.reuseId, for: indexPath) as! ServiceCellSubCell
cell.setup(with: servicesCategoriesArray[indexPath.row])
return cell
}
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
return CGSize(width: 140, height: 140)
}
}
You should implement "didSelect" in ServiceCell
and you should implement in your ViewController "should highlight" for first section to "false"
func collectionView(_ collectionView: UICollectionView,
shouldHighlightItemAt indexPath: IndexPath) -> Bool {
return yourServiceSection ? false : true
}
the below code must be in ServiceCell and ViewController
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
collectionview.deselectItem(at: indexPath, animated: true)
}
in your "ServiceCell" you must add this extension:
import Foundation
import UIKit
extension ServiceCell: UICollectionViewDataSource, UICollectionViewDelegate, UICollectionViewDelegateFlowLayout {
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return viewModel.list.count ?? 0
}
func collectionView(_ collectionView: UICollectionView,
cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier:
ServiceSubCell.nameOfClass,
for: indexPath) as? ServiceSubCell
if let item = viewModel.data?.item(at: indexPath.item) {
cell?.config(item: item)
}
return cell ?? UICollectionViewCell()
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout,
sizeForItemAt indexPath: IndexPath) -> CGSize {
return CGSize(width: SizeConstant.ServiceSubCellWidth.rawValue,
height: SizeConstant.ServiceSubCellHeight.rawValue)
}
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
collectionview.deselectItem(at: indexPath, animated: true)
// implement your code you need
}
}

How to call the indexPath.row of a UITableViewCell with a UICollectionView embedded within

Currently, I have a UITableView with a UICollectionView embedded in it. I have 3 arrays of information and I want each array to correspond to a UICollectionView, and therefore a UITableViewCell.
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return 5
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "CookieCell", for: indexPath) as? MenuCollectionViewCell
cell?.fullView.layer.borderColor = UIColor.black.cgColor
cell?.labelView.layer.borderColor = UIColor.black.cgColor
cell?.fullView.layer.borderWidth = 0.3
cell?.labelView.layer.borderWidth = 0.3
return cell!
}
func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath) {
}
Where each of the return cell? is, I want to do something like:
if indexPathOfTableView.row == 0 {
//designated parameters
}
else if indexPathOfTableView.row == 1 {
//designated parameters
}
else {
//designated parameters
}
How would I do this?
Hello #helloworld12345
from your question I got the idea that you want to collectionview in tableviewcell
may be below code will help you.
first in you viewController or tableviewcontroller,
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell
{
//send indexPath of this cell
let cell = tblView.dequeueReusableCell(withIdentifier: "tableViewCell", for: indexPath) as! tableViewCell
//Pass your array which you want to show in collectionViewCell and then reload collection view
cell.clnView.reloadData()
return cell
}
In your tableViewCell swift file:
class tableViewCell: UITableViewCell, UICollectionViewDelegate, UICollectionViewDataSource, UICollectionViewDelegateFlowLayout
{
#IBOutlet weak var clnView: UICollectionView!
//after awakenib method write below code
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int
{
return 4 //pass your array count
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize
{
let flowayout = collectionViewLayout as? UICollectionViewFlowLayout
let space: CGFloat = (flowayout?.minimumInteritemSpacing ?? 0.0) + (flowayout?.sectionInset.left ?? 0.0) + (flowayout?.sectionInset.right ?? 0.0)
let size:CGFloat = (self.clnView.frame.size.width - space) / 2.0 //By this you can show two cell in one screen
return CGSize(width: size + 60, height: (size + 200))
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell
{
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "clnViewCell", for: indexPath) as! clnViewCell
// do your stuff with your
return cell
}
}

How to scroll the collection view horizontal with header

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

How to display specific cell of UICollectionView using viewForSupplementaryElementOfKind - swift

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

Resources