gpt4 book ai didi

macos - 在基于 View 的 NSTableView 中,NSTextField 被 NSImageView 裁剪

转载 作者:行者123 更新时间:2023-12-03 17:09:46 25 4
gpt4 key购买 nike

TL;博士:

在 macOS 10.11 中,基于 View 的 NSTableView 在文本字段下方包含一个 NSTextField 和一个 NSImageView ,其中一些行有图像而其他行没有,在向下滚动表格后向上剪切一些文本。

滚动前:

enter image description here

滚动后:

enter image description here

当我说“剪裁”时,它意味着 TextView 处于自动布局定义的最小高度,而应该展开它。

请注意,此错误行为仅发生在 macOS 10.11 Mavericks 中。 macOS 10.12 Sierra 没有此类问题。

语境

macOS 10.11+,基于 View 的 NSTableView。

每行都有一个文本字段,以及文本字段下方的 ImageView 。

所有元素都在 IB 中设置了自动布局约束。

enter image description here

enter image description here

目标

TextView 必须垂直调整其高度 - ImageView 应相应移动,并保持粘在文本字段的底部。

当然,行本身也必须适应它的高度。

有时没有要显示的图像,在这种情况下, ImageView 不应该是可见的。

这是它正常工作时应该呈现的方式:

enter image description here

当前实现

该行是 NSTableCellView 的子类。

在单元格中,文本字段设置有属性字符串。

tableView(_ tableView: NSTableView, heightOfRow row: Int) -> CGFloat ,我制作了一个虚拟 TextView ,用于查找实际文本字段的高度,并相应地返回修改后的行高。我还检查是否有要显示的图像,如果是这种情况,我将图像高度添加到行高。

let ns = NSTextField(frame: NSRect(x: 0, y: 0, width: defaultWidth, height: 0))
ns.attributedStringValue = // the attributed string
var h = ns.attributedStringValue.boundingRect(with: ns.bounds.size, options: [.usesLineFragmentOrigin, .usesFontLeading]).height
if post.hasImage {
h += image.height
}
return h + margins

tableView(_ tableView: NSTableView, viewFor tableColumn: NSTableColumn?, row: Int) -> NSView?我准备了实际的单元格内容:
getUserAvatar { img in
DispatchQueue.main.async {
cell.iconBackground.layer?.backgroundColor = self.prefs.colors.iconBackground.cgColor
cell.iconBackground.rounded(amount: 6)
cell.iconView.rounded(amount: 6)
cell.iconView.image = img
}
}

cell.usernameLabel.attributedStringValue = xxx
cell.dateLabel.attributedStringValue = xxx

// the textView at the top of the cell
cell.textLabel.attributedStringValue = xxx

// the imageView right under the textView
if post.hasImage {
getImage { img in
DispatchQueue.main.async {
cell.postImage.image = img
}
}
}

问题

滚动 tableView 时,只要一行或几行在 ImageView 中有图像,就会出现显示问题。

剪切的文本

有时文本被剪裁,可能是因为空的 ImageView 掩盖了文本的底部:

普通的

enter image description here

剪裁

enter image description here

重要提示:调整表格大小会触发重绘并修复显示问题...

我试过的

单元重用

我认为主要问题是由于 tableView 重用了单元格。

所以我默认将图像字段隐藏在 tableView(_ tableView: NSTableView, viewFor tableColumn: NSTableColumn?, row: Int) -> NSView? 中,只有在有要设置的图像时才隐藏,我在主线程上执行此操作:
guard let cell = tableView.make(withIdentifier: "xxx", owner: self) as? PostTableCellView else {
return nil
}
DispatchQueue.main.async {
cell.postImage.isHidden = true
cell.postImage.image = nil
}
// set the text view here, the buttons, labels, etc, then this async part runs:
downloadImage { img in
DispatchQueue.main.async {
cell.postImage.isHidden = false
cell.postImage.image = img
}
}
// more setup
return cell

但是在某些情况下,imageView 仍然会阻塞 TextView 。

无论如何,有时在任何滚动完成之前,文本会在第一次显示时被剪裁......

核心动画层

我认为可能需要对单元格进行层支持,以便正确重新显示它们,所以我在 scrollView、tableView、tableCell 等上启用了 CoreAnimation 层。但我几乎看不到任何区别。

A/B 测试

如果我完全删除 imageView 并且只处理文本字段一切正常。拥有 imageView 绝对是这里造成问题的原因。

自动布局

我试图在不使用自动布局的情况下处理行内容的显示,但无济于事。我也尝试过设置不同的约束,但很明显我不喜欢自动布局,也没有找到一个很好的替代我当前约束的方法。

替代方案:带有图像的 NSAttributedString

我试图删除 ImageView ,并将图像添加到 TextView 中属性字符串的末尾。但是当它工作时结果通常很丑 - 而且在大多数情况下它只是不起作用(例如,当图像无法及时下载以添加到属性字符串中时,使单元格根本没有文本或图像并且高度错误)。

问题

我究竟做错了什么?我该如何解决这些问题?我的猜测是我应该更改自动布局约束,但我没有看到可行的解决方案。

或者,也许你会以完全不同的方式来做这件事?

最佳答案

文本字段在 IB 中有“首选宽度”字段,它允许调整固有大小与自动布局计算大小的相关性。

将此 IB 属性值更改为“First Runtime Layout Width”或“Explicit”通常有助于解决类似问题。

enter image description here

这解决了我过去的很多问题。

关于macos - 在基于 View 的 NSTableView 中,NSTextField 被 NSImageView 裁剪,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41675154/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com