自定义uiview在表格内部自定义单元格“跳跃”在表负载上

发布于 2025-01-22 05:55:51 字数 4928 浏览 7 评论 0 原文

我有一个 uitaiteView ,其中内部的自定义单元格被称为 newscell 。 在 newscell 内,我有一个自定义 uiview 用作操作按钮。

很多时候,当 tableView 加载单元格时,自定义操作按钮出现在单元格的 top 持续几秒钟,直到它回到其正确的位置细胞的底部。有时,只有在我将单元滚出视口滚出后,它才能返回到正确的位置。

知道为什么会发生这种情况吗?

这是一张使事情变得更清晰的照片: contion按钮

使用.xib文件创建了newscell

protocol NewsCellDelegate {
    func favoriteIconDidPress(forArticle article: Article)
    func actionButtonDidPress(inside article: Article)
}

enum ArticleFavoriteMark {
    case selected
    case notSelected
}

class NewsCell: UITableViewCell, MainActionButtonDelegate{

    @IBOutlet weak var entireNewsCell: UIView!
    @IBOutlet weak var newsImage: UIImageView!
    @IBOutlet weak var favoriteIcon: UIImageView!
    
    @IBOutlet weak var dateLabel: UILabel!
    @IBOutlet weak var subjectTag: UIButton!
    @IBOutlet weak var moreSubjectsTag: UIButton!
    
    @IBOutlet weak var titleLabel: UILabel!
    @IBOutlet weak var authorLabel: UILabel!
    @IBOutlet weak var summaryLabel: UILabel!
    
    @IBOutlet weak var actionButton: MainActionButtonView!
    
    var delegate: NewsCellDelegate?
    var articleUrl = ""
    var articleID = ""
    var articleImageUrl = ""
    var isFavorite: Bool = false
    
    
    override func awakeFromNib() {
        super.awakeFromNib()

        setCellBorder()
        setCellColorsDesign()
        setImageRounded()
        setTagsRounded()
        setGestureRecognizer()
        
        actionButton.delegate = self
    }
    
    override func layoutSubviews() {
        super.layoutSubviews()

        contentView.frame = contentView.frame.inset(by: UIEdgeInsets(top: 20, left: 0, bottom: 0, right: 0))
    }
     

    func setGestureRecognizer() {
        favoriteIcon.addGestureRecognizer(UITapGestureRecognizer(target: favoriteIcon, action: #selector(favoriteIconPressed)))
        favoriteIcon.isUserInteractionEnabled = true
        let tapGestureRecognizer1 = UITapGestureRecognizer(target: self, action: #selector(favoriteIconPressed(tapGestureRecognizer:)))
        favoriteIcon.addGestureRecognizer(tapGestureRecognizer1)
    }
    
    
    @objc func favoriteIconPressed(tapGestureRecognizer: UITapGestureRecognizer) {
        let currentArticle = Article(id: articleID, articleTitle: titleLabel.text!, date: dateLabel.text ?? "", url: articleUrl, content: summaryLabel.text!, author: authorLabel.text ?? "", topic: subjectTag.currentTitle!, imageUrl: articleImageUrl , isFavorite: isFavorite)
        delegate?.favoriteIconDidPress(forArticle: currentArticle)
    }
    
    
    func actionButtonDidPress(btnText: String) {
        let currentArticle = Article(
            id: articleID,
            articleTitle: titleLabel.text ?? "",
            date: dateLabel.text ?? "",
            url: articleUrl,
            content: summaryLabel.text ?? "",
            author: authorLabel.text ?? "",
            topic: subjectTag.currentTitle ?? "",
            imageUrl: articleImageUrl,
            isFavorite: self.isFavorite)

        delegate?.actionButtonDidPress(inside: currentArticle)
    }
}

newscell 是我的 newscell 元素层次结构:

新闻单元格

元素我在 newscell 中的“操作”按钮上放了约束:

这就是我如何限制 actionbutton uiview 在“动作”按钮自定义Uiview 内部的约束

在我的tableView中,我在tableView中启动了每个单元格,

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        
        let currentCell = tableView.dequeueReusableCell(withIdentifier: Constants.TableCellsIdentifier.FAVORITES, for: indexPath) as! SavedArticleCell
        currentCell.delegate = self
        
        let currentKey = viewModel.keysArray[indexPath.row]
        let savedArticle = viewModel.savedArticles[currentKey]
        
        if let savedArticle = savedArticle {
            currentCell.articleID = savedArticle.id!
            currentCell.articleTitle.text = savedArticle.title
            currentCell.articleTopic.setTitle(savedArticle.topic, for: .normal)
            
            if let imageUrl = savedArticle.imageUrl {
                currentCell.articleImageURL = imageUrl
                currentCell.articleImage.sd_setImage(with: URL(string: imageUrl), placeholderImage: UIImage(named: "light-gray-background"))
            } else {
                currentCell.articleImage.image = UIImage(named: "light-gray-background")
            }
        }
        
        return currentCell
    }

I have a UITableView with custom cells inside it called NewsCell.
Inside the NewsCell I have a custom UIView that is used as an action button.

Many times when the TableView is loading a cell, the custom action button appears at the top of the cell for a few seconds until it goes back down to its right spot at the bottom of the cell. Sometimes it returns to its right place only after I scroll the cell out of the viewport.

Any idea why this is happening?

Here is a photo to make things clearer:
action button out of place

NewsCell was created using .xib file and here is the relevant codes:

protocol NewsCellDelegate {
    func favoriteIconDidPress(forArticle article: Article)
    func actionButtonDidPress(inside article: Article)
}

enum ArticleFavoriteMark {
    case selected
    case notSelected
}

class NewsCell: UITableViewCell, MainActionButtonDelegate{

    @IBOutlet weak var entireNewsCell: UIView!
    @IBOutlet weak var newsImage: UIImageView!
    @IBOutlet weak var favoriteIcon: UIImageView!
    
    @IBOutlet weak var dateLabel: UILabel!
    @IBOutlet weak var subjectTag: UIButton!
    @IBOutlet weak var moreSubjectsTag: UIButton!
    
    @IBOutlet weak var titleLabel: UILabel!
    @IBOutlet weak var authorLabel: UILabel!
    @IBOutlet weak var summaryLabel: UILabel!
    
    @IBOutlet weak var actionButton: MainActionButtonView!
    
    var delegate: NewsCellDelegate?
    var articleUrl = ""
    var articleID = ""
    var articleImageUrl = ""
    var isFavorite: Bool = false
    
    
    override func awakeFromNib() {
        super.awakeFromNib()

        setCellBorder()
        setCellColorsDesign()
        setImageRounded()
        setTagsRounded()
        setGestureRecognizer()
        
        actionButton.delegate = self
    }
    
    override func layoutSubviews() {
        super.layoutSubviews()

        contentView.frame = contentView.frame.inset(by: UIEdgeInsets(top: 20, left: 0, bottom: 0, right: 0))
    }
     

    func setGestureRecognizer() {
        favoriteIcon.addGestureRecognizer(UITapGestureRecognizer(target: favoriteIcon, action: #selector(favoriteIconPressed)))
        favoriteIcon.isUserInteractionEnabled = true
        let tapGestureRecognizer1 = UITapGestureRecognizer(target: self, action: #selector(favoriteIconPressed(tapGestureRecognizer:)))
        favoriteIcon.addGestureRecognizer(tapGestureRecognizer1)
    }
    
    
    @objc func favoriteIconPressed(tapGestureRecognizer: UITapGestureRecognizer) {
        let currentArticle = Article(id: articleID, articleTitle: titleLabel.text!, date: dateLabel.text ?? "", url: articleUrl, content: summaryLabel.text!, author: authorLabel.text ?? "", topic: subjectTag.currentTitle!, imageUrl: articleImageUrl , isFavorite: isFavorite)
        delegate?.favoriteIconDidPress(forArticle: currentArticle)
    }
    
    
    func actionButtonDidPress(btnText: String) {
        let currentArticle = Article(
            id: articleID,
            articleTitle: titleLabel.text ?? "",
            date: dateLabel.text ?? "",
            url: articleUrl,
            content: summaryLabel.text ?? "",
            author: authorLabel.text ?? "",
            topic: subjectTag.currentTitle ?? "",
            imageUrl: articleImageUrl,
            isFavorite: self.isFavorite)

        delegate?.actionButtonDidPress(inside: currentArticle)
    }
}

This is my NewsCell elements hierarchy:

news cell elements

And these are the constraints I put on the action button inside the NewsCell:

constraints on action button inside NewsCell

And this is how I constrained the ActionButton UIView:
constraints inside the action button custom uiview

In my TableView I initiate each cell like this:

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        
        let currentCell = tableView.dequeueReusableCell(withIdentifier: Constants.TableCellsIdentifier.FAVORITES, for: indexPath) as! SavedArticleCell
        currentCell.delegate = self
        
        let currentKey = viewModel.keysArray[indexPath.row]
        let savedArticle = viewModel.savedArticles[currentKey]
        
        if let savedArticle = savedArticle {
            currentCell.articleID = savedArticle.id!
            currentCell.articleTitle.text = savedArticle.title
            currentCell.articleTopic.setTitle(savedArticle.topic, for: .normal)
            
            if let imageUrl = savedArticle.imageUrl {
                currentCell.articleImageURL = imageUrl
                currentCell.articleImage.sd_setImage(with: URL(string: imageUrl), placeholderImage: UIImage(named: "light-gray-background"))
            } else {
                currentCell.articleImage.image = UIImage(named: "light-gray-background")
            }
        }
        
        return currentCell
    }

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

忆伤 2025-01-29 05:55:51

您必须添加 contentView.layoutifneeded() in layoutsubviews() newscell

override func layoutSubviews() {
    super.layoutSubviews()
    
    contentView.frame = contentView.frame.inset(by: UIEdgeInsets(top: 20, left: 0, bottom: 0, right: 0))
    contentView.layoutIfNeeded()
}

layoutifneed()的目的是要强制一种视图及其子视图的同步(本质上是“立即”的)。您必须称呼此功能,因为您已经更新了 layoutsubviews()方法中的布局。关于 layoutifneed()这是说。

使用此方法迫使视图立即更新其布局。使用自动布局时,布局引擎会根据需要更新视图位置,以满足约束的变化。使用接收消息作为根视图的视图,此方法从根部开始列出视图子树。如果没有布局更新正在待处理,则此方法在不修改布局或调用任何与布局相关的回调的情况下退出。

You have to add contentView.layoutIfNeeded() in layoutSubViews() method of NewsCell

override func layoutSubviews() {
    super.layoutSubviews()
    
    contentView.frame = contentView.frame.inset(by: UIEdgeInsets(top: 20, left: 0, bottom: 0, right: 0))
    contentView.layoutIfNeeded()
}

The purpose of layoutIfNeeded() is to force a synchronous (essentially "immediate") redraw of a view and its subviews. You have to call this because you have updated the layout in layoutsubviews() method. Regarding layoutIfNeeded() Here is what Apple says.

Use this method to force the view to update its layout immediately. When using Auto Layout, the layout engine updates the position of views as needed to satisfy changes in constraints. Using the view that receives the message as the root view, this method lays out the view subtree starting at the root. If no layout updates are pending, this method exits without modifying the layout or calling any layout-related callbacks.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文