Autolayout strange behaviour on Ipad - swift

collection view getting right size with auto layout but view size on collection view is not working properly view on collection view taking size from storyboard design. its depend what you setting size in storyboard design. its working perfectly in Iphone but not working in Ipad. i tried to setting size in size for item at section but its not working.
dropbox link of project is here.
let isPad = UIDevice.current.userInterfaceIdiom == .pad
import UIKit
class AchivementVC: UIViewController {
#IBOutlet weak var clcAchivement:UICollectionView!
override func viewDidLoad() {
super.viewDidLoad()
}
#IBAction func btnBackClick(sender:UIButton)
{
self.navigationController?.popViewController(animated: true)
}
}
extension AchivementVC:UICollectionViewDelegate,UICollectionViewDataSource,UICollectionViewDelegateFlowLayout
{
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return 10
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "achiveCell", for: indexPath) as! AchiveClcCell
return cell
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
print(collectionView.frame)
if(isPad)
{
return CGSize(width: (collectionView.frame.size.width * 0.5)-30, height: (collectionView.frame.size.width * 0.45)-30)
}
else
{
return CGSize(width: (collectionView.frame.size.width * 0.5)-10, height: (collectionView.frame.size.width * 0.45)-10)
}
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumLineSpacingForSectionAt section: Int) -> CGFloat {
if(isPad)
{
return 30
}
else
{
return 10
}
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumInteritemSpacingForSectionAt section: Int) -> CGFloat {
if(isPad)
{
return 30
}
else
{
return 10
}
}
}
class AchiveClcCell:UICollectionViewCell
{
override func awakeFromNib() {
self.setNeedsLayout()
}
override func layoutSubviews() {
}
}

You should call super.layoutSubviews() when you override layoutSubviews

Related

Cant display image in UICollectionView cell

I need to display images in collection view cells but when I'm trying to do that I'm getting 10 empty cells and I don't know where im making mistakes
Here is my code of ViewController
class NewGalleryViewController: UIViewController {
var presenter: ViewToPresenterPhotoProtocol?
var builder: GalleryRequestBuilder?
#IBOutlet var collectionView: UICollectionView!
let reuseIdentifier = "customCVCell"
#objc func refresh() {
presenter?.refresh()
}
override func viewDidLoad() {
super.viewDidLoad()
self.setupPresenterIfNeed()
presenter?.viewDidLoad()
// Do any additional setup after loading the view.
}
func setupPresenterIfNeed() {
self.collectionView.backgroundColor = UIColor.white
if self.presenter == nil {
let presenter = GalleryPresenter()
presenter.view = self
self.presenter = presenter
self.builder = GalleryRequestBuilder()
}
}
}
extension NewGalleryViewController: UICollectionViewDelegate, UICollectionViewDataSource, UICollectionViewDelegateFlowLayout {
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return self.presenter?.photos.count ?? 0
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: reuseIdentifier, for: indexPath) as! PhotoCollectionViewCell
KFImage.url(builder?.createImageUrl(name: (presenter?.photos[indexPath.item].name)!))
.onSuccess { result in
cell.imageView.image = result.image
}
return cell
}
func collectionView(_ collectionView: UICollectionView,
layout collectionViewLayout: UICollectionViewLayout,
sizeForItemAt indexPath: IndexPath) -> CGSize {
return CGSize(width: 180, height: 128)
}
func collectionView(_ collectionView: UICollectionView,
layout collectionViewLayout: UICollectionViewLayout,
minimumInteritemSpacingForSectionAt section: Int) -> CGFloat {
return 1.0
}
func collectionView(_ collectionView: UICollectionView, layout
collectionViewLayout: UICollectionViewLayout,
minimumLineSpacingForSectionAt section: Int) -> CGFloat {
return 20.0
}
// MARK: - UICollectionViewDelegate protocol
private func collectionView(collectionView: UICollectionView, didSelectItemAtIndexPath indexPath: NSIndexPath) {
// handle tap events
print("You selected cell #\(indexPath.item)!")
}
}
extension NewGalleryViewController: PresenterToViewPhotoProtocol{
func onFetchPhotoSuccess() {
self.collectionView.reloadData()
self.collectionView!.collectionViewLayout.invalidateLayout()
self.collectionView!.layoutSubviews()
self.collectionView.refreshControl?.endRefreshing()
}
func onFetchPhotoFailure(error: String) {
print("View receives the response from Presenter with error: \(error)")
self.collectionView.refreshControl?.endRefreshing()
}
}
And Here is the code of cell
class PhotoCollectionViewCell: UICollectionViewCell {
#IBOutlet weak var imageView: UIImageView!
override func awakeFromNib() {
super.awakeFromNib()
// Initialization code
}
}
I've checked the link I'm making request to and it works. So problem is not in link. Maybe I should reload items after getting images?
You should set your UICollectionView delegate and data source once the view is loaded:
override func viewDidLoad() {
super.viewDidLoad()
// Add this lines
collectionView.delegate = self
collectionView.dataSource = self
self.setupPresenterIfNeed()
presenter?.viewDidLoad()
}

Why is my uiCollection view cell not changing based on different screen size? I'm using storyboards and Swift

just as to make it clear all other similar questions are asking for objective C or either not in storyboard hence my question is valid..
So I want to do is create a full screen image slider. Im using collection view to do it. but the outcome is not as expected especially the scrolling and the way the cell is displayed.
here is my code for collection view:
import UIKit
import Firebase
import FirebaseDatabase
import SDWebImage
class DoceFullImageVIew: UIViewController {
#IBOutlet weak var colltionView: UICollectionView!
var images = [ChudoInsta]()
// var imgArr = [ChudoInsta]()
var dbRef: DatabaseReference!
let viewImageSegueIdentifier = "doceImageSegueIdentifier"
override func viewDidLoad() {
super.viewDidLoad()
dbRef = Database.database().reference().child("wedding/doce_pics")
loadDB()
}
func loadDB(){
dbRef.observe(DataEventType.value, with: { (snapshot) in
var newImages = [ChudoInsta]()
for chudoInstaSnapshot in snapshot.children {
let chudoInstaObject = ChudoInsta(snapshot: chudoInstaSnapshot as! DataSnapshot)
newImages.append(chudoInstaObject)
}
self.images = newImages
self.colltionView.reloadData()
})
}
func printvalue() {
print("This is the doce full image firebase \(images)")
// print("This is the doce full image firebase \(images)")
}
}
extension DoceFullImageVIew: UICollectionViewDelegate, UICollectionViewDataSource {
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return images.count
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "cell", for: indexPath) as? DataCollectionViewCell
let image = images[indexPath.row]
cell?.img.sd_setImage(with: URL(string: image.imageUrl), placeholderImage: UIImage(named: "image1"))
return cell!
}
}
extension DoceFullImageVIew: UICollectionViewDelegateFlowLayout {
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
let size = UIScreen.main.bounds
return CGSize(width: size.width, height: size.height)
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, insetForSectionAt section: Int) -> UIEdgeInsets {
return UIEdgeInsets(top: 0, left: 0, bottom: 0, right: 0)
//return UIEdgeInsets(0, 5, 0, 5);
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumInteritemSpacingForSectionAt section: Int) -> CGFloat {
return 0
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumLineSpacingForSectionAt section: Int) -> CGFloat {
return 0
}
}
Can some one point out what is wrong and why the output comes like this images chopped :
https://drive.google.com/file/d/1JzbX-B0dhuInJ_ydwFWyuYTNq6d_lZS_/view?usp=sharing
https://drive.google.com/file/d/1KdPKkcvdAR4lMEY-0nwthsFlS2OxC_Te/view?usp=sharing
and in landscape the images are chopped as well:
https://drive.google.com/file/d/1RgqUCtUL_L2Xystg1eDDm7ZMBBhqaZvj/view?usp=sharing
here are some of my story board screenshots:
https://drive.google.com/file/d/1NMzvSHfEHWil_HsMtELmU4kd2Awe4nXt/view?usp=sharing
https://drive.google.com/file/d/1Q6DiBWWXGCzZ6bVKn9dkprMeluXuuonW/view?usp=sharing
https://drive.google.com/file/d/1-CB_XtGSI_rXpqbckytGgNrdaH1upaUy/view?usp=sharing
https://drive.google.com/file/d/1r4gAV2p_VS4Ix5ht_HPQVe7Rs8LeKtpX/view?usp=sharing
my flow delegate:
https://drive.google.com/file/d/1BjIBwvTVe0Ew_MAKBpeorkowQlDdD3eT/view?usp=sharing
Im trying to achieve a fullscreen image slider with collection view(images are retrieved from firebase)

CollectionView don't update visible cell

Good afternoon!
Faced with this problem, there is a collection in which cells in the whole screen
the cell is configured with data,
and there are events inside the cell that make the collection reload,
it is not possible to make a check, if the cell is now visible, it is not necessary to update it completely, but only part of the data, I do not yet understand how to do it, can someone be able to prompt?!))
Test project))
import UIKit
class ViewController: UIViewController, UICollectionViewDataSource, UICollectionViewDelegateFlowLayout {
#IBOutlet weak var collectionViwe: UICollectionView!
let dataSource = [1,2,3,4,5,6,7,8,9]
override func viewDidLoad() {
super.viewDidLoad()
collectionViwe.isPagingEnabled = true
collectionViwe.register(Cell.self, forCellWithReuseIdentifier: "Cell")
// Do any additional setup after loading the view.
}
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return dataSource.count
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "Cell", for: indexPath) as! Cell
let text = String(dataSource[indexPath.row])
if cell.label.text != text {
cell.label.text = text
cell.label.backgroundColor = .random()
}
return cell
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
return view.frame.size
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, insetForSectionAt section: Int) -> UIEdgeInsets {
return .zero
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumLineSpacingForSectionAt section: Int) -> CGFloat {
return 0
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumInteritemSpacingForSectionAt section: Int) -> CGFloat {
return 0
}
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
collectionView.reloadData()
}
}
class Cell: UICollectionViewCell {
let label = UILabel()
override init(frame: CGRect) {
super.init(frame: frame)
label.backgroundColor = .red
addSubview(label)
label.frame = CGRect(x: 36, y: 36, width: 200, height: 100)
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}
extension CGFloat {
static func random() -> CGFloat {
return CGFloat(arc4random()) / CGFloat(UInt32.max)
}
}
extension UIColor {
static func random() -> UIColor {
return UIColor(red: .random(),
green: .random(),
blue: .random(),
alpha: 1.0)
}
}

How to trigger an function of an UICollectionViewCell inside an UICollectionViewController?

I would like to trigger the animation3() function (which is a function inside PageCell() which is a UICollectionViewCell) inside the BreathingSwpipingController which is a UICollectionViewController.
class BreathingSwipingController: UICollectionViewController, UICollectionViewDelegateFlowLayout {
var pageCell: PageCell?
override func viewDidLoad() {
super.viewDidLoad()
collectionView.backgroundColor = .white
collectionView.register(PageCell.self, forCellWithReuseIdentifier: "cellId")
collectionView.isPagingEnabled = true
setupStartStopButton()
}
override func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return 3
}
override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
pageCell = (collectionView.dequeueReusableCell(withReuseIdentifier: "cellId", for: indexPath) as? PageCell)!
return pageCell!
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
return CGSize(width: collectionView.frame.width, height: collectionView.frame.height)
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumLineSpacingForSectionAt section: Int) -> CGFloat {
return 0
}
#objc func startStopTapped() {
pageCell!.animation3()
}
}
Make PageCell a delegate of BreathingSwipingController by making a protocol
protocol BreathingSwipingDelegate: class {
func doSth()
}
now inside UICollectionViewController define a weak var delegate: BreathingSwipingDelegate?
then head to PageCell file and conform to that protocol
class PageCell: BreathingSwipingDelegate .... {
func doSth() {
animation3()
}
var mController = BreathingSwipingController()
override init(style: .....) {
mController.delegate = self
.
.
.
.
}
}
now in BreathingSwipingController make the following
#objc func startStopTapped() {
delegate?.doSth()
}

UICollectionViewLayout methods never get called

I am working with a UICollectionView and I am trying to use the UICollectionViewLayout methods to adjust the sizing of the cell however they are never being called. The methods are :
sizeForItemAtIndexPath, minimumInterimItemSpacingForSectionAtIndex, and minimumLineSpacingForSectionAtIndex
these 3 methods are never being called and I'm not sure where/ how to call them from. below is my code in Swift 3
import Foundation
import UIKit
class CollectionVC: UICollectionViewController {
var Sections = [SectionService]()
override func viewDidLoad() {
createServiceSections()
}
func createServiceSections(){
ServiceSections.append(ServiceSection(headerTitle: "1", items: 2, headerImage: UIImage(named: "Default"), stats: nil))
ServiceSections.append(ServiceSection(headerTitle: "2", items: 3, headerImage: UIImage(named: "Default"), stats: nil))
ServiceSections.append(ServiceSection(headerTitle: "3", items: 3, headerImage: UIImage(named: "Default"), stats: nil))
ServiceSections.append(ServiceSection(headerTitle: "4", items: 5, headerImage: UIImage(named: "Default"), stats: nil))
}
override func numberOfSections(in collectionView: UICollectionView) -> Int {
return ServiceSections.count
}
override func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return ServiceSections[indexPath.section].items.count
}
override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell1 = collectionView.dequeueReusableCell(withReuseIdentifier: "servicecell", for: indexPath) as! ServicesCellView
cell1.serviceLabel.text = "test"
cell1.serviceImage.image = ServiceSections[indexPath.section].headerImage
return cell1
}
func collectionView(collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAtIndexPath indexPath: NSIndexPath) -> CGSize {
print("size for item at indexPath")
var cellSize: CGSize
let collectionViewWidth = self.collectionView!.bounds.size.width
cellSize = CGSize(width: (collectionViewWidth * 0.48), height: (collectionViewWidth * 0.48))
return cellSize
}
func collectionView(collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumInterItemSpacingForSectionAtIndex section: Int) -> CGFloat {
print("min spacing section")
return 1
}
func collectionView(collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumLineSpacingForSectionAtIndex section: Int) -> CGFloat {
print("min line spacing section")
return 1
}
}
With help from Xinatanil, I was able to fix the issue. First, I had to change my class line to this
class CollectionVC: UICollectionViewController, UICollectionViewDelegateFlowLayout {
and then I had to change the methods declarations to Swift 3 syntax...
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
var cellSize: CGSize
let collectionViewWidth = self.collectionView!.bounds.size.width
cellSize = CGSize(width: (collectionViewWidth * 0.48), height: (collectionViewWidth * 0.48))
return cellSize
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumInteritemSpacingForSectionAt section: Int) -> CGFloat {
return 1
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumLineSpacingForSectionAt section: Int) -> CGFloat {
return 1
}
I think, you haven't set collectionView delegate
Please try:
self.collectionView.delegate = self in viewDidLoad() method
Actually UICollectionViewDelegateFlowLayout inherits from UICollectionViewDelegate. So setting the delegate will be sufficient.
Happy Coding!