自调整大小动态UICollectionViewCell Height在调用reloadData()后不正确地调整自身大小 [英] Self sizing dynamic UICollectionViewCell height improperly sizes itself after calling reloadData()

查看:20
本文介绍了自调整大小动态UICollectionViewCell Height在调用reloadData()后不正确地调整自身大小的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个UICollectionView,它可以自动调整单元格的高度,因此它会根据单元格中的文本大小适当地调整高度。

我可以很好地单击所有按钮、向上或向下滚动等,但问题是,当我调用reloadData()时,由于某种原因,集合ViewCell的约束被搞砸了,它们堆叠在一起。

这里是调用reloadData()之前的集合视图的图片:

这里是我调用reloadData()后的集合VIew的图片:

有人可能知道为什么会发生这种情况以及我如何修复它吗?

以下是我的CustomCollectionView代码:

class CustomCollectionView: UICollectionView {
    
public let bottomRefresh = CollectionViewBottomRefresh()

init() {
    let layout = UICollectionViewFlowLayout()
    layout.minimumLineSpacing = 0
    layout.minimumInteritemSpacing = 0
    layout.scrollDirection = .vertical
    layout.estimatedItemSize = CGSize(width: UIScreen.main.bounds.width, height: 50)
    super.init(frame: .zero, collectionViewLayout: layout)
    alwaysBounceVertical = true
    backgroundColor = .systemBackground
    delaysContentTouches = false
    showsVerticalScrollIndicator = false
    register(PostView.self, forCellWithReuseIdentifier: "post")
}

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

override func touchesShouldCancel(in view: UIView) -> Bool {
    if view is UIButton || view is UITextField {
        return true
    }
    return super.touchesShouldCancel(in: view)
}

}

以下是我的CollectionViewCell代码:

class PostView: UICollectionViewCell, {

override init(frame: CGRect) {
    super.init(frame: frame)
    contentView.addSubview(commentsButton)
    contentView.addSubview(kuduAppTeamDeleteButton)
    contentView.addSubview(titleLabel)
    contentView.addSubview(infoButton)
    contentView.addSubview(imageViewButton)
    contentView.addSubview(likeButton)
    contentView.addSubview(followButton)
    contentView.addSubview(profile)
    contentView.addSubview(likeCount)
    contentView.addSubview(date)
    contentView.addSubview(line)
    addConstraints()
}

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

public func setupView(post: Post) {
    guard let post = fb.posts.firstIndex(where: { p in p.id == post.id }) else { return }
    self.post = post
    guard let user = fb.users.firstIndex(where: { user in user.id == fb.posts[post].uid }) else { return }
    self.user = user
    
    if fb.currentUser.likes.contains(fb.posts[post].id) {
        self.likeButton.setImage(UIImage(systemName: "hand.thumbsup.fill"), for: .normal)
        self.likeButton.tintColor = UIColor.theme.blueColor
    } else {
        self.likeButton.setImage(UIImage(systemName: "hand.thumbsup"), for: .normal)
        self.likeButton.tintColor = .label
    }
    let result = String(format: "%ld %@", locale: Locale.current, fb.posts[post].likeCount, "")
    likeCount.text = result
    
    
    //Button Actions
    infoButton.addAction(infoButtonAction, for: .touchUpInside)
    likeButton.addAction(likeButtonAction, for: .touchUpInside)
    followButton.addAction(followButtonAction, for: .touchUpInside)
    imageViewButton.addAction(imageViewButtonAction, for: .touchUpInside)
    profile.addAction(profileAction, for: .touchUpInside)
    commentsButton.addAction(commentsButtonAction, for: .touchUpInside)
    kuduAppTeamDeleteButton.addAction(kuduAppTeamDeleteButtonAction, for: .touchUpInside)
    
    //Date
    let dateFormatter = DateFormatter()
    dateFormatter.timeStyle = .none
    dateFormatter.dateStyle = .long
    let dateString = dateFormatter.string(from: fb.posts[post].date)
    date.text = dateString
    
    //Set follow button text
    if self.fb.currentUser.following.contains(fb.users[user].id) {
        self.followButton.label.text = "Unfollow"
    } else {
        self.followButton.label.text = "Follow"
    }
    
    //Set imageview image
    imageViewButton.setImage(fb.posts[post].image, for: .normal)
    
    imageViewButton.imageView!.contentMode = .scaleAspectFill
    
    //Set user image
    profile.usernameLabel.text = fb.users[user].username
    profile.profileImage.image = fb.users[user].profileImage
    if profile.profileImage.image == UIImage(systemName: "person.circle.fill") {
        profile.profileImage.tintColor = UIColor.theme.accentColor
    }
    
    //Set post title
    titleLabel.text = fb.posts[post].title
}

override func prepareForReuse() {
    //Remove all actions
    infoButton.removeAction(infoButtonAction, for: .touchUpInside)
    likeButton.removeAction(likeButtonAction, for: .touchUpInside)
    imageViewButton.removeAction(imageViewButtonAction, for: .touchUpInside)
    profile.removeAction(profileAction, for: .touchUpInside)
    commentsButton.removeAction(commentsButtonAction, for: .touchUpInside)
    followButton.removeAction(followButtonAction, for: .touchUpInside)
    kuduAppTeamDeleteButton.removeAction(kuduAppTeamDeleteButtonAction, for: .touchUpInside)
    
    //Remove any other text or images
    for subview in imageViewButton.subviews {
        if let subview = subview as? UIImageView, subview.image == UIImage(systemName: "play.circle.fill") {
            subview.removeFromSuperview()
        }
    }
    imageViewButton.setImage(nil, for: .normal)
    kuduAppTeamDeleteButton.color = nil
    profile.profileImage.image = nil
    titleLabel.text = nil
    date.text = nil
    self.followButton.label.text = nil
}

// Sets a requried width and a dynamic height that changes depending on what is in the cell. So we can have searchbar as first cell heigh 50, and post in other cells with height of view.bounds.width.
override func preferredLayoutAttributesFitting(_ layoutAttributes: UICollectionViewLayoutAttributes) -> UICollectionViewLayoutAttributes {
    let targetSize = CGSize(width: layoutAttributes.frame.width, height: 0)
    layoutAttributes.frame.size = contentView.systemLayoutSizeFitting(targetSize, withHorizontalFittingPriority: .required, verticalFittingPriority: .fittingSizeLevel)
    return layoutAttributes
}

private func addConstraints() {
    kuduAppTeamDeleteButton.height(30)
    kuduAppTeamDeleteButton.width(UIScreen.main.bounds.width / 4)
    kuduAppTeamDeleteButton.bottom(to: commentsButton)
    kuduAppTeamDeleteButton.leftToRight(of: commentsButton, offset: 5)
    
    imageViewButton.width(UIScreen.main.bounds.width)
    imageViewButton.height(UIScreen.main.bounds.width * 9/16)
    imageViewButton.topToSuperview()
    
    infoButton.leftToRight(of: titleLabel, offset: 6)
    infoButton.topToBottom(of: imageViewButton, offset: 15)
    infoButton.width(30)
    infoButton.height(30)
    
    titleLabel.horizontalToSuperview(insets: UIEdgeInsets(top: 0, left: 10, bottom: 0, right: 40))
    titleLabel.topToBottom(of: imageViewButton, offset: 5)
    titleLabel.height(min: 50)
    
    likeButton.topToBottom(of: titleLabel, offset: 10)
    likeButton.trailingToSuperview(offset: 10)
    likeButton.height(32)
    likeButton.width(32)
    
    profile.leadingToSuperview(offset: 5)
    profile.topToBottom(of: titleLabel, offset: 10)
    profile.widthToSuperview(multiplier: 0.4)
    
    likeCount.trailingToLeading(of: likeButton, offset: -5)
    likeCount.topToBottom(of: titleLabel, offset: 15)
    
    followButton.topToBottom(of: titleLabel, offset: 5)
    followButton.trailingToLeading(of: likeCount, offset: -10)
    followButton.height(50)
    followButton.width(UIScreen.main.bounds.width / 4)
    
    date.bottom(to: commentsButton, offset: -5)
    date.trailingToSuperview(offset: 5)
    
    commentsButton.topToBottom(of: profile, offset: 10)
    commentsButton.leadingToSuperview(offset: 5)
    
    line.horizontalToSuperview()
    line.bottom(to: commentsButton)
    line.height(1)
    
    contentView.bottom(to: line)
    contentView.widthToSuperview()
}

}

提前谢谢!

推荐答案

终于想好了,如果其他人遇到此问题,您可以如何修复此问题。

所以我决定使用UITableView而不是UICollectionView。当您更改为UITableView时,您可以访问变量UITableView.automaticDimension

附注:如果您有一列,则只能使用UITableView。

我对我的UITableView执行了以下操作:

class MyTableView: UITableView {

public let bottomRefresh = TableViewBottomRefresh()

init() {
    super.init(frame: .zero, style: .plain)
    rowHeight = UITableView.automaticDimension
    estimatedRowHeight = 500
    separatorStyle = .none
    allowsSelection = false
    delaysContentTouches = false
    alwaysBounceVertical = true
    showsVerticalScrollIndicator = false
    register(MyTableViewCell.self, forCellReuseIdentifier: "MyCell")
}

}

然后您需要创建一个tainerView,稍后可以将所有单元格内容放入其中:

    private let containerView: UIView = {
   let view = UIView()
    view.translatesAutoresizingMaskIntoConstraints = false
    return view
}()

添加contentView.addsubview(containerView)并将所有单元格内容放入容器视图中,以便单元格可以自动调整自身大小:

    override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
    super.init(style: style, reuseIdentifier: reuseIdentifier)
    contentView.addSubview(containerView)
    containerView.addSubview(profileImage)
    containerView.addSubview(username)
    containerView.addSubview(editProfileButton)
    addConstraints()
}

addconstraints()函数:

    private func addConstraints() {
    profileImage.topToSuperview()
    profileImage.centerXToSuperview()
    profileImage.widthToSuperview(multiplier: 1/2)
    profileImage.height(UIScreen.main.bounds.width / 2)
    
    username.topToBottom(of: profileImage, offset: 10)
    username.horizontalToSuperview()
    username.height(50)
    
    editProfileButton.height(50)
    editProfileButton.widthToSuperview(multiplier: 1/3)
    editProfileButton.centerXToSuperview()
    editProfileButton.topToBottom(of: username, offset: 10)
    
    containerView.widthToSuperview()
    containerView.bottom(to: editProfileButton)
}

希望这对某个人有帮助!如果有人知道如何在不破坏单元格约束的情况下使用动态集合调用reloadData()ViewCell Height,请让我知道!我试了两个星期,仍然没有找到解决方案:(.

这篇关于自调整大小动态UICollectionViewCell Height在调用reloadData()后不正确地调整自身大小的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆