在tableview单元格内创建动态collectionView

问题描述 投票:0回答:1

我正在尝试在tableviewcell内创建一个水平集合视图,并在其中创建一个动态尺寸的uiimageview,这将是强制视图。

我创建了一个UIView:

public class CardImage: UIView {

    private var imageView: UIImageView?
    private var titleLabel: UILabel?
    private var descriptionLabel: UILabel?
    private var subtitleLabel: UILabel?

    private var icon: UIImage?
    private var imageURL: String?

    private var screenPercentage: CGFloat = 1.0

    override public func layoutSubviews() {
        super.layoutSubviews()
        layer.cornerRadius = 4
    }

    public override func awakeFromNib() {
        super.awakeFromNib()
        setup()
        layoutSubviews()
    }

    public init() {
        super.init(frame: .zero)
        setup()
        layoutSubviews()
    }

    required init?(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)
        setup()
        layoutSubviews()
    }

    public func fill(dto: SomeDTO) {
        setupImage(icon: dto.image, imageUrl: dto.imageURL)
        descriptionLabel?.text = dto.description
        titleLabel?.text = dto.title
        subtitleLabel?.text = dto.subtitle
        screenPercentage = dto.screenPercentage
    }

        private func setup() {
            isUserInteractionEnabled = true

            translatesAutoresizingMaskIntoConstraints = false

            backgroundColor = .red

            titleLabel = UILabel()
            titleLabel?.textColor = .white
            titleLabel?.numberOfLines = 1
            addSubview(titleLabel!)

            descriptionLabel = UILabel()
            descriptionLabel?.textColor = .white
            descriptionLabel?.numberOfLines = 2
            addSubview(descriptionLabel!)

            subtitleLabel = UILabel()
            subtitleLabel?.textColor = .white
            subtitleLabel?.numberOfLines = 1
            addSubview(subtitleLabel!)

            imageView = UIImageView(frame: .zero)
            imageView?.backgroundColor = .red
            addSubview(imageView!)

            setupConstraints()
        }

        private func setupImage(icon: UIImage?, imageUrl: String?) {
            if let url = imageURL {
                return
            }

            guard let image = icon else {
                return
            }

            imageView?.image = image
            imageView?.contentMode = .scaleAspectFit

            setNeedsDisplay()
            setNeedsLayout()
        }


        private func setupConstraints() {
            imageView?.translatesAutoresizingMaskIntoConstraints = false
            imageView?.topAnchor.constraint(equalTo: topAnchor).isActive = true
            imageView?.leadingAnchor.constraint(equalTo: leadingAnchor).isActive = true
            imageView?.trailingAnchor.constraint(equalTo: trailingAnchor).isActive = true

            let screenSize = UIScreen.main.bounds
            let computedWidth = screenSize.width * screenPercentage
            imageView?.widthAnchor.constraint(equalToConstant: computedWidth).isActive = true
            //the image should be 16:9
            imageView?.heightAnchor.constraint(equalTo: widthAnchor, multiplier: 9.0/16.0).isActive = true

            titleLabel?.translatesAutoresizingMaskIntoConstraints = false
            titleLabel?.topAnchor.constraint(equalTo: imageView!.bottomAnchor, constant: 16).isActive = true
            titleLabel?.leadingAnchor.constraint(equalTo: leadingAnchor, constant: 16).isActive = true
            titleLabel?.heightAnchor.constraint(equalToConstant: 18).isActive = true

            subtitleLabel?.translatesAutoresizingMaskIntoConstraints = false
            subtitleLabel?.topAnchor.constraint(equalTo: titleLabel!.topAnchor).isActive = true
            subtitleLabel?.trailingAnchor.constraint(equalTo: trailingAnchor, constant: -16).isActive = true

            titleLabel?.widthAnchor.constraint(equalTo: subtitleLabel!.widthAnchor).isActive = true
            titleLabel?.trailingAnchor.constraint(equalTo: subtitleLabel!.leadingAnchor, constant: 6).isActive = true

            descriptionLabel?.translatesAutoresizingMaskIntoConstraints = false
            descriptionLabel?.topAnchor.constraint(equalTo: titleLabel!.bottomAnchor, constant: 16).isActive = true
            descriptionLabel?.leadingAnchor.constraint(equalTo: leadingAnchor, constant: 16).isActive = true
            descriptionLabel?.trailingAnchor.constraint(equalTo: trailingAnchor, constant: -16).isActive = true
            descriptionLabel?.bottomAnchor.constraint(equalTo: bottomAnchor, constant: -16).isActive = true
        }
}

将在CollectionViewCell中:

public class CardImageCollectionViewCell: UICollectionViewCell {
    private let view: CardImage = CardImage()

    override public func awakeFromNib() {
        super.awakeFromNib()

        translatesAutoresizingMaskIntoConstraints = false
//this only pin the view to the four anchors of the uicollectionview
        view.pinToBounds(of: self.contentView)
        backgroundColor = .clear

        AccessibilityManager.setup(self, log: true)
    }

    public func fill(dto: SomeDTO) {
        view.fill(dto: dto)
    }
}

然后在tableviewcell内的CollectionViewCell中,有一个collectionview:

public class CardImageCollectionView: UIView, UICollectionViewDataSource, UICollectionViewDelegate, UICollectionViewDelegateFlowLayout {

        @IBOutlet private weak var collectionView: UICollectionView!
        private var dto: [SomeDTO] = []

        public override func awakeFromNib() {
            super.awakeFromNib()
            setup()
        }

        private func setup() {
            backgroundColor = .blue

            collectionView.backgroundColor = .clear
            collectionView.delegate = self
            collectionView.dataSource = self

            if let flowLayout = collectionView?.collectionViewLayout as? UICollectionViewFlowLayout {
                flowLayout.estimatedItemSize = UICollectionViewFlowLayout.automaticSize
            }

            registerCells()
        }

        func fill(dto: [SomaImageCardDTO]) {
            self.dto = dto
            DispatchQueue.main.async {
                self.collectionView.reloadData()
                self.collectionView.layoutIfNeeded()
            }
        }

        private func registerCells() {
            collectionView.register(UINib(nibName: String(describing: CardImageCollectionViewCell.self), bundle: nil), forCellWithReuseIdentifier: String(describing: CardImageCollectionViewCell.self))
        }

        public func numberOfSections(in collectionView: UICollectionView) -> Int {
            return 1
        }

        public func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
            return dto.count
        }
        //this should not be setted since the sizing is automatic 
    //    public func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
    //        return CGSize(width: 304, height: 238)
    //    }
    //
        public func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {

            let cell = collectionView.dequeueReusableCell(withReuseIdentifier: String(describing: CardImageCollectionViewCell.self), for: indexPath) as! CardImageCollectionViewCell

            cell.fill(dto: dto[indexPath.row])
            return cell
        }
    }

我面临的两个问题是,图像不能假定任何大小,因为在填充了某些信息之前,集合视图没有任何大小。

然后,即使我设置了图像大小,也无法将信息传递给UITableViewcell大小。

ios swift uitableview uicollectionview uicollectionviewcell
1个回答
0
投票

如果我正确理解了您的问题,则UITableView中有多个行,其中有水平UICollectionViews。这些集合视图的单元格根据其内部图像具有动态大小。

因此,UITableView的宽度是固定的,但是行的高度取决于UICollectionView的高度,对吗?

我建议在UITableView中使用自动调整大小的单元格。请参阅此处的参考:https://developer.apple.com/library/archive/documentation/UserExperience/Conceptual/AutolayoutPG/WorkingwithSelf-SizingTableViewCells.html

之后,您需要找到一种方法来正确计算UICollectionView的高度,以便UITableView单元可以确定正确的高度。有几种方法可以做到这一点,例如,通过重写UICollectionView的intrinsicContentSize属性并返回图像的最大高度。

© www.soinside.com 2019 - 2024. All rights reserved.