Can you add a collection view in a UIView? - swift

I'm trying to add a collection view in a UIview to display users posts like Instagram has where you are able to swipe left and right on a users profile:
Can you add a collection view in the purple bit below (which is a UIView)?
So far this is what I have tried and I am not getting it to work and I'm not sure what else to try
import UIKit
private let reuseIdentifier = "Cell"
class CollectionView: UIView, UICollectionViewDataSource, UICollectionViewDelegate,
UICollectionViewDelegateFlowLayout {
//MARK: - Properties
let cellId = "cellId"
let collectionView: UICollectionView = {
let layout = UICollectionViewFlowLayout()
let view = UICollectionView(frame: .zero, collectionViewLayout: layout)
return view
}()
//MARK: - Init
override init(frame: CGRect) {
super.init(frame: frame)
addSubview(collectionView)
collectionView.anchor(top: topAnchor, left: leftAnchor, bottom: bottomAnchor, right: rightAnchor, paddingTop: 0, paddingLeft: 0, paddingBottom: 0, paddingRight: 0, width: 0, height: 0)
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
//MARK: - UICollectionView
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: reuseIdentifier, for: indexPath)
return cell
}
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection
section: Int) -> Int {
return 2
}
}

you need to set the delegate and data source for your collection view
try this
lazy var collectionView: UICollectionView = {
let layout = UICollectionViewFlowLayout()
let view = UICollectionView(frame: .zero, collectionViewLayout: layout)
view.dataSource = self
view.delegate = self
return view
}()

Related

Collectionview in NSObject Class doesn't work?

I wrote a class contain a collectionview to show in main viewcontroller,
but it was "never" shows the cell data. And the cell background color wasn't change to black..(change color is only for test, not my purpose)..
(The collectionView can be showed correctly)
Where I should to correct it?
class CellClass: NSObject,
UICollectionViewDataSource,
UICollectionViewDelegate,
UICollectionViewDelegateFlowLayout
{
let cellid = "cellid"
let cv : UICollectionView = {
let fl = UICollectionViewFlowLayout()
let v = UICollectionView(frame: .zero,
collectionViewLayout: fl)
v.translatesAutoresizingMaskIntoConstraints = false
v.backgroundColor = UIColor.white
return v
}()
override init() {
super.init()
print("init")
cv.delegate = self
cv.dataSource = self
cv.register(Cell.self,
forCellWithReuseIdentifier: cellid)
if let window = UIApplication.shared.keyWindow {
window.addSubview(cv)
cv.frame = CGRect(x: 0,
y: window.frame.height - 300,
width: window.frame.width,
height: 300)
}
}
func collectionView(_ collectionView: UICollectionView,
numberOfItemsInSection section: Int) -> Int {
print("numberOfItemsInSection")
return 3
}
func collectionView(_ collectionView: UICollectionView,
cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
print("cell")
let vc = collectionView.dequeueReusableCell(withReuseIdentifier: cellid,
for: indexPath) as! Cell
vc.lbl.text = "test"
vc.backgroundColor = UIColor.black
return vc
}
func collectionView(_ collectionView: UICollectionView,
layout collectionViewLayout: UICollectionViewLayout,
sizeForItemAt indexPath: IndexPath) -> CGSize {
return CGSize(width: 300, height: 100)
}
}
class Cell: UICollectionViewCell {
let lbl : UILabel = {
let t = UILabel()
t.translatesAutoresizingMaskIntoConstraints = false
return t
} ()
override init(frame: CGRect) {
super.init(frame: frame)
lbl.frame = CGRect(x: 0,
y: 0,
width: 200,
height: 30)
addSubview(lbl)
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}
I could be wrong but I have a feeling you do something like this in your viewDidLoad
let cellClass = CellClass()
As soon as the didLoad function completes its execution, cellClass no longer persists in order to be the datasource and delegate.
You can try this by adding a deinit to your CellClass
deinit {
print("Cell Class Deinit")
}
And I believe it will be called
What I suggest instead is to persist the object beyond viewDidLoad
class AVPlayerScroll: UIViewController, UIGestureRecognizerDelegate
{
var cellClass: CellClass?
override func viewDidLoad()
{
super.viewDidLoad()
cellClass = CellClass()
}
I believe this should give you the results you are looking for
you can try couple of things here.
You can either try to set the constraints programmatically. Something like this.
NSLayoutConstraint.activate([
lbl.leadingAnchor.constraint(equalTo: self.leadingAnchor),
lbl.topAnchor.constraint(equalTo: self.topAnchor),
lbl.widthAnchor.constraint(equalToConstant: 200),
actionSheetView.heightAnchor.constraint(equalToConstant: 30)])
You can try to assign the frame to the UILabel (lbl) subview in layoutSubviews() method.

CollectionView is not showing inside a view in Swift

I have a view with a collection view inside it. I am adding this view to another view but the collection view is not showing. What am I doing wrong here?
I have a view which has a collection view
class GiftFilterView: UIView {
var giftImageIcon: [UIImage] = [#imageLiteral(resourceName: "Gift Mic Icon"), #imageLiteral(resourceName: "Gift Smile Icon"), #imageLiteral(resourceName: "Gift Gif Icon"), #imageLiteral(resourceName: "Gift Camera Icon"), #imageLiteral(resourceName: "Gift Gift Icon"), #imageLiteral(resourceName: "Gift Three Dot Icon")]
//MARK:- Properties
weak var delegate: sendMessageToChatScreenDelegate?
weak var giftIcondelegate: GiftIconCellActionDeleate?
lazy var collectionView: UICollectionView = {
let layout = UICollectionViewFlowLayout()
let cv = UICollectionView(frame: .zero, collectionViewLayout: layout)
cv.translatesAutoresizingMaskIntoConstraints = false
cv.backgroundColor = .white
cv.delegate = self
cv.dataSource = self
cv.isScrollEnabled = false
return cv
}()
lazy var customInputView: CustomInputAccesoryView = {
let customView = CustomInputAccesoryView()
customView.delegate = self
return customView
}()
//MARK:- Lifecycles
override init(frame: CGRect) {
super.init(frame: frame)
addSubview(customInputView)
customInputView.anchor(top: topAnchor, left: leftAnchor, right: rightAnchor, paddingTop: 5)
addSubview(collectionView)
collectionView.anchor(top: customInputView.bottomAnchor, left: leftAnchor, paddingTop: 10)
collectionView.setDimensions(width: self.frame.size.width, height: 30)
backgroundColor = .white
self.collectionView.register(GiftFilterCollectionViewCell.self, forCellWithReuseIdentifier: reuseIdentifier)
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}
//MARK:- UICollectionViewDataSource, UICollectionViewDelegate
extension GiftFilterView: UICollectionViewDataSource, UICollectionViewDelegate{
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return giftImageIcon.count
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
guard let cell = self.collectionView.dequeueReusableCell(withReuseIdentifier: reuseIdentifier, for: indexPath) as? GiftFilterCollectionViewCell else {
return UICollectionViewCell()
}
cell.imageIcon = giftImageIcon[indexPath.row]
return cell
}
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
giftIcondelegate?.changeKeyboardheight()
}
}
//MARK:- UICollectionViewDelegateFlowLayout
extension GiftFilterView: UICollectionViewDelegateFlowLayout{
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
return CGSize(width: frame.width / CGFloat(giftImageIcon.count), height: 40)
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumInteritemSpacingForSectionAt section: Int) -> CGFloat {
return 10
}
}
I am adding this view to another view
class GiftAccessoryCollectionView: UIView {
//MARK:- Properties
weak var delegate: sendMessageToChatScreenDelegate?
weak var giftIcondelegate: GiftIconCellActionDeleate?
private lazy var filterView: GiftFilterView = {
let giftView = GiftFilterView()
giftView.translatesAutoresizingMaskIntoConstraints = false
return giftView
}()
//MARK:- Lifecycles
override init(frame: CGRect) {
super.init(frame: frame)
addSubview(filterView)
filterView.anchor(top: topAnchor, left: leftAnchor, right: rightAnchor,height: 130)
addSubview(collectionView)
collectionView.anchor(top: filterView.bottomAnchor, left: leftAnchor, paddingTop: 10)
collectionView.setDimensions(width: self.frame.size.width, height: 260)
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}
But the collection view is not showing when I am adding the view to another view.
It looks like you need to activate your anchors either by using isActive property or for multiple views the following would be more useful:
NSLayoutConstraint.activate([
...
])

Adding a CollectionViewController as a subView

Using Swift 5.1.3, iOS13.3, XCode11.3,
I try to display a horizontal collectionView that is wider than the view's width.
By dragging, the collectionView cells shall scroll horizontally.
The problem now is the following: As soon as I click to drag, the collectionView content "disappears" (i.e. turns transparent). If you look carefully, you can see that the scrollbar is still there.
Why is does the collectionView content turns transparent as soon as I click into it ?
Here is a video illustrating the error behaviour:
Below you will find the corresponding code:
Here is the code:
Inside my Main-ViewController I add the collectionView:
override func viewDidLoad() {
super.viewDidLoad()
let cardsHorizontalController = CardsHorizontalController()
self.view.addSubview(cardsHorizontalController.view)
cardsHorizontalController.view.translatesAutoresizingMaskIntoConstraints = false
cardsHorizontalController.view.topAnchor.constraint(equalTo: self.view.topAnchor, constant: 100.0).isActive = true
cardsHorizontalController.view.heightAnchor.constraint(equalToConstant: 279).isActive = true
cardsHorizontalController.view.widthAnchor.constraint(equalToConstant: UIScreen.main.bounds.width).isActive = true
}
Here is the collectionView controller class:
class CardsHorizontalController: BaseListController, UICollectionViewDelegateFlowLayout {
let cellId = "cellId"
override func viewDidLoad() {
super.viewDidLoad()
collectionView.backgroundColor = .clear
collectionView.register(CardHeaderCell.self, forCellWithReuseIdentifier: cellId)
if let layout = collectionViewLayout as? UICollectionViewFlowLayout {
layout.scrollDirection = .horizontal
}
collectionView.contentInset = UIEdgeInsets(top: 100, left: 0, bottom: 0, right: 0)
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
return .init(width: view.frame.width - 48, height: view.frame.height)
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, insetForSectionAt section: Int) -> UIEdgeInsets {
return .init(top: 0, left: 16, bottom: 0, right: 0)
}
override func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return 3
}
override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: cellId, for: indexPath)
return cell
}
}
And its corresponding parent class:
class BaseListController: UICollectionViewController {
init() {
super.init(collectionViewLayout: UICollectionViewFlowLayout())
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}
And here the collectionView cell at play:
class CardHeaderCell: UICollectionViewCell {
let imageView = UIImageView(cornerRadius: 8)
override init(frame: CGRect) {
super.init(frame: frame)
imageView.backgroundColor = .red
let stackView = VerticalStackView(arrangedSubviews: [
// companyLabel,
// titleLabel,
imageView
], spacing: 12)
addSubview(stackView)
stackView.fillSuperview(padding: .init(top: 16, left: 0, bottom: 0, right: 0))
}
required init?(coder aDecoder: NSCoder) {
fatalError()
}
}
I finally found a solution:
The collectionView-Controller (i.e. CardsHorizontalController()) needs to be added as a ChildController!
Inside Main-ViewController's viewDidLoad()(in first paragraph of code above), please replace the following line...
self.view.addSubview(cardsHorizontalController.view)
with the following:
self.addChild(cardsHorizontalController)
self.view.addSubview(cardsHorizontalController.view)
self.didMove(toParent: cardsHorizontalController)
Having done so, everything works as expected !
You find a working project (stripped-down with only the CollectionView) in this GitHub repo: https://github.com/iKK001/HorizontalCollectionViewExample
And since I'm so happy - here a video of the working horizontal CollectionView:
Have you tried changing return .init(width: view.frame.width - 48, height: view.frame.height) inside sizeForItemAt to return .init(width: collectionView.frame.width - 48, height: collectionView.frame.height)?

uicollectionviewcells not showing [duplicate]

I have got this Swift code
`
let cellId="cellId"
class FeedController: UICollectionViewController{
override func viewDidLoad() {
super.viewDidLoad()
navigationItem.title = "Centill"
collectionView?.reloadData()
collectionView?.backgroundColor = UIColor(white: 0.95, alpha: 1)
collectionView?.register(FeedCell.self, forCellWithReuseIdentifier: cellId)
}
override func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return 3
}
override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell=collectionView.dequeueReusableCell(withReuseIdentifier: cellId, for: indexPath);
cell.backgroundColor = .yellow
return cell
}
}
class FeedCell: UICollectionViewCell {
override init(frame: CGRect){
super.init(frame: frame)
setupViews()
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
func setupViews(){
backgroundColor = .yellow
}
}
`
But unfortunately my cells are not showing.It only shows navigation bar and background color.what may be the problem with my code?
Try This code:
let layout: UICollectionViewFlowLayout = UICollectionViewFlowLayout()
layout.sectionInset = UIEdgeInsets(top: 20, left: 10, bottom: 10, right: 10)
layout.itemSize = CGSize(width: 60, height: 60)
let myCollectionView:UICollectionView = UICollectionView(frame: self.view.frame, collectionViewLayout: layout)
myCollectionView.dataSource = self
myCollectionView.delegate = self
myCollectionView.registerClass(UICollectionViewCell.self, forCellWithReuseIdentifier: "MyCell")
myCollectionView.backgroundColor = UIColor.whiteColor()
self.view.addSubview(myCollectionView)
You have to provide the size for collection view cell. add the below code snippet
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
// calculate and return the height
}
In your cellForItemAt dataSource method you need to give custom UICollectionCell Class
let cell=collectionView.dequeueReusableCell(withReuseIdentifier: cellId, for: indexPath) as! FeedCell
cell.backgroundColor = .yellow
return cell
Then you will able to see cell.
Try it.
You add in the class
UICollectionViewDataSource and UICollectionVIewDelegate.

Swift collectionViewCells are not showing

I have got this Swift code
`
let cellId="cellId"
class FeedController: UICollectionViewController{
override func viewDidLoad() {
super.viewDidLoad()
navigationItem.title = "Centill"
collectionView?.reloadData()
collectionView?.backgroundColor = UIColor(white: 0.95, alpha: 1)
collectionView?.register(FeedCell.self, forCellWithReuseIdentifier: cellId)
}
override func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return 3
}
override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell=collectionView.dequeueReusableCell(withReuseIdentifier: cellId, for: indexPath);
cell.backgroundColor = .yellow
return cell
}
}
class FeedCell: UICollectionViewCell {
override init(frame: CGRect){
super.init(frame: frame)
setupViews()
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
func setupViews(){
backgroundColor = .yellow
}
}
`
But unfortunately my cells are not showing.It only shows navigation bar and background color.what may be the problem with my code?
Try This code:
let layout: UICollectionViewFlowLayout = UICollectionViewFlowLayout()
layout.sectionInset = UIEdgeInsets(top: 20, left: 10, bottom: 10, right: 10)
layout.itemSize = CGSize(width: 60, height: 60)
let myCollectionView:UICollectionView = UICollectionView(frame: self.view.frame, collectionViewLayout: layout)
myCollectionView.dataSource = self
myCollectionView.delegate = self
myCollectionView.registerClass(UICollectionViewCell.self, forCellWithReuseIdentifier: "MyCell")
myCollectionView.backgroundColor = UIColor.whiteColor()
self.view.addSubview(myCollectionView)
You have to provide the size for collection view cell. add the below code snippet
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
// calculate and return the height
}
In your cellForItemAt dataSource method you need to give custom UICollectionCell Class
let cell=collectionView.dequeueReusableCell(withReuseIdentifier: cellId, for: indexPath) as! FeedCell
cell.backgroundColor = .yellow
return cell
Then you will able to see cell.
Try it.
You add in the class
UICollectionViewDataSource and UICollectionVIewDelegate.