简体   繁体   中英

How to image setup in UICollectionView in UICollectionViewCell Swift

I am trying to set up images in the horizontal alignment in collectionView, but it's not working properly. Please check the attached screenshot.

View Controller Code:-

import UIKit

class ViewController: UIViewController,UICollectionViewDataSource,UICollectionViewDelegate,UICollectionViewDelegateFlowLayout {

@IBOutlet weak var texting1: UICollectionView!

override func viewDidLoad() {
    super.viewDidLoad()
    
    self.texting1.register(UINib(nibName:"CollectionViewCell1", bundle: nil), forCellWithReuseIdentifier: "CollectionViewCell1")
    self.texting1.delegate = self
    self.texting1.dataSource = self
    texting1.backgroundColor = .red
}

func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
    return 1
}

func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
    let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "CollectionViewCell1", for: indexPath) as! CollectionViewCell1
    return cell
}

func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
    return CGSize(width: self.view.frame.width, height: 120)
  }
}

Output:- Image

CollectionViewCell1 Code:-

import UIKit

class CollectionViewCell1: UICollectionViewCell,UICollectionViewDataSource, UICollectionViewDelegate,UICollectionViewDelegateFlowLayout {

@IBOutlet weak var userImageColectionView: UICollectionView!

override func awakeFromNib() {
    super.awakeFromNib()
    self.userImageColectionView.register(UINib(nibName:"CollectionViewCell2", bundle: nil), forCellWithReuseIdentifier: "CollectionViewCell2")
    userImageColectionView.delegate = self
    userImageColectionView.dataSource = self
    userImageColectionView.backgroundColor = .black
}
    
var items = ["1", "2", "3", "4"]

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: "CollectionViewCell2", for: indexPath as IndexPath) as! CollectionViewCell2
    return cell
}

// MARK: - UICollectionViewDelegate protocol
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
    print("You selected cell #\(indexPath.item)!")
}

func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
    return CGSize(width: 70, height: 60);
}

func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumLineSpacingForSectionAt section: Int) -> CGFloat {
    return -10
  }
}

Xib ScreenShot:- Image

CollectionViewCell2 Code:-

class CollectionViewCell2: UICollectionViewCell {

@IBOutlet weak var imguserView: UIImageView!
override func awakeFromNib() {
    super.awakeFromNib()
    imguserView.image = UIImage(systemName: "person.crop.circle")
   }
}

Xib ScreenShot:- Image

My Goal:- Image

Can someone please explain to me how to show images under in collection view in the horizontal alignment and setup dynamic width according to cell images count, I've tried to implement by above but no results yet.

Any help would be greatly appreciated.

Thanks in advance.

One way to do this without using a collection view is to create a "horizontal chain" of constraints for the "cell views."

For example, if we have 3 image views - red, green, and blue - with these constraints:

    NSLayoutConstraint.activate([
        red.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: 20.0),
        green.leadingAnchor.constraint(equalTo: red.trailingAnchor, constant: 10.0),
        blue.leadingAnchor.constraint(equalTo: green.trailingAnchor, constant: 10.0),
    ])

it will look like this:

在此处输入图像描述

If we instead use negative constants:

    NSLayoutConstraint.activate([
        red.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: 20.0),
        green.leadingAnchor.constraint(equalTo: red.trailingAnchor, constant: -20.0),
        blue.leadingAnchor.constraint(equalTo: green.trailingAnchor, constant: -20.0),
    ])
    

it can look like this:

在此处输入图像描述

So we can create a custom UIView subclass that handles all of that for us -- such as this:

class OverlapView: UIView {
    
    public var overlap: CGFloat = -30 { didSet { setNeedsLayout() } }
    
    public var cellViews: [UIView] = [] {
        didSet {
            // clear out any existing subviews
            subviews.forEach { v in
                v.removeFromSuperview()
            }
            cellViews.forEach { v in
                // in case it wasn't set by the caller
                v.translatesAutoresizingMaskIntoConstraints = false
                addSubview(v)
                // center it vertically
                v.centerYAnchor.constraint(equalTo: centerYAnchor).isActive = true
                // we want the overlap to go from left-to-right
                sendSubviewToBack(v)
            }
            setNeedsLayout()
        }
    }
    
    private var horizontalConstraints: [NSLayoutConstraint] = []
    
    override func layoutSubviews() {
        super.layoutSubviews()

        guard cellViews.count > 0 else { return }

        // de-activate any existing horizontal constraints
        NSLayoutConstraint.deactivate(horizontalConstraints)
        
        var prevView: UIView!
        cellViews.forEach { v in
            // if it's the first one
            if prevView == nil {
                horizontalConstraints.append(v.leadingAnchor.constraint(equalTo: leadingAnchor))
            } else {
                horizontalConstraints.append(v.leadingAnchor.constraint(equalTo: prevView.trailingAnchor, constant: overlap))
            }
            prevView = v
        }
        // constrain last view's trailing
        horizontalConstraints.append(prevView.trailingAnchor.constraint(equalTo: trailingAnchor))

        // activate the udpated constraints
        NSLayoutConstraint.activate(horizontalConstraints)
    }
}

Here's a sample controller demonstrating that:

class OverlapTestVC: UIViewController {
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        let testView = OverlapView()
        testView.translatesAutoresizingMaskIntoConstraints = false
        view.addSubview(testView)
        
        let g = view.safeAreaLayoutGuide
        NSLayoutConstraint.activate([
            testView.topAnchor.constraint(equalTo: g.topAnchor, constant: 40.0),
            testView.leadingAnchor.constraint(equalTo: g.leadingAnchor, constant: 16.0),
            testView.heightAnchor.constraint(equalToConstant: 70.0),
            
            // no trailing or width constraint
            //  width will be determined by the number of "cells"
        ])

        // let's add 6 "cells" -- one for each color
        let colors: [UIColor] = [
            .systemRed, .systemGreen, .systemBlue,
            .systemYellow, .systemCyan, .magenta,
        ]
        var cellViews: [UIView] = []
        colors.forEach { c in
            if let img = UIImage(systemName: "person.crop.circle") {
                let imgView = UIImageView(image: img)
                imgView.tintColor = c
                imgView.backgroundColor = .white
                imgView.translatesAutoresizingMaskIntoConstraints = false
                // let's use a 60x60 image view
                imgView.widthAnchor.constraint(equalToConstant: 60.0).isActive = true
                imgView.heightAnchor.constraint(equalTo: imgView.widthAnchor).isActive = true
                // we want "round" views
                imgView.layer.cornerRadius = 30.0
                imgView.layer.masksToBounds = true
                cellViews.append(imgView)
            }
        }

        testView.cellViews = cellViews
        
        // we can change the overlap value here if we don't want to use
        //  our custom view's default
        // for example:
        //testView.overlap = -40.0
        
        // so we can see the framing
        testView.backgroundColor = UIColor(white: 0.9, alpha: 1.0)

    }
    
}

Output looks like this:

在此处输入图像描述

(We gave the custom view itself a light gray background so we can see its frame.)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM