2017-01-16 21 views
1

TLによってクリップされ、DR:は、NSTextFieldはNSImageView

のMacOS 10.11、NSTableViewは、いくつかの行が画像を有する、右のテキストフィールドの下にNSTextFieldとNSImageViewを含むベースビューで他のものではなく、いくつかのテキストはテーブルをスクロールした後に切り取られます。

enter image description here

をスクロールした後:スクロール前

enter image description here

私はそれが自動レイアウトで定義されているテキストビューは、その最小の高さであることを意味し、 "クリッピング" と言います、代わりに展開する必要があります。

この問題はMacOS 10.11マーベリックスでのみ発生することに注意してください。 macOS 10.12 Sierraにはこのような問題はありません。


コンテキスト

MacOSの10.11+、 NSTableView基づい図。

各行にはテキストフィールドがあり、テキストフィールドのすぐ下にイメージビューがあります。

すべての要素には、IBで設定された自動レイアウト制約があります。

enter image description here

enter image description here

目標

テキストビューは、垂直方向の高さを適合しなければならない - 画像ビューは、テキストフィールドの底に接着滞在し、それに応じて移動しなければなりません。

もちろん、行自体も高さに合わせなければなりません。

画像が表示されない場合があります。この場合、画像の表示は表示されません。

これは、それが正常に動作したときにレンダリングするはずの方法です:

enter image description here

現在の実装

行が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スクロール、とすぐに表示の問題があるのですビュー。

クリップされたテキスト

ときどきテキストが空の画像ビューは、テキストの下の部分をマスキングしているためか、クリッピングされます。クリップされ

ノーマル

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のは、まだテキストをブロックしていますいくつかのケースで見ることができます。

とにかく、任意のスクロールが行われる前に、時にはテキストは、最初の表示でクリップされています...

CoreAnimationレイヤ

私は、彼らがしているように、細胞が裏打ちされた層である必要は多分考え正しく再表示されたので、scrollView、tableView、tableCellなどでCoreAnimationレイヤーを有効にしましたが、ほとんど違いはありません。

A/Bテスト

私は完全にImageViewのを削除し、唯一のテキストフィールドのすべてがOK作品を扱う場合。 imageViewを持っていることは間違いなくここで問題を引き起こしています。

自動レイアウト

私は、自動レイアウトを使用せずに、しかし無駄に行の内容の表示を処理しようとしました。私はまた別の制約を設定しようとしましたが、明らかに私はautolayoutを吸って、私の現在の制約に代わる良い方法を見つけられませんでした。

オルタナティブ:NSAttributedString画像とは

私はイメージビューを削除しようとした画像ではなくテキストビューの属性付き文字列の末尾に追加されました。しかし、結果はしばしば醜いです。ほとんどの場合、それはうまくいきません(例えば、文字列に追加する時間に画像をダウンロードできず、テキストや画像なしでセルを残すなど)誤った高さで)。

質問

私は間違っていますか?どうすればこれらの問題を解決できますか?私の推測では、自動レイアウト制約を変更する必要がありますが、実際のソリューションは表示されません。

これはまったく別のことですか?

+0

あなたはNSTextViewと、NSTextFieldを使っているピクチャとコードについて話しています。 'ns.bounds.size'が' heightOfRow'で正しいかどうかチェックしましたか? – Willeke

+0

Arf、私のせいで、テスト中にNSTextViewからNSTextFieldに変更されましたが、元に戻すのを忘れてしまいました。 NSTextFieldの使い方が間違っていると思いますか?NSTextViewに戻ってください。 // Woah、ns.bounds.sizeは常に高さがゼロです...何が起こっているのかは分かりませんが、NSTextViewではなくNSTextFieldが原因ですか? – Moritz

+0

私は、これがMacOS 10.12 Sierraで問題なく動作することを発見しました。間違った動作はMacOS 10.11マーベリックスでのみ発生します... oO – Moritz

答えて

1

テキストフィールドには、IBの「Preferred Width」フィールドがあります。これにより、自動レイアウト計算サイズと組み込みサイズの相関を調整できます。

このIBプロパティ値を「最初の実行時レイアウト幅」または「明示的」に変更すると、よく似た問題が解決されます。

enter image description here

これは、過去に私の問題の多くを解決しました。

+0

これはMavericksの問題を解決し、Sierraでは何も変更していないようです。ありがとう、ユージーン! :) – Moritz