Collectionview Flowlayout Overlapping When Scrolling Not Working

Keep Collection View Cells Overlapped When They Are Redrawn

Try this, that might help you:

1- Inside your Cells, you could define innerView inside your cell and set the frame to

let innerView:UIView = CGRect(x: 0,y: -overlapHeight,width: screenWidth, height:cell.height + overlapHeight)
cell?.contentView.addSubview(innerView)

2- Configure your cell during initialisation with this:

cell?.contentView.clipsToBounds = false

3- When loading cell, set the z-order:

override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: reuseIdentifier, for: indexPath)
cell.layer.zPosition = CGFloat(indexPath.row)
// configure your cell after here
}

You should be able to see the nested views inside your content view to have overlapping.

I have drafted a sample code, not looking perfectly, but will help you get started:

private let reuseIdentifier = "Cell"
private let overlapHeight:CGFloat = 100
class CustomCollectionCell:UICollectionViewCell {
var innerView:UIView?
override init(frame: CGRect) {
super.init(frame: CGRect(x: 0, y: 0, width: UIScreen.main.bounds.width, height: 300))
self.backgroundColor = .darkGray
let innerView = UIView(frame: CGRect(x: 0,y: -overlapHeight,width: UIScreen.main.bounds.width,height: overlapHeight + self.contentView.frame.height))
self.innerView = innerView
innerView.layer.cornerRadius = 20
self.contentView.addSubview(innerView)
self.contentView.clipsToBounds = false
}

required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}

func configure(color:UIColor?) {
innerView?.backgroundColor = color
}
}

import UIKit

private let reuseIdentifier = "Cell"
private let overlapHeight:CGFloat = 100
class CustomCollectionCell:UICollectionViewCell {
var innerView:UIView?
override init(frame: CGRect) {
super.init(frame: frame)
self.backgroundColor = .darkGray
let innerView = UIView(frame: CGRect(x: 0,y: -overlapHeight,width: UIScreen.main.bounds.width,height: overlapHeight + self.contentView.frame.height))
self.innerView = innerView
innerView.layer.cornerRadius = 20
self.contentView.addSubview(innerView)
self.contentView.clipsToBounds = false
}

required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}

func configure(color:UIColor?) {
innerView?.backgroundColor = color
}
}

class CollectionViewController: UICollectionViewController {

override func viewDidLoad() {
super.viewDidLoad()

let flowLayout = UICollectionViewFlowLayout()
flowLayout.itemSize = CGSize(width: UIScreen.main.bounds.width, height: 190)
flowLayout.sectionInset = UIEdgeInsets(top: 0, left: 5, bottom: 0, right: 5)
flowLayout.scrollDirection = .vertical
flowLayout.minimumInteritemSpacing = 0.0
collectionView.collectionViewLayout = flowLayout

// Register cell classes
self.collectionView!.register(CustomCollectionCell.self, forCellWithReuseIdentifier: reuseIdentifier)

}

// MARK: UICollectionViewDataSource

override func numberOfSections(in collectionView: UICollectionView) -> Int {
// #warning Incomplete implementation, return the number of sections
return 1
}

override func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
// #warning Incomplete implementation, return the number of items
return 30
}

override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: reuseIdentifier, for: indexPath)
cell.layer.zPosition = CGFloat(indexPath.row)

var color:UIColor?
switch indexPath.row % 4 {
case 0:
color = .purple
case 1:
color = .yellow
case 2:
color = .green
default:
color = .red
}
if let cell = cell as? CustomCollectionCell {
cell.configure(color: color)
}

return cell
}

}

Result:

Sample Image

UICollectionViewCells overlapping

I found the problem, the problem is in the cell, I am adding whole view as a subview because I am using nib. I am doing it so because I want to use nib and UICollectionViewCell class too.

[self addSubview:[[[NSBundle mainBundle] loadNibNamed:@"LoungeUserPostCell" owner:self options:nil]objectAtIndex:0]];

- (id)initWithFrame:(CGRect)frame {

self = [super initWithFrame:frame];
if (self) {
// Initialization code
self.backgroundColor=[UIColor orangeColor];

[self addSubview:[[[NSBundle mainBundle] loadNibNamed:@"LoungeUserPostCell" owner:self options:nil]objectAtIndex:0]];

[self onLoadAdjustments];
}
return self;
}

now I am registering it as nib in Collection view and use - (void)awakeFromNib method to make changes in nib.

How archive like this CollectionView stacked Cell for Overlapping Cell Like Wallet

I have tried it's working fine, thanks to everyone

class CardLayout: UICollectionViewLayout {
var contentHeight: CGFloat = 0.0
var cachedAttributes = [UICollectionViewLayoutAttributes]()
var nextIndexPath: Int?
override init() {
super.init()
}

required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}

override var collectionViewContentSize: CGSize {
var size = super.collectionViewContentSize
let collection = collectionView!
size.width = collection.bounds.size.width
if let _ = FlowLayoutAttributes.shared.cellIndex{
size.height = contentHeight+UIScreen.main.bounds.width/2+38
}else{
size.height = contentHeight
}
print("Contend",contentHeight)
return size
}


func reloadData(){
self.cachedAttributes = [UICollectionViewLayoutAttributes]()
}

override func prepare() {
cachedAttributes.removeAll()
guard let numberOfItems = collectionView?.numberOfItems(inSection: 0) else {
return
}
for index in 0..<numberOfItems {
let layout = UICollectionViewLayoutAttributes(forCellWith: IndexPath(row: index, section: 0))
layout.frame = frameFor(index: index)

if let indexExpand = FlowLayoutAttributes.shared.cellIndex, indexExpand == index {
self.nextIndexPath = index+1
contentHeight = CGFloat(CGFloat(numberOfItems)*getCardSize())+UIScreen.main.bounds.width/2+38*2
}else{
contentHeight = CGFloat(CGFloat(numberOfItems)*getCardSize())+UIScreen.main.bounds.width/2+38
}
layout.zIndex = index
layout.isHidden = false

cachedAttributes.append(layout)
}
}

override func layoutAttributesForElements(in rect: CGRect) -> [UICollectionViewLayoutAttributes]? {

var layoutAttributes = [UICollectionViewLayoutAttributes]()

for attributes in cachedAttributes {
if attributes.frame.intersects(rect) {
layoutAttributes.append(cachedAttributes[attributes.indexPath.item])
}

}
return layoutAttributes
}
override func shouldInvalidateLayout(forBoundsChange newBounds: CGRect) -> Bool {
return true
}
override func layoutAttributesForItem(at indexPath: IndexPath) -> UICollectionViewLayoutAttributes? {
return cachedAttributes[indexPath.item]
}
func frameFor(index: Int) -> CGRect {
var frame = CGRect(origin: CGPoint(x: CGFloat(8), y:0), size: CGSize(width: UIScreen.main.bounds.width - CGFloat(8 + 8), height: CGFloat(UIScreen.main.bounds.width/2+38)))
var frameOrigin = frame.origin
if let indexExpand = FlowLayoutAttributes.shared.cellIndex{
if index > 0 {
if indexExpand < index {
let spacesHeight = CGFloat((getCardSize() * CGFloat(index)))+UIScreen.main.bounds.width/2+38-getCardSize()/2
frameOrigin.y = spacesHeight
}else{
frameOrigin.y = CGFloat((getCardSize() * CGFloat(index)))
}
}
}else{
if index > 0 {
frameOrigin.y = CGFloat((getCardSize() * CGFloat(index)))
}
}
frame.origin = frameOrigin
return frame
}
func getCardSize()-> CGFloat{
if UIDevice().userInterfaceIdiom == .phone {
switch UIScreen.main.nativeBounds.height {
case 1136:
print("iPhone 5 or 5S or 5C")
return 45.25
case 1334:
print("iPhone 6/6S/7/8")
return 45.25
case 1920, 2208:
print("iPhone 6+/6S+/7+/8+")
return 46
case 2436:
print("iPhone X/XS/11 Pro")
return 45.25
case 2688:
print("iPhone XS Max/11 Pro Max")
return 46
case 1792:
print("iPhone XR/ 11 ")
return 46
case 2532:
print("iPhone 12/ iPhone 12 Pro")
return 45.50
case 2778:
print("iPhone 12 Pro Max")
return 46.2
default:
return 46.2
}
}else{
return CGFloat(46.2)
}
}

}

UICollectionViewCell labels overlap each other in background color

In swift 2.0

class MYVIEWCONTROLLER: UIViewController ,UICollectionViewDelegate , UICollectionViewDataSource , UICollectionViewDelegateFlowLayout{

var items = ["12", "2", "3221", "434", "52342","bdvjsd","Hello","5646445646454464654646464", "bdvjsd", "adscfaaaw", "How are you?"];

// collectionview delegates methods.
func collectionView(collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return self.items.count
}

func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {

let cell = collectionView.dequeueReusableCellWithReuseIdentifier("invitecell", forIndexPath: indexPath)
let label: UILabel = (cell.viewWithTag(15) as! UILabel)
label.text = self.items[indexPath.item]

return cell
}

// collectionview layoutflow method. first this method call then other delagates method call.
func collectionView(collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAtIndexPath indexPath: NSIndexPath) -> CGSize {

return CGSize(width: self.findHeightForText(self.items[indexPath.item], havingWidth: self.view.frame.size.width - 116, andFont: UIFont.systemFontOfSize(14.0)).width + 12, height: 35)

}
func findHeightForText(text: String, havingWidth widthValue: CGFloat, andFont font: UIFont) -> CGSize {
var size = CGSizeZero
if text.isEmpty == false {
let frame = text.boundingRectWithSize(CGSizeMake(widthValue, CGFloat.max), options: .UsesLineFragmentOrigin, attributes: [NSFontAttributeName: font], context: nil)
size = CGSizeMake(frame.size.width, ceil(frame.size.height))
}
return size
}
func collectionView(collectionView: UICollectionView, didSelectItemAtIndexPath indexPath: NSIndexPath){

print("Selected item :\(self.items[indexPath.item])")
}

In Swift 3.0

Don't Forget to look at class declaration. It extends UICollectionViewDelegateFlowLayout also

class ViewController: UIViewController, UICollectionViewDelegate, UICollectionViewDataSource, UICollectionViewDelegateFlowLayout {

let reuseIdentifier = "cell"
var items = ["12", "2", "3221", "434", "52342","5646445646454446464", "bdvjsd", "adscfaaaw", "How are you?"];

@IBOutlet weak var myCollectionView: UICollectionView!
@IBOutlet weak var flowLayout: UICollectionViewFlowLayout!
override func viewDidLoad() {
super.viewDidLoad()
}

override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}

func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
let Labell : UILabel = UILabel()

Labell.text = self.items[indexPath.item]
let labelTextWidth = Labell.intrinsicContentSize.width
return CGSize(width: labelTextWidth + 12, height: 35)

}

func findHeightForText(text: String, havingWidth widthValue: CGFloat, andFont font: UIFont) -> CGSize {
var size = CGSize()
if text.isEmpty == false {
let frame = text.boundingRect(with: CGSize(width: widthValue, height: CGFloat.greatestFiniteMagnitude), options: .usesLineFragmentOrigin, attributes: [NSFontAttributeName: font], context: nil)
size = CGSize(width: frame.size.width, height: ceil(frame.size.height))
}
return size
}
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return self.items.count
}

func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {

let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "cell", for: indexPath as IndexPath) as! MyCollectionViewCell
cell.myLabel.text = self.items[indexPath.item]
cell.myLabel.backgroundColor = UIColor.yellow

return cell
}

func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
// handle tap events

print("You selected cell #\(indexPath.item)!")
}
}

Storyboard one label inside collectionviewcell. Use Autolayout.

label constrain.

Output :

Output

UICollectionView with ContentInset is not Scrolling all the Way Down

Today, by chance I discovered the solution!

Select your view controller and uncheck the option "Adjust Scroll View Insets".

Sample Image

With this option unchecked, iOS does not automatically adjust your insets of the view (and probably its subviews), which caused the problems for me ... Uncheck it and configure your scroll insets like this programmatically:

- (void)configureInsetsOfCollectionView
{
[_collectionView setContentInset: UIEdgeInsetsMake(self.navigationController.navigationBar.bounds.size.height + [UIApplication sharedApplication].statusBarFrame.size.height + DEFAULT_SPACING, 0.f, _keyboardHeight + _toolbar.bounds.size.height + DEFAULT_SPACING, 0.f)];
[_collectionView setScrollIndicatorInsets:UIEdgeInsetsMake(self.navigationController.navigationBar.bounds.size.height + [UIApplication sharedApplication].statusBarFrame.size.height, 0.f, _keyboardHeight + _toolbar.bounds.size.height, 0.f)];
}


Related Topics



Leave a reply



Submit