【问题标题】:Self sizing dynamic UICollectionViewCell height improperly sizes itself after calling reloadData()调用 reloadData() 后自行调整动态 UICollectionViewCell 高度的大小不正确
【发布时间】:2022-01-16 02:30:43
【问题描述】:

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

这工作得很好,我可以单击所有按钮,向上或向下滚动等,但问题是当我调用 reloadData() 时,collectionViewCell 的约束被搞砸了,它们出于某种原因相互堆叠.

这是调用reloadData()之前collectionView的图片:

这是我打电话给reloadData()后收集的照片:

任何人都可能知道为什么会发生这种情况以及我该如何解决?

这是我的 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()
}

}

提前致谢!

【问题讨论】:

    标签: swift dynamic uicollectionviewcell uicollectionviewlayout


    【解决方案1】:

    终于想通了,如果其他人遇到这个问题,你可以如何解决这个问题。

    所以我决定使用 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")
    }
    

    }

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

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

    添加contentView.addsubview(containerView)并将所有单元格内容放入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)
    }
    

    希望这对某人有所帮助!如果有人知道如何使用动态 collectionViewCell 高度调用 reloadData() 而不会破坏单元格约束,请告诉我!我尝试了 2 周,但仍然没有找到解决方案:(。

    【讨论】:

      猜你喜欢
      • 2015-11-10
      • 1970-01-01
      • 2018-08-04
      • 2014-04-02
      • 1970-01-01
      • 1970-01-01
      • 2018-04-29
      • 2021-10-27
      • 1970-01-01
      相关资源
      最近更新 更多