TLによってクリップされ、DR:は、NSTextFieldはNSImageView
のMacOS 10.11、NSTableViewは、いくつかの行が画像を有する、右のテキストフィールドの下にNSTextFieldとNSImageViewを含むベースビューで他のものではなく、いくつかのテキストはテーブルをスクロールした後に切り取られます。
をスクロールした後:スクロール前
私はそれが自動レイアウトで定義されているテキストビューは、その最小の高さであることを意味し、 "クリッピング" と言います、代わりに展開する必要があります。
この問題はMacOS 10.11マーベリックスでのみ発生することに注意してください。 macOS 10.12 Sierraにはこのような問題はありません。
コンテキスト
MacOSの10.11+、 NSTableView基づい図。
各行にはテキストフィールドがあり、テキストフィールドのすぐ下にイメージビューがあります。
すべての要素には、IBで設定された自動レイアウト制約があります。
目標
テキストビューは、垂直方向の高さを適合しなければならない - 画像ビューは、テキストフィールドの底に接着滞在し、それに応じて移動しなければなりません。
もちろん、行自体も高さに合わせなければなりません。
画像が表示されない場合があります。この場合、画像の表示は表示されません。
これは、それが正常に動作したときにレンダリングするはずの方法です:
現在の実装
行がNSTableCellViewのサブクラスです。
セルでは、テキストフィールドに属性付き文字列が設定されます。
tableView(_ tableView: NSTableView, heightOfRow row: Int) -> CGFloat
では、私は実際のテキストフィールドの高さを見つけ、それに応じて修正された行の高さを返すために使用するダミーのtextViewを作成します。表示する画像があるかどうかを確認し、その場合は画像の高さを行の高さに追加します。tableView(_ tableView: NSTableView, viewFor tableColumn: NSTableColumn?, row: Int) -> NSView?
で
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
は、私が実際のセルの内容を準備します
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スクロール、とすぐに表示の問題があるのですビュー。
クリップされたテキスト
ときどきテキストが空の画像ビューは、テキストの下の部分をマスキングしているためか、クリッピングされます。クリップされ
ノーマル
重要:テーブルのサイズを変更して再描画をトリガし、表示の問題を修正...
私は主な問題は思った
セル再使用
を試してみた何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のは、まだテキストをブロックしていますいくつかのケースで見ることができます。
とにかく、任意のスクロールが行われる前に、時にはテキストは、最初の表示でクリップされています...
CoreAnimationレイヤ
私は、彼らがしているように、細胞が裏打ちされた層である必要は多分考え正しく再表示されたので、scrollView、tableView、tableCellなどでCoreAnimationレイヤーを有効にしましたが、ほとんど違いはありません。
A/Bテスト
私は完全にImageViewのを削除し、唯一のテキストフィールドのすべてがOK作品を扱う場合。 imageViewを持っていることは間違いなくここで問題を引き起こしています。
自動レイアウト
私は、自動レイアウトを使用せずに、しかし無駄に行の内容の表示を処理しようとしました。私はまた別の制約を設定しようとしましたが、明らかに私はautolayoutを吸って、私の現在の制約に代わる良い方法を見つけられませんでした。
オルタナティブ:NSAttributedString画像とは
私はイメージビューを削除しようとした画像ではなくテキストビューの属性付き文字列の末尾に追加されました。しかし、結果はしばしば醜いです。ほとんどの場合、それはうまくいきません(例えば、文字列に追加する時間に画像をダウンロードできず、テキストや画像なしでセルを残すなど)誤った高さで)。
質問
私は間違っていますか?どうすればこれらの問題を解決できますか?私の推測では、自動レイアウト制約を変更する必要がありますが、実際のソリューションは表示されません。
これはまったく別のことですか?
あなたはNSTextViewと、NSTextFieldを使っているピクチャとコードについて話しています。 'ns.bounds.size'が' heightOfRow'で正しいかどうかチェックしましたか? – Willeke
Arf、私のせいで、テスト中にNSTextViewからNSTextFieldに変更されましたが、元に戻すのを忘れてしまいました。 NSTextFieldの使い方が間違っていると思いますか?NSTextViewに戻ってください。 // Woah、ns.bounds.sizeは常に高さがゼロです...何が起こっているのかは分かりませんが、NSTextViewではなくNSTextFieldが原因ですか? – Moritz
私は、これがMacOS 10.12 Sierraで問題なく動作することを発見しました。間違った動作はMacOS 10.11マーベリックスでのみ発生します... oO – Moritz