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:
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.
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".
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
iOS App Crashes on Phone But Works Fine on Simulator
Video with Gpuimagechromakeyfilter Has Tint When Played in Transparent Gpuimageview
What Is a Safe Way to Turn Streamed (Utf8) Data into a String
Coredata Conditionally Fetching on Nsdate Using Nspredicate (Swift)
How to Authorize Twitter with Swifter
How to Draw a Simple Rounded Rect in Swift (Rounded Corners)
Creating a Custom UI View Class to Use as a Map Annotation
How to Deal with Dynamic Sections and Rows in iOS Uitableview
Change Selected Row Label Color in Picker View Swift 1.2
Pure Swiftui Login, Signup, Register Flow, Is It Possible
Swift 3 - Passing Data Between a View Controller and After That to Another 2
Creating a Rtsp Client for Live Audio and Video Broadcasting in Objective C
iOS Uiimagepickercontroller: Any Way of Getting the Date of the Chosen Picture
Mirror Not Working in Swift When Iterating Through Children of an Objective-C Object
Checkbox Uitableview with Different Sections
Iad Interstitials Not Showing Consistently? and Not at All on the Simulator
Making the Map Zoom to User Location and Annotation (Swift 2)