UICollectionView on UIScrollView freezes - ios

I have an UIViewController, which contains UIScrollView, which contains a few elements, including UICollectionView. UICollectionView is used to display N buttons in fixed frame. UICollectionView scrolling is disabled. Still, my UIScrollView scrolls not as smoothly as it scrolls without UICollectionView. What my be the problem? Does it have something to do with reusable cells?
code:
func numberOfSectionsInCollectionView(collectionView: UICollectionView) -> Int {
return 1
}
func collectionView(collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return 9
}
func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCellWithReuseIdentifier("tagsCell", forIndexPath: indexPath) as! TagsCollectionViewCell
cell.backgroundColor = UIColor.clearColor()
cell.tagsButton.setTitle("Test", forState: .Normal)
cell.tagsButton.sizeToFit()
return cell
}
func collectionView(collectionView: UICollectionView!, layout collectionViewLayout: UICollectionViewLayout!,
sizeForItemAtIndexPath indexPath: NSIndexPath!) -> CGSize
{
let element = "Test" as NSString
let stringSize = element.sizeWithAttributes([NSFontAttributeName: UIFont.systemFontOfSize(17.0)])
return CGSize(width: stringSize.width + 25, height: 29)
}

If the frame of the scrollView and collectionView is same then it must be a problem to differentiate, which one to call. May be that is why it's creating an issue with the collectionView.

Related

How to change the cell height after putting a collection view into a table view

I'm trying to put some images with horizontal scrolling in a tableview cell, so I use a collectionview, I put it into the cell, and everything works except the cell height. I've chosen the cell height to custom in storyboard, and changed the cell height with code too, but it still doesn't work. I'm a rookie, I can't find where the problem is, please help me, thank you guys!
1.I want to change the cell height
2.Stroyboard
class HomePageTableViewController: UITableViewController {
var ImageArray = [String]()
override func viewDidLoad() {
super.viewDidLoad()
ImageArray = ["Calendar.png","Calendar.png","Calendar.png","Calendar.png","Calendar.png"]
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return ImageArray.count
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "BannerCell") as! BannerTableViewCell
return cell
}
override func viewWillAppear(_ animated: Bool) {
tableView.estimatedRowHeight = 100
tableView.rowHeight = UITableViewAutomaticDimension
}
}
extension HomePageTableViewController: UICollectionViewDelegate,
UICollectionViewDataSource {
func numberOfSections(in collectionView: UICollectionView) -> Int {
return 1
}
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return ImageArray.count
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath)
-> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "BannerCollection", for: indexPath) as! BannerCollectionCollectionViewCell
cell.BannerImage.image = UIImage(named: ImageArray[indexPath.row])
return cell
}
}
You probably need to set the collectionviewcell size such as the following:
extension HomePageTableViewController: UICollectionViewDelegateFlowLayout {
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
// Return the cell size
let cellSize = CGSize(width: collectionView.bounds.width, height: collectionView.bounds.width * (ratioToUse))
return cellSize
}
}
I've done something similar where I'm using a collectionview to scroll horizontally but I'm using the full width for each cell and calculating the aspectratio. However, you'll need to modify this for the size you want.
I had to do some tricks elsewhere to size the collectionview itself as well.
I would try this first then, if you're still having problems, post an image of what it looks like.
Update #2:
If you are using AutoLayout, you shouldn't need to do this but you can set the height yourself using the following:
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
<#code#>
}
Update #3:
I just some testing with this. You should put a height constraint on your collectionview and that should make the tableviewcell resize appropriately. You shouldn't need "heightForRowAt" as I mentioned above. AutoLayout should handle this for you.
Try to change the content mode of the UIImageView to aspect fit. It might work.

how can we achieve appearance of collection view as shown in image below?

Also i need to have circular scrolling enabled for that collection view.
Can anyone please help me out?
First of all drag collection view in your respective ViewController and then select scroll direction as Horizontal in activity inspector.
func collectionView(collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumLineSpacingForSectionAtIndex section: Int) -> CGFloat {
return collectionView.frame.size.width/2
}
func collectionView(collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAtIndexPath indexPath: NSIndexPath) -> CGSize {
return CGSizeMake((collectionView.frame.size.height) , (collectionView.frame.size.height))
}
func collectionView(collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return img_Arr.count
}
// make a cell for each cell index path
func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
// get a reference to our storyboard cell
let cell = collectionView.dequeueReusableCellWithReuseIdentifier("Cell3", forIndexPath: indexPath) as! ImageCaptureCell
cell.CapturedImage.clipsToBounds = true
cell.contentView.frame = cell.bounds
let capt = UIImage(data:img_Arr[indexPath.row] as! NSData,scale:1.0)
cell.CapturedImage.image = capt
return cell
}
// MARK: - UICollectionViewDelegate protocol
func collectionView(collectionView: UICollectionView, didSelectItemAtIndexPath indexPath: NSIndexPath) {
// handle tap events
print("You selected cell #\(indexPath.item)!")
}
func collectionView(collectionView: UICollectionView, didHighlightItemAtIndexPath indexPath: NSIndexPath)
{
let cell = collectionView.cellForItemAtIndexPath(indexPath)
//cell?.backgroundColor = UIColor.redColor()
}
// change background color back when user releases touch
func collectionView(collectionView: UICollectionView, didUnhighlightItemAtIndexPath indexPath: NSIndexPath) {
let cell = collectionView.cellForItemAtIndexPath(indexPath)
// cell?.backgroundColor = UIColor.yellowColor()
}
Additionaly give search bar on top and connet to the table delegate

UICollectionView reuse in UITableViewCell

I know this question is already ask many times but non of the solution will work.
I have collection view in uitableview cell and i prepare a cell of table view and collection view in story board and my problem is that suppose i scroll cell 1 collection view then cell 4 collection is auto scroll to that position also. How i can handle this situation..
Please note right now i make a static design of the screen
My code
// MARK:
// MARK: table view delegate method
func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return 1
}
func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
if Appconstant.isIpad()
{
return 215.0
}
return 185.0
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 6
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let strCell = "WorkoutCell" //+ "\(indexPath.row)"
let cell = tableView.dequeueReusableCellWithIdentifier(strCell) as? WorkoutCell
// if cell == nil
// {
// cell = work
// }
return cell!
}
func tableView(tableView: UITableView, willDisplayCell cell: UITableViewCell, forRowAtIndexPath indexPath: NSIndexPath) {
let cell2 = cell as! WorkoutCell
cell2.collecionWorkout.reloadData()
}
// MARK:
// MARK: collectionview delegate and data source
//1
func shouldInvalidateLayoutForBoundsChange(newBounds: CGRect) -> Bool {
return true
}
func numberOfSectionsInCollectionView(collectionView: UICollectionView) -> Int {
return 1
}
//2
func collectionView(collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return 10
}
func collectionView(collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, insetForSectionAt section: Int) -> UIEdgeInsets {
return UIEdgeInsetsMake(0.0, 10.0, 0.0, 10.0)
}
func collectionView(collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: NSIndexPath) -> CGSize {
// Adjust cell size for orientation
if Appconstant.isIpad() {
return CGSize(width: 160, height: 150)
}
return CGSize(width: 140.0, height: 130.0)
}
//3
func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCellWithReuseIdentifier("WorkoutCollectionCell", forIndexPath: indexPath)
// Configure the cell
return cell
}
uitableview cell code
class WorkoutCell: UITableViewCell {
#IBOutlet weak var collecionWorkout: UICollectionView!
var flowLayout : UICollectionViewFlowLayout!
override func awakeFromNib() {
super.awakeFromNib()
self.flowLayout = UICollectionViewFlowLayout()
if Appconstant.isIpad()
{
self.flowLayout.itemSize = CGSize(width: 160, height: 150)
}
else
{
self.flowLayout.itemSize = CGSize(width: 140, height: 130)
}
self.flowLayout.scrollDirection = .Horizontal
self.flowLayout.minimumInteritemSpacing = 10.0
flowLayout.sectionInset = UIEdgeInsetsMake(0.0, 10.0, 0.0, 10.0);
collecionWorkout.collectionViewLayout = flowLayout
// Initialization code
}
override func setSelected(selected: Bool, animated: Bool) {
super.setSelected(selected, animated: animated)
// Configure the view for the selected state
}
}
Cell 1st which i scroll
cell 4th which auto scroll
There are two scenarios.
1 - Reset The UICollectionView offset position :
To Reset the collectionview position just call cell.collectionView.contentOffset = .zero in cellForRowAtIndexPath
2 - Maintain the previous scroll position :
To Maintain the previous scroll position, You'll need to have a list of offsets for each cell stored alongside your data models in the containing view controller. Then you might save the offset for a given cell in didEndDisplayingCell and setting it in cellForRowAtIndexPath instead of .zero .
UITableView works on the concept of reusability. Whenever the tableView is scrolled, the cells in the tableView will definitely be reused.
Now 2 scenarios arise with this,
Get a new cell - When the tableViewCell is reused, the collectionView inside it also will be reused and so this is the reason the contentOffset of the previous cell is retained.
Scroll to previous cell - if we've manually scrolled to a particular cell in the collectionView, we might want to retain its position when we scroll back to it.
To get this kind of functionality in tableView, we need to - manually reset the contentOffset for 1st case and need to retain the contentOffset in the 2nd one.
Another approach you can follow is using a combination of UIScrollview and UIStackView.
This is how it goes.
In storyboard, create a UIScrollView. Add a vertical UIStackView to it.
Add 4 UICollectionViews in the stackView. This number is configurable as per your requirement.
Add your controller as the dataSource and delegate of all the collectionViews.
i.e.
class ViewController: UIViewController, UICollectionViewDataSource {
override func viewDidLoad() {
super.viewDidLoad()
}
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return 10
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "cell", for: indexPath) as! CustomCell
cell.label.text = "\(indexPath.row)"
return cell
}
}
class CustomCell: UICollectionViewCell {
#IBOutlet weak var label: UILabel!
}
Now, since we're using a stackView, none of the collectionViews will be reused. So, the contentOffsets of the all the collectionViews will remain intact.

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

Putting horizontally scrolling UICollectionView into vertically scrolling UICollectionViewCell

I have a vertically scrolling UICollectionview with different elements. In one section, I would like to show multiple horizontally scrollable elements. This is how my setup looks like:
A Prototype Cell (subclass of UICollectionViewCell):
class SlidingCollectionViewCell: UICollectionViewCell, UICollectionViewDelegate, UICollectionViewDataSource, UICollectionViewDelegateFlowLayout {
func numberOfSectionsInCollectionView(collectionView: UICollectionView) -> Int {
return 2
}
func collectionView(collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return 8
}
func collectionView(collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAtIndexPath indexPath: NSIndexPath) -> CGSize {
return CGSizeMake(130, 100)
}
func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
return collectionView.dequeueReusableCellWithReuseIdentifier("SwipeContainedCell", forIndexPath: indexPath) as! UICollectionViewCell
}
}
Whatever I do, it just doesn't scroll horizontally :-(. What am I doing wrong?
make sure that you don't have the nested CollectionView inside an UIView

Resources