web-dev-qa-db-ja.com

テキストビューの高さをSWIFTのコンテンツに合わせて調整する方法は?

私のView Controllerには、UITextViewがあります。このテキストビューには文字列が入力されます。文字列は短くても長くてもかまいません。文字列の長さに応じて、textviewの高さを調整する必要があります。ストーリーボードと自動レイアウトを使用しています。

テキストビューの高さにいくつか問題があります。

場合によっては、高さがテキストに完全に調整されます。時々、いいえ、最初の行でテキストがトリミングされます。以下では、textviewは黄色です。青はスクロールビュー内のコンテナビューです。紫は写真を撮る場所です。

title1title2

テキストは私のコアデータベースからのもので、文字列属性です。画面1と2の間で変更されるのは文字列だけです。
コンソールで文字列を印刷すると、正しいテキストが表示されます。

my amazing new title

Another funny title for demo

私のテキストビューの制約:

enter image description here

2つの異なるディスプレイがある理由がわかりません。

編集

私はviewDidLoadで@Nateのアドバイスを試しました、私は追加しました:

    myTextViewTitle.text="my amazing new title"

    myTextViewTitle.setContentHuggingPriority(1000, forAxis: UILayoutConstraintAxis.Vertical)
    myTextViewTitle.setContentCompressionResistancePriority(1000, forAxis: UILayoutConstraintAxis.Vertical)
    myTextViewTitle.setTranslatesAutoresizingMaskIntoConstraints(false)  

    let views = ["new_view": myTextViewTitle]
    var constrs = NSLayoutConstraint.constraintsWithVisualFormat("|-8-[new_view]-8-|", options: NSLayoutFormatOptions(0), metrics: nil, views: views)
    self.view.addConstraints(constrs)
    self.view.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("V:|-8-[new_view]", options: NSLayoutFormatOptions(0), metrics: nil, views: views))
    self.myTextViewTitle.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("V:[new_view(220@300)]", options: NSLayoutFormatOptions(0), metrics: nil, views: views))

結果がありません。インターフェイスビルダーのテキストビューに追加された高さ制約の有無にかかわらず...

編集2

除外パスを使用するには、戻るボタンがあるため、UIlabelではなくUITextViewが必要です。

     let exclusionPathBack:UIBezierPath = UIBezierPath(rect: CGRect(x:backButton.bounds.Origin.x, y:backButton.bounds.Origin.y, width:backButton.bounds.width+10, height:backButton.bounds.height))
     myTextViewTitle.textContainer.exclusionPaths=[exclusionPathBack]
23
cmii

私は解決策を見つけました。

UITextViewの高さに注目し、アスペクト比に関する記事を読みました。試してみたかったのですが、うまくいきました!

そのため、ストーリーボードで、textviewのアスペクト比を追加し、[ビルド時に削除]オプションをオンにしました。

ViewDidLayoutSubviews()で、私は書いた:

override func viewDidLayoutSubviews() {

    super.viewDidLayoutSubviews()

    let contentSize = self.myTextViewTitle.sizeThatFits(self.myTextViewTitle.bounds.size)
    var frame = self.myTextViewTitle.frame
    frame.size.height = contentSize.height
    self.myTextViewTitle.frame = frame

    aspectRatioTextViewConstraint = NSLayoutConstraint(item: self.myTextViewTitle, attribute: .Height, relatedBy: .Equal, toItem: self.myTextViewTitle, attribute: .Width, multiplier: myTextViewTitle.bounds.height/myTextViewTitle.bounds.width, constant: 1)
    self.myTextViewTitle.addConstraint(aspectRatioTextViewConstraint!)

}

完璧に機能します。

40
cmii

まず、UITextViewのスクロール可能を無効にします。 2つのオプション:

  1. .xibのScrolling Enabledをオフにします。
  2. [TextView setScrollEnabled:NO];

UITextViewを作成し、IBOutlet(TextView)に接続します。デフォルトの高さのUITextView高さ制約を追加し、IBOutlet(TextViewHeightConstraint)に接続します。 UITextViewのテキストを非同期に設定する場合、UITextViewの高さを計算し、UITextViewの高さの制約を設定する必要があります。サンプルコード:

CGSize sizeThatFitsTextView = [TextView sizeThatFits:CGSizeMake(TextView.frame.size.width, MAXFLOAT)];

TextViewHeightConstraint.constant = sizeThatFitsTextView.height; 

In Swift 3.0、tvHeightConstraintは対象のTextViewの高さの制約です(複数のtextviewを使用する場合、関数入力に追加します):

func textViewDidChange(textView: UITextView) {

        let size = textView.sizeThatFits(CGSize(width: textView.frame.size.width, height: CGFloat.greatestFiniteMagnitude))
        if size.height != tvHeightConstraint.constant && size.height > textView.frame.size.height{
            tvHeightConstraint.constant = size.height
            textView.setContentOffset(CGPoint.zero, animated: false)
        }
    }

@cmiおよび@Pablo RuanへのH/T

8
agrippa

In Swift 2.3:

 func textViewDidChange(textView: UITextView) {

    let size = textView.sizeThatFits(CGSize(width: textView.frame.size.width, height: CGFloat.max))
    if size.height != TXV_Height.constant && size.height > textView.frame.size.height{
        TXV_Height.constant = size.height
        textView.setContentOffset(CGPointZero, animated: false)
    }
}
5
Pablo Ruan

私はあなたのコードを適合させ、レイアウトサブビューとtextViewDidChangeの両方に使用しました。トラブルシューティングを1時間行った後、私の1日をありがとうございました...

override func viewDidLayoutSubviews() {

    super.viewDidLayoutSubviews()
    textViewDidChange(self.recordingTitleTV)


}

func textViewDidChange(_ textView: UITextView) {

    let contentSize = textView.sizeThatFits(textView.bounds.size)
    var frame = textView.frame
    frame.size.height = contentSize.height
    textView.frame = frame

    let aspectRatioTextViewConstraint = NSLayoutConstraint(item: textView, attribute: .height, relatedBy: .equal, toItem: textView, attribute: .width, multiplier: textView.bounds.height/textView.bounds.width, constant: 1)
    textView.addConstraint(aspectRatioTextViewConstraint)
}
0
AppNerd

非常に類似した問題に対する私の簡単な解決策:

テキストフィールドまたはビューを使用する代わりに、行数を0に設定したラベルを使用しました。次に、この例では幅を制約するラベルのコンテナーにリーディングエッジとトレーリングエッジをクリップしました。制約の定数は0です。問題は、行数を0に設定して、内容に応じてラベルを拡大または縮小できるようにすることです。テキストが切り取られることはなく、ラベルの高さは、幅(私の場合はコンテナーの幅)に対して構成したさまざまなサイズクラスのすべてについて、その内容を超えることはありません。 IOS 8.0以降(さまざまなサイズクラスに合わせてラベル幅のすべてのラベルの[優先幅]属性の横にある[明示的]がオフになっていることも確認してください)].

0
AshleyC

戻るボタンの画像とテキストのUILabelを用意し、自動レイアウトを使用して配置しませんか?そして、おそらく黄色の背景の3番目のビュー。

0
Koen