Esat kemal Ekren
Esat kemal Ekren

Reputation: 556

How to proper design UICollection View Cell in Swift

I created UICollection View without use Storyboard. I 'll share the my codes and the screenshots in the below. I want to help about the how can I properly arrange my UICollection View Cell with constraint and anchor. Thank you for the helping me for the solving my problem.

Here is my code in collectionview.swift;

class ProductViewController : UICollectionViewController, UICollectionViewDelegateFlowLayout {


var product : Product?
var productdetail : [ProductDetail]?
var categories : [NSDictionary] = [NSDictionary]()
var mainurl  = "http://www.example.com"
var idforurl = ""


override func viewDidLoad() {
    idforurl = (product?.id)!
    mainurl = ("\(mainurl)\(idforurl)")
    print(mainurl)
    //self.mainurl += (product?.id)!

    fetchproductDetail()

    collectionView?.backgroundColor = .white
    navigationItem.title = self.product?.name
    self.navigationItem.leftBarButtonItem = UIBarButtonItem(title: "Close", style: .plain, target: self, action: #selector (handleCloseBook))

    collectionView?.register(ProductDetailCell.self, forCellWithReuseIdentifier: "cellId")
    let layout =  collectionView?.collectionViewLayout as? UICollectionViewFlowLayout
    //layout?.scrollDirection = .vertical
    layout?.minimumLineSpacing = 40
    collectionView?.isPagingEnabled = false





}

func handleCloseBook() {

    dismiss(animated: true, completion: nil)
}

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

    return CGSize(width: view.frame.width / 4, height: view.frame.height / 5)

}

override func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {


    let selectedproduct = self.productdetail?[indexPath.row]
    let productVC = DetailViewController()
    productVC.detailproduct = selectedproduct
    let navController = UINavigationController(rootViewController: productVC)
    present(navController, animated: true, completion: nil)



}


override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
    let pagecell = collectionView.dequeueReusableCell(withReuseIdentifier: "cellId", for: indexPath) as! ProductDetailCell

    let products1 = productdetail?[indexPath.item]
    pagecell.product = products1
    return pagecell

}

override func numberOfSections(in collectionView: UICollectionView) -> Int {

    return 1

}

override func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {

    return productdetail?.count ?? 0
}

func fetchproductDetail () {

    if let url = URL(string: mainurl) {
        URLSession.shared.dataTask(with: url, completionHandler: { (data, response, error) in

            if let err = error {

                print("fetch error",err)

            }

            guard let data = data else{return}

            do {
                self.productdetail = []

                let json = try JSONSerialization.jsonObject(with: data, options: JSONSerialization.ReadingOptions.mutableContainers) as! [String:AnyObject]

                if let tempData = json["data"] as? [NSDictionary] {
                    for category in tempData {
                        if let tempResult = category["Menu"] as? NSDictionary {
                            self.categories.append(tempResult)
                        }
                    }
                }

                for category in self.categories {

                    let product =  ProductDetail(dictionary: category as! [String : Any])
                    self.productdetail?.append(product)
                    print(product.productname)
                    print(product.productdesc)

                }

                DispatchQueue.main.async {
                    self.collectionView?.reloadData()
                }

            }

            catch let JsonErr {

                print("Failed to Parse json properly", JsonErr)
            }


        }).resume()
    }

}





}

and here is the collection view cell file;

class ProductDetailCell : UICollectionViewCell {
        var product : ProductDetail? {
            didSet{
                textLbl.text =  product?.productname
                priceLbl.text = product?.productprice

                guard let productImages = product?.productimage else {return}
                let baseUrl = "http://www.example.com"
                guard let url = URL(string: baseUrl) else {return}
                productImage.image = nil

                URLSession.shared.dataTask(with: url) { (data, response, error) in

                    if let err = error {

                        print("Error has been occurred", err)

                    }

                    guard let imagedata = data else{return}
                    let image = UIImage(data: imagedata)

                    DispatchQueue.main.async {

                        self.productImage.image = image
                    }

                    }.resume()

            }
            }

    let textLbl: UILabel = {

        let label = UILabel()
        label.text = "Veri Yok!"
        label.numberOfLines = 0
        label.translatesAutoresizingMaskIntoConstraints = false
        label.font = UIFont(name: "Avenir-Light", size: 12)
        label.textAlignment = .center
        label.lineBreakMode = .byWordWrapping
        label.numberOfLines = 1
        label.minimumScaleFactor = 0.1
        label.adjustsFontSizeToFitWidth = true

        return label
    }()

    let priceLbl: UILabel = {

        let label = UILabel()
        label.text = "Veri Yok!"
        label.numberOfLines = 0
        label.translatesAutoresizingMaskIntoConstraints = false
        label.font = UIFont(name: "Avenir-Light", size: 12)
        label.textAlignment = .center
        label.lineBreakMode = .byWordWrapping
        label.numberOfLines = 1
        label.adjustsFontSizeToFitWidth = true

        return label
    }()

    let productImage : UIImageView = {

        let imageView = UIImageView()
        imageView.translatesAutoresizingMaskIntoConstraints = false
        imageView.contentMode = .scaleAspectFit
        imageView.clipsToBounds = false
        imageView.image = #imageLiteral(resourceName: "amazon_icon")
        return imageView

    }()


    override init(frame: CGRect) {
        super.init(frame: frame)

        addSubview(productImage)
        productImage.topAnchor.constraint(equalTo: topAnchor, constant: 5).isActive = true
        productImage.leftAnchor.constraint(equalTo: self.leftAnchor, constant: 5).isActive = true
        productImage.bottomAnchor.constraint(equalTo: bottomAnchor, constant: -10).isActive = true
        productImage.rightAnchor.constraint(equalTo: self.rightAnchor, constant: -5).isActive = true
        productImage.widthAnchor.constraint(equalToConstant: frame.size.width / 5).isActive = true



        addSubview(textLbl)
        textLbl.topAnchor.constraint(equalTo: productImage.bottomAnchor, constant: 2).isActive = true
       // textLbl.leftAnchor.constraint(equalTo: self.leftAnchor, constant: -5).isActive = true
        //textLbl.rightAnchor.constraint(equalTo: self.rightAnchor, constant: 5).isActive = true
       // textLbl.bottomAnchor.constraint(equalTo: self.bottomAnchor).isActive = true
        textLbl.heightAnchor.constraint(equalToConstant: 30).isActive = true
        textLbl.centerXAnchor.constraint(equalTo: self.centerXAnchor).isActive = true


        addSubview(priceLbl)
        priceLbl.topAnchor.constraint(equalTo: textLbl.bottomAnchor, constant: 2).isActive = true
        // textLbl.leftAnchor.constraint(equalTo: self.leftAnchor, constant: -5).isActive = true
        //textLbl.rightAnchor.constraint(equalTo: self.rightAnchor, constant: 5).isActive = true
        //textLbl.heightAnchor.constraint(equalToConstant: 40).isActive = true
        priceLbl.centerXAnchor.constraint(equalTo: self.centerXAnchor).isActive = true

    }

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


     }

}

and lastly I got result on simulator in the below

Simulator Screenshot

As you can see my collection view cell not properly set I want them in perfect square and the space for the middle of the cell should be reduced too. Thanks for help again.

Upvotes: 0

Views: 834

Answers (1)

Kashif
Kashif

Reputation: 4632

Since you have used storyboard, first thing you would want to do is to use a 1:1 ratio constraint on the cell. This will ensure that the cell is always perfectly square.

Secondly, to reduce the padding between cells, you can do something like this in view did load:

let columns:CGFloat = 3
let sW = self.view.frame.width
let padding = sW / 32      // 32 points being the padding space between cells
cellWidth = (sW - (padding*(columns+1))) / columns

Upvotes: 1

Related Questions