Collectionview the end Draging Position dont stop on each cell - swift

could somebody help me?
I have Collection view with insets, Scroll Direction Horizontal, Paging enables and no space between cells. And the issue is that the paging doesn't stop on each cell.
I tried all possible solution which I can find on StackOverflow and the World Wide Web but nothing works. I use Xcode 10 and Swift5 and this is for an iPhone app. I don't add my collectionviewcell code because it have only the IBoutlet for the Label.
class ViewController: UIViewController, UICollectionViewDataSource,
UICollectionViewDelegate {
#IBOutlet weak var collectionView: UICollectionView!
private let item = ["Monday","Tuesday","Wednesday","Thursday","Friday","Saturday", "Sunday"]
private let cellScaling: CGFloat = 0.33
private var cellWidth: CGFloat = 0
override func viewDidLoad() {
super.viewDidLoad()
UpdateUI()
}
func UpdateUI(){
self.collectionView.backgroundColor = UIColor.white
let screenSize = UIScreen.main.bounds.size
let cellWidth = floor(screenSize.width * cellScaling)
let insetX = (view.bounds.width - cellWidth) / 2
let layout = collectionView!.collectionViewLayout as! UICollectionViewFlowLayout
layout.itemSize = CGSize(width: cellWidth, height: collectionView.bounds.height)
collectionView.contentInset = UIEdgeInsets(top: 0, left: insetX, bottom: 0, right: insetX)
// layout.minimumLineSpacing = 0
self.cellWidth = cellWidth
}
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return self.item.count
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "cell", for: indexPath) as! CollectionViewCell
cell.label.text = self.item[indexPath.row]
cell.backgroundColor = UIColor.cyan
return cell
}
private var startingScrollingOffset = CGPoint.zero
func scrollViewWillBeginDragging(_ scrollView: UIScrollView) {
startingScrollingOffset = scrollView.contentOffset
}
func scrollViewWillEndDragging(_ scrollView: UIScrollView, withVelocity velocity: CGPoint, targetContentOffset: UnsafeMutablePointer<CGPoint>) {
let page: CGFloat
let offset = scrollView.contentOffset.x + scrollView.contentInset.left
let proposedPage = offset / max(1, cellWidth)
let snapPoint: CGFloat = 0.1
let snapDelta: CGFloat = offset > startingScrollingOffset.x ? (1-snapPoint) : snapPoint
if floor(proposedPage + snapDelta) == floor(proposedPage){
page = floor(proposedPage)
} else {
page = floor(proposedPage + 1)
}
targetContentOffset.pointee = CGPoint(x: cellWidth * page, y: targetContentOffset.pointee.y)
}
}
enter image description here
And please Notice that I tried all other solution what I could find. Before you vote to delete this Question. the photo shows what it should look like on every cell.

I had to do a similar collection view a few months ago,
This is the code that I use:
func scrollViewWillEndDragging(_ scrollView: UIScrollView, withVelocity velocity: CGPoint, targetContentOffset: UnsafeMutablePointer<CGPoint>) {
let layout = theNameOfYourCollectionView.collectionViewLayout as! UICollectionViewFlowLayout
let cellWidthIncludingSpacing = layout.itemSize.width + layout.minimumLineSpacing // Calculate cell size
let offset = scrollView.contentOffset.x
let index = (offset + scrollView.contentInset.left) / cellWidthIncludingSpacing // Calculate the cell need to be center
if velocity.x > 0 { // Scroll to -->
targetContentOffset.pointee = CGPoint(x: ceil(index) * cellWidthIncludingSpacing - scrollView.contentInset.right, y: -scrollView.contentInset.top)
} else if velocity.x < 0 { // Scroll to <---
targetContentOffset.pointee = CGPoint(x: floor(index) * cellWidthIncludingSpacing - scrollView.contentInset.left, y: -scrollView.contentInset.top)
} else if velocity.x == 0 { // No dragging
targetContentOffset.pointee = CGPoint(x: round(index) * cellWidthIncludingSpacing - scrollView.contentInset.left, y: -scrollView.contentInset.top)
}
}
This code calculates the size of your cell, how many cells have already been shown and once the scroll is finished, adjust it to leave the cell centered.
Make sure you have the pagingEnabled of your collectionView in false if you want to use this code.
I hope I help you!

Related

TableView Cells scroll over headerview in UITableViewController

so I currently have a TableViewController that has headerview and prototype cells. Inside the headerview, there is an image. I have programmed it to where a user scrolls down, the headerview stretches down. But I want to find a way to make that header view stick where it is at and when a user scrolls up on the table view, the cells go over the headerview instead of the headerview scrolling up with the cells which it currently is doing. Here is my code for the TableViewController:
import UIKit
class HeaderViewTableViewController: UITableViewController {
var image: UIImageView?
var image2: UIImageView?
var songNameArray = ["Intro", "The Box", "Start wit Me (feat. Gunna)", "Perfect Time", "Moonwalkin (feat. Lil Durk)", "Big Stepper", "Gods Eyes", "Peta (feat. Meek Mill)", "Boom Boom Boom", "Elyse's Skit", "High Fashion (feat. Mustard)", "Bacc Seat (feat. Ty Dolla $ign)", "Roll Dice", "Prayers to the Trap God", "Tip Toe (feat. A Boogie wi da Hoodie)", "War Baby"]
private let tableHeaderViewHeight: CGFloat = 350.0
private let tableHeaderViewCutAway: CGFloat = 0.1
var headerView: HeaderView!
var headerMaskLayer: CAShapeLayer!
override func viewDidLoad() {
super.viewDidLoad()
tableView.tableFooterView = UIView()
headerView = tableView.tableHeaderView as! HeaderView
headerView.imageView = image
tableView.tableHeaderView = nil
tableView.addSubview(headerView)
tableView.contentInset = UIEdgeInsets(top: tableHeaderViewHeight, left: 0, bottom: 0, right: 0)
tableView.contentOffset = CGPoint(x: 0, y: -tableHeaderViewHeight + 64)
//cut away header view
headerMaskLayer = CAShapeLayer()
headerMaskLayer.fillColor = UIColor.black.cgColor
headerView.layer.mask = headerMaskLayer
let effectiveHeight = tableHeaderViewHeight - tableHeaderViewCutAway/2
tableView.contentInset = UIEdgeInsets(top: effectiveHeight, left: 0, bottom: 0, right: 0)
tableView.contentOffset = CGPoint(x: 0, y: -effectiveHeight)
updateHeaderView()
}
func updateHeaderView() {
let effectiveHeight = tableHeaderViewHeight - tableHeaderViewCutAway/2
var headerRect = CGRect(x: 0, y: -effectiveHeight, width: tableView.bounds.width, height: tableHeaderViewHeight)
if tableView.contentOffset.y < -effectiveHeight {
headerRect.origin.y = tableView.contentOffset.y
headerRect.size.height = -tableView.contentOffset.y + tableHeaderViewCutAway/2
}
headerView.frame = headerRect
let path = UIBezierPath()
path.move(to: CGPoint(x: 0, y:0))
path.addLine(to: CGPoint(x: headerRect.width, y: 0))
path.addLine(to: CGPoint(x: headerRect.width, y: headerRect.height))
path.addLine(to: CGPoint(x: 0, y: headerRect.height - tableHeaderViewCutAway))
headerMaskLayer?.path = path.cgPath
}
override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) {
self.tableView.decelerationRate = UIScrollView.DecelerationRate.fast
}
override func tableView(_ tableView: UITableView, heightForFooterInSection section: Int) -> CGFloat {
return UITableView.automaticDimension
}
#IBAction func backButton(_ sender: Any) {
dismiss(animated: true, completion: nil)
}
}
extension HeaderViewTableViewController {
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return songNameArray.count
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "SongCell", for: indexPath) as! SongNameTableViewCell
cell.songName.text = songNameArray[indexPath.row]
return cell
}
}
extension HeaderViewTableViewController {
override func scrollViewDidScroll(_ scrollView: UIScrollView) {
updateHeaderView()
}
}
Any idea on how to achieve this? Also I have a button nested inside the headerview that I would like to stick to the top of the view controller when users scroll up. I have it nested there because I'm not sure where else it could go in a table view like a custom cell.
Heres an image of how it is setup in my storyboard and what it looks like when ran on the simulator.

Multiple overlayed images in the Navigation bar title

I know how to center a single image in UINavigationBar but no idea how to do that with dynamic number of images. I have a chat app that supports group chats. The number of people in a group chat could be as little as 3 but there's no upper limit.
In the UINavigationBar, I have to set the title to show at least 4 or 5 overlayed images (but not more than that since it looks odd in the UINavigationBar) and a UILabel showing how many more users are in the same group chat (ie + 15 more). The title (all the images and the label) should be centered in the UINavigationBar. The images are being downloaded from the server.
When the user taps on the title (any of the images or the label in the UINavigationBar) it should trigger an action to show a full list of the users in a separate UIViewController
The number of the overlayed images is dynamic (based on each group chat) but I can't figure out how to do this. Here's what the image of what the end result should look like:
Has anyone done this before or have an idea how to accomplish this? Help is very much appreciated
UPDATE:
I've tried to accomplish this with UIStackView but I have multiple problems. Here's the code:
var navStackView : UIStackView = {
let stack = UIStackView()
stack.axis = .horizontal
stack.backgroundColor = .red
stack.alignment = .fill
stack.distribution = .fillEqually
stack.translatesAutoresizingMaskIntoConstraints = false
return stack
}()
var images = ["1", "2", "3", "4"]
override func viewDidLoad() {
super.viewDidLoad()
let navController = navigationController!
navController.navigationBar.addSubview(navStackView)
// x, y, w, h
navStackView.leadingAnchor.constraint(equalTo: navController.navigationBar.leadingAnchor).isActive = true
navStackView.trailingAnchor.constraint(equalTo: navController.navigationBar.trailingAnchor).isActive = true
navStackView.topAnchor.constraint(equalTo: navController.navigationBar.topAnchor).isActive = true
navStackView.bottomAnchor.constraint(equalTo: navController.navigationBar.bottomAnchor).isActive = true
for image in images {
let imageView = UIImageView()
imageView.image = UIImage(named: image)
imageView.layer.cornerRadius = imageView.bounds.height / 2
imageView.clipsToBounds = true
imageView.layer.masksToBounds = true
imageView.contentMode = .scaleAspectFill
// imageView.frame = CGRect(x: 0, y: 0, width: 30, height: 30)
navStackView.addArrangedSubview(imageView)
navStackView.layoutIfNeeded()
}
navigationItem.titleView = navStackView
}
Here's the result so far (I'm stuck though, not sure how to accomplish it):
I'm not sure about stackView. But for a simple implementation I've used collectionView. Check the below strategy. You should be able to modify accordingly per your requirement.
import UIKit
class OverlayCell: UICollectionViewCell {
func didplay(with number: String) {
let view = UIView(frame: CGRect(x: 0, y: 0, width: 40.0, height: 40.0))
view.backgroundColor = UIColor.blue
view.layer.cornerRadius = 20.0
view.layer.masksToBounds = true
view.layer.borderColor = UIColor.white.cgColor
view.layer.borderWidth = 2.0
let label = UILabel(frame: CGRect(x: 2, y: 2, width: view.bounds.width - 4, height: view.bounds.height - 4))
label.textColor = .white
label.text = number
label.textAlignment = .center
view.addSubview(label)
contentView.addSubview(view)
contentView.transform = CGAffineTransform(scaleX: -1, y: 1)
}
}
class OverlayedView: UIView {
var mainView: UIView!
var imageCollection: UICollectionView!
//Static for now
let cellWidth: CGFloat = 40.0
let cellHeight: CGFloat = 40.0
var collectionWidth: CGFloat = 115.0
override init(frame: CGRect) {
super.init(frame: frame)
loadNib()
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
loadNib()
}
private func loadNib() {
if let view = Bundle.main.loadNibNamed("OverlayedView", owner: self, options: nil)?.first as? UIView {
mainView = view
mainView.frame = self.bounds
self.backgroundColor = .black
addSubview(view)
}
}
var dataSource = ["4","3","2","1"]
func loadData() {
//dynamically calculate collectionWidth to be able to kepp it in center
collectionWidth = dataSource.count >= 4 ? CGFloat(dataSource.count) * cellWidth - CGFloat((dataSource.count - 1) * 15) : CGFloat(dataSource.count) * cellWidth - CGFloat((dataSource.count - 1) * 15) //CGFloat(dataSource.count * 15) here is the item spacing from delegate -15 inward so that we can get overlapping effect
let layout = UICollectionViewFlowLayout()
layout.scrollDirection = .horizontal
imageCollection = UICollectionView(frame: CGRect(x: 0, y: 0, width: collectionWidth, height: self.bounds.height), collectionViewLayout: layout)
imageCollection.center = mainView.center
imageCollection.register(OverlayCell.self, forCellWithReuseIdentifier: "Cell")
//flip the collectionView so that it loads from right to left for overlapping effect
imageCollection.transform = CGAffineTransform(scaleX: -1, y: 1)
imageCollection.delegate = self
imageCollection.dataSource = self
mainView.addSubview(imageCollection)
}
}
extension OverlayedView: UICollectionViewDelegate, UICollectionViewDelegateFlowLayout, UICollectionViewDataSource {
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
if dataSource.count > 4 {
return 4
}
return dataSource.count
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "Cell", for: indexPath) as! OverlayCell
cell.didplay(with: dataSource[indexPath.row])
return cell
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
let size = CGSize(width: 40.0 , height: 40.0)
return size
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumInteritemSpacingForSectionAt section: Int) -> CGFloat {
return 0.0
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumLineSpacingForSectionAt section: Int) -> CGFloat {
return -15.0
}
}
Usage:
let navOverlay = OverlayedView(frame: CGRect(x: 0, y: 0, width: 250.0, height: 44.0))
navOverlay.loadData() . //pass your data to this method
navigationItem.titleView = navOverlay
I've figured it out finally. Not sure if this is the right way to accomplish it, but it's a way to accomplish it and it works great. The thing to notice - I have to calculate the navStackView width based on the number of images we have. More than 5-6 images gets too crouded, so, no more than 5 images.
The navStackView.spacing also is calculated based the width and the space you'd like between the images.
var navStackView : UIStackView = {
let stack = UIStackView()
stack.axis = .horizontal
stack.alignment = .fill
stack.distribution = .fillEqually
stack.translatesAutoresizingMaskIntoConstraints = false
return stack
}()
var moreLabel: UILabel = {
let label = UILabel()
label.text = "+ 5 more"
label.textColor = .black
label.textAlignment = .left
label.translatesAutoresizingMaskIntoConstraints = false
return label
}()
var images = ["1", "2", "3", "4", "3", "3"]
override func viewDidLoad() {
super.viewDidLoad()
let navController = navigationController!
navController.navigationBar.addSubview(navStackView)
// x, y, w, h
navStackView.widthAnchor.constraint(equalToConstant: 95).isActive = true
navStackView.centerYAnchor.constraint(equalTo: navController.navigationBar.centerYAnchor).isActive = true
navStackView.heightAnchor.constraint(equalToConstant: 35).isActive = true
navStackView.centerXAnchor.constraint(equalTo: navController.navigationBar.centerXAnchor).isActive = true
// image height = 35, image width = 35
// when subtracting spacing from NavStackView, we need to subtrack from the width as well for (items - 1)
switch images.count {
case 0:
print("0 images")
case 1:
changeNavStackWidth(constant: 60, spacing: 0)
moreLabel.isHidden = true
case 2:
changeNavStackWidth(constant: 80, spacing: 10)
moreLabel.isHidden = true
case 3:
changeNavStackWidth(constant: 95, spacing: -5)
moreLabel.isHidden = true
case 4:
changeNavStackWidth(constant: 110, spacing: -10)
moreLabel.isHidden = true
case 5:
changeNavStackWidth(constant: 95, spacing: -20)
moreLabel.isHidden = true
case 6...1000:
changeNavStackWidth(constant: 95, spacing: -20)
moreLabel.isHidden = false
default:
print("default")
}
for image in images {
let imageView = UIImageView()
imageView.image = UIImage(named: image)
imageView.layer.borderColor = UIColor.white.cgColor
imageView.layer.borderWidth = 1
imageView.contentMode = .scaleAspectFill
imageView.clipsToBounds = true
navStackView.addArrangedSubview(imageView)
navStackView.layoutIfNeeded()
}
navController.navigationBar.addSubview(moreLabel)
// x, y ,w, h
moreLabel.leadingAnchor.constraint(equalTo: navStackView.trailingAnchor, constant: 50).isActive = true
moreLabel.topAnchor.constraint(equalTo: navStackView.topAnchor).isActive = true
moreLabel.bottomAnchor.constraint(equalTo: navStackView.bottomAnchor).isActive = true
navigationItem.titleView = navStackView
let stackTap = UITapGestureRecognizer()
stackTap.addTarget(self, action: #selector(stackTapped))
navStackView.isUserInteractionEnabled = true
navStackView.addGestureRecognizer(stackTap)
}
#objc func stackTapped() {
print("tapp")
}
func changeNavStackWidth(constant: CGFloat, spacing: CGFloat) {
navStackView.constraints.forEach { constraint in
if constraint.firstAttribute == .width {
constraint.constant = constant
}
}
navStackView.spacing = spacing
}
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
navStackView.subviews.forEach { $0.layer.cornerRadius = $0.frame.height / 2 }
}

Swift 4 - Multiple inheritance from classes 'NSObject' and 'UICollectionViewFlowLayout'

I am trying to programatically size the collection cell to be the width of the frame, however, the cell size doesn't change when I run the app. Is this the right function to call for Swift 4 and Xcode 9?
import UIKit
class SettingsLauncher: NSObject, UICollectionViewDelegate, UICollectionViewDataSource, UICollectionViewFlowLayout {
let blackView = UIView()
let collectionView: UICollectionView = {
let layout = UICollectionViewFlowLayout()
let cv = UICollectionView(frame: .zero, collectionViewLayout: layout)
cv.backgroundColor = UIColor.white
return cv
}()
let cellID = "cell"
#objc func showMenu() {
// Show menu
if let window = UIApplication.shared.keyWindow { // Get the size of the entire window
blackView.backgroundColor = UIColor(white: 0, alpha: 0.5)
let height: CGFloat = 200
let y = window.frame.height - height // The y value to appear at the bottom of the screen
collectionView.frame = CGRect(x: 0, y: window.frame.height, width: window.frame.width, height: height)
// Add gesture recognizer on black view to dismiss menu
blackView.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(handleDismiss)))
window.addSubview(blackView)
window.addSubview(collectionView)
blackView.frame = window.frame
blackView.alpha = 0
// Slow the animation down towards the end (curveEasOut)
UIView.animate(withDuration: 1, delay: 0, usingSpringWithDamping: 1, initialSpringVelocity: 1, options: .curveEaseOut, animations: {
// Animate black view
self.blackView.alpha = 1
// Animate collection view
self.collectionView.frame = CGRect(x: 0, y: y, width: self.collectionView.frame.width, height: height)
}, completion: nil)
}
}
#objc func handleDismiss() {
// Dimisses menu view
UIView.animate(withDuration: 0.5) {
self.blackView.alpha = 0
if let window = UIApplication.shared.keyWindow {
self.collectionView.frame = CGRect(x: 0, y: window.frame.height, width: self.collectionView.frame.width, height: self.collectionView.frame.height)
}
}
}
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return 6
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: cellID, for: indexPath)
return cell
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
return CGSize(width: collectionView.frame.width, height: 50)
}
override init() {
super.init()
collectionView.delegate = self
collectionView.dataSource = self
collectionView.register(MenuCell.self, forCellWithReuseIdentifier: cellID)
}
}
Edit:
This table view is being animated from the bottom of the page and presents a collection view, which is being called from the view controller that is using the pop up menu.
I now get the error:
Multiple inheritance from classes 'NSObject' and 'UICollectionViewFlowLayout'
UICollectionViewFlowLayout is not a protocol, it's a class. You need to use UICollectionViewDelegateFlowLayout instead of UICollectionViewFlowLayout.
Change
class SettingsLauncher: NSObject, UICollectionViewDelegate, UICollectionViewDataSource, UICollectionViewFlowLayout
to
class SettingsLauncher: NSObject, UICollectionViewDelegate, UICollectionViewDataSource, UICollectionViewDelegateFlowLayout

TableView rows dissapear when tapped

I have a table view embedded in an iCarousel item and firstly I can't seem to set the view frame whether it's in viewDidLayoutSubviews() but also when I tap the Tableview all the cells disappear. I have created the Tableview in its own ViewController as each carousel item will need editing buttons for the Tableviews they contain. If I don't put the Tableview in its own view controller the cells remain but I get an index out of range when scrolling a lot of views and I can't add editing buttons. I've run out of ideas and would love some pointers or tips.
class BillSplitterTableView: UIViewController, UITableViewDataSource, UITableViewDelegate {
var splitter: BillSplitter?
var tableView: UITableView!
var viewFrame: CGRect?
init(frame: CGRect, splitter: BillSplitter) {
super.init(nibName: nil, bundle: nil)
self.splitter = splitter
self.viewFrame = frame
}
required init(coder aDecoder: NSCoder) {
fatalError("init(coder:)")
}
override func viewDidLoad() {
super.viewDidLoad()
let subView = UIView(frame: viewFrame!)
view.backgroundColor = .clear
tableView = UITableView(frame: view.frame)
tableView.delegate = self
tableView.dataSource = self
tableView.frame = subView.frame
tableView.separatorStyle = .none
tableView.estimatedRowHeight = 35
let tableViewBackground = UIImageView(image: UIImage(data: splitter?.image as! Data, scale:1.0))
tableViewBackground.contentMode = .scaleAspectFit
tableViewBackground.frame = tableView.frame
tableView.backgroundView = tableViewBackground
subView.addSubview(tableView)
view.addSubview(subView)
}
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return UITableViewAutomaticDimension
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
if (splitter?.items?.count)! > 0 {
return (splitter!.items?.count)!
} else {
TableViewHelper.EmptyMessage("\(splitter?.name!) has no items to pay for.", tableView: tableView)
return 0
}
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
tableView.register(SplitterCarouselItemTableViewCell.classForCoder(), forCellReuseIdentifier: "splitterCarouselItemTableViewCell")
let cell: SplitterCarouselItemTableViewCell = tableView.dequeueReusableCell(withIdentifier: "splitterCarouselItemTableViewCell") as! SplitterCarouselItemTableViewCell
let item = (splitter?.items?.allObjects as! [Item])[indexPath.row]
let count = item.billSplitters?.count
cell.backgroundColor = UIColor(netHex: 0xe9edef).withAlphaComponent(0.5)
if count! > 1 {
cell.name!.text = "\(item.name!)\nsplit \(count!) ways"
cell.price!.text = "£\(Double(item.price)/Double(count!))"
} else {
cell.name!.text = item.name!
cell.price!.text = "£\(item.price)"
}
return cell
}
}
the carousel viewcontroller:
func numberOfItems(in carousel: iCarousel) -> Int {
return allBillSplitters.count
}
func carousel(_ carousel: iCarousel, viewForItemAt index: Int, reusing view: UIView?) -> UIView {
let splitter = allBillSplitters[index]
carouselIndex = index
let splitterView = SplitterCarouselItemView(frame: CGRect(x: 0, y: 0, width: width, height: height))
let viewWidth = Int(splitterView.frame.width)
let nameLabel = SplitterCarouselItemNameLabel(frame: CGRect(x: 0, y: 0, width: viewWidth, height: 30))
let emailLabel = SplitterCarouselItemEmailLabel(frame: CGRect(x: 0, y: 30, width: viewWidth, height: 20))
let addItemButton = SplitterCarouselItemButton(frame: CGRect(x: viewWidth - 45, y: 50, width: 35, height: 35), addsItem: true)
let deleteItemButton = SplitterCarouselItemButton(frame: CGRect(x: 15, y: 50, width: 35, height: 35), addsItem: false)
let itemHeight = Int(splitterView.frame.height)
let payTotalButton = SplitterCarouselItemPayButton(frame: CGRect(x: 0, y: itemHeight - 35, width: viewWidth + 1, height: 35))
let tableViewHeight = Int(height - 130)
let frame = CGRect(x: 0, y: 85, width: viewWidth, height: tableViewHeight)
let tableView = BillSplitterTableView(frame: frame, splitter: splitter)
splitterView.addSubview(nameLabel)
splitterView.addSubview(emailLabel)
splitterView.addSubview(addItemButton)
splitterView.addSubview(deleteItemButton)
splitterView.addSubview(tableView.view)
splitterView.addSubview(payTotalButton)
nameLabel.text = "\(allBillSplitters[index].name!)"
emailLabel.text = "\(allBillSplitters[index].email!)"
payTotalButton.setTitle("Pay £\(allBillSplitters[index].total)", for: .normal)
return splitterView
}
func carousel(_ carousel: iCarousel, valueFor option: iCarouselOption, withDefault value: CGFloat) -> CGFloat {
if allBillSplitters.count > 2 {
switch option {
case .spacing:
return value * 1.05
case .fadeMin:
return 0.0
case .fadeMinAlpha:
return 0.3
case .fadeMax:
return 0.0
default:
return value
}
}
return value
}
Thanks for any help in advance

Swift CollectionView Vertical Paging

I enabled paging on my collectionview and encountered the first issue of each swipe not stopping on a different cell, but page.
I then tried to enter code and handle the paging manually in ScrollViewWillEndDecelerating.
However my problem is the changing the collectionviews ContentOffset or scrolling to a Point both do not work unless called in LayoutSubiews. that is the only place where they effect the CollectionView
Each cell in my collection view is full screen. I handle the cell sizing in layout subviews.
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
if let layout = customCollectionView.collectionViewLayout as? UICollectionViewFlowLayout {
let itemWidth = view.frame.width
let itemHeight = view.frame.height
layout.itemSize = CGSize(width: itemWidth, height: itemHeight)
layout.invalidateLayout()
}
let ip = IndexPath(row: 2, section: 0)
view.layoutIfNeeded()
customCollectionView.scrollToItem(at: ip, at: UICollectionViewScrollPosition.centeredVertically, animated: true)
let point = CGPoint(x: 50, y: 600)
customCollectionView.setContentOffset(point, animated: true)
}
func scrollViewWillEndDragging(_ scrollView: UIScrollView, withVelocity velocity: CGPoint, targetContentOffset: UnsafeMutablePointer<CGPoint>) {
let pageHeight = customCollectionView.bounds.size.height
let videoLength = CGFloat(videoArray.count)
let minSpace:CGFloat = 10
var cellToSwipe = (scrollView.contentOffset.y) / (pageHeight + minSpace) + 0.5
if cellToSwipe < 0 {
cellToSwipe = 0
}
else if (cellToSwipe >= videoLength){
cellToSwipe = videoLength - 1
}
let p = Int(cellToSwipe)
let roundedIP = round(Double(Int(cellToSwipe)))
let ip = IndexPath(row: Int(roundedIP), section: 0)
let ip = IndexPath(row: 2, section: 0)
view.layoutIfNeeded()
customCollectionView.scrollToItem(at: ip, at: UICollectionViewScrollPosition.centeredVertically, animated: true)
}
First off, I would recommend making your view controller class conform to UICollectionViewDelegateFlowLayout and use the following delegate method to size your UICollectionViewCells
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
let size = CGSize(width: view.frame.width, height: view.frame.height)
return size
}
Then in your viewDidLoad call
customCollectionView.isPagingEnabled = true