539

UITextView大量のテキストを表示する iOS アプリケーションを使用しています。

次に、のオフセット マージン パラメータを使用して、このテキストをページングしていますUITextView

UITextView私の問題は、使用するフォントサイズと書体によって異なるように見えるため、のパディングが計算を混乱させることです。

のコンテンツを囲むパディングを削除することは可能UITextViewですか?

4

24 に答える 24

819

iOS 7.0 では、contentInset トリックが機能しなくなっていることがわかりました。これは、iOS 7 でマージン/パディングを取り除くために使用したコードです。

これにより、テキストの左端がコンテナーの左端に移​​動します。

textView.textContainer.lineFragmentPadding = 0

これにより、テキストの上部がコンテナーの上部に揃えられます。

textView.textContainerInset = .zero

マージン/パディングを完全に削除するには、両方の行が必要です。

于 2013-09-24T17:05:03.450 に答える
460

2021年の最新情報

これは、iOS で最も愚かなバグの 1 つです。

ここで指定されたクラスUITextViewFixedは広く使用されており、通常は全体として最も合理的なソリューションです。

クラスは次のとおりです。

@IBDesignable class UITextViewFixed: UITextView {
    override func layoutSubviews() {
        super.layoutSubviews()
        setup()
    }
    func setup() {
        textContainerInset = UIEdgeInsets.zero
        textContainer.lineFragmentPadding = 0
    }
}

インスペクタで scrollEnabled をオフにすることを忘れないでください!

  1. ソリューションはストーリーボードで正しく機能します

  2. ソリューションは実行時に適切に機能します

これで完了です。

一般に、ほとんどの場合、これで十分です。

その場でテキストビューの高さを変更している場合でも、UITextViewFixed通常は必要なすべてを行います。

(その場で高さを変更する一般的な例は、ユーザーの入力に応じて変更することです。)

これはAppleの壊れたUITextViewです...

UITextView を使用した Interface Builder のスクリーンショット

ここにあるUITextViewFixed

UITextViewFixed を使用した Interface Builder のスクリーンショット

もちろん、あなたがしなければならないことに注意してください...

...インスペクタで scrollEnabled をオフにします。

(scrollEnabled をオンにするということは、「このビューを可能な限り下の余白を拡大することによって、垂直方向に可能な限り拡大する」ことを意味します。)


さらにいくつかの問題

(1) 高さを動的に変更するいくつかの非常にまれなケースでは、Apple は奇妙なことを行います:下部に余分なスペースを追加します

いいえ、本当に!これは、iOS で最も腹立たしいことの 1 つに違いありません。

問題が発生した場合は、通常役立つ「クイック フィックス」を次に示します。

...
        textContainerInset = UIEdgeInsets.zero
        textContainer.lineFragmentPadding = 0

        // this is not ideal, but sometimes this "quick fix"
        // will solve the "extra space at the bottom" insanity:
        var b = bounds
        let h = sizeThatFits(CGSize(
           width: bounds.size.width,
           height: CGFloat.greatestFiniteMagnitude)
       ).height
       b.size.height = h
       bounds = b
 ...

(2) まれに、Apple によるさらに別の微妙な混乱を修正するために、以下を追加する必要があります。

override func setContentOffset(_ contentOffset: CGPoint, animated: Bool) {
    super.setContentOffset(contentOffset, animated: false) // sic
}

(3) おそらく、以下を追加する必要があります。

contentInset = UIEdgeInsets.zero

直後.lineFragmentPadding = 0UITextViewFixed

しかし...信じられないかもしれませんが...それは現在のiOSでは機能しません! (2021年チェック済み。)今後、その行を追加する必要があるかもしれません。

iOS で壊れているという事実UITextViewは、すべてのモバイル コンピューティングで最も奇妙なことの 1 つです。この質問から 10 周年を迎えましたが、まだ修正されていません。

最後に、Text Fieldについても同様のヒントがあります: Set the maximum character length of a UITextField in Swift

完全にランダムなヒント: 末尾に「...」を追加する方法

多くの場合、「UILabel のような」UITextView を使用しています。したがって、省略記号「...」を使用してテキストを切り捨てる必要があります。

その場合は、次を追加します。

 textContainer.lineBreakMode = .byTruncatingTail

テキストがまったくないときに、高さをゼロにしたい場合の便利なヒント

多くの場合、テキスト ビューを使用してテキストのみを表示します。したがって、行数「0」を使用して、テキスト ビューの高さがテキストの行数に応じて自動的に変更されることを意味します。

それは素晴らしいことです。しかし、テキストがまったくない場合、残念ながらテキストが 1 行ある場合と同じ高さになります!!!! テキストビューが「消える」ことはありません。

ここに画像の説明を入力してください

「消える」ようにしたい場合は、これを追加してください

override var intrinsicContentSize: CGSize {
    var i = super.intrinsicContentSize
    print("for \(text) size will be \(i)")
    if text == "" { i.height = 1.0 }
    print("   but we changed it to \(i)")
    return i
}

ここに画像の説明を入力してください

(高さを「1」にしたので、そのデモで何が起こっているかは明らかです。「0」で問題ありません。)

UILabel はどうですか?

テキストを表示するだけの場合、UILabel には UITextView よりも多くの利点があります。UILabel には、この Q&A ページに記載されている問題はありません。

実際、私たち全員が通常「あきらめ」て UITextView を使用する理由は、UILabel の操作が難しいためです。特に、 UILabel にpaddingを正しく追加するのは非常に困難です。

実際、ここでは UILabel にパディングを「最終的に」正しく追加する方法についての完全な議論があります: UILabelにスペース/パディングを追加します。場合によっては、動的な高さのセルで難しいレイアウトを行っている場合、UILabel を使用して難しい方法で行う方がよい場合があります。

于 2017-02-19T22:45:34.307 に答える
259

この回避策は、iOS 3.0 がリリースされた 2009 年に作成されました。適用されなくなりました。

私はまったく同じ問題に遭遇し、最終的には使用する必要がありました

nameField.contentInset = UIEdgeInsetsMake(-4, -8, 0, 0);

nameField はUITextViewです。たまたま使っていたフォントは Helvetica 16 ポイントでした。これは、私が描いていた特定のフィールド サイズのカスタム ソリューションにすぎません。これにより、左側のオフセットが左側と同じ高さになり、上部のオフセットが描画されたボックスに必要な場所になります。

さらに、これUITextViewsはデフォルトのアラインメントを使用している場所にのみ適用されるようです。つまり、

nameField.textAlignment = NSTextAlignmentLeft;

たとえば、右に揃えると、右端にUIEdgeInsetsMakeはまったく影響がないように見えます。

少なくとも、.contentInset プロパティを使用すると、フィールドを「正しい」位置に配置し、.content をオフセットすることなく偏差に対応できますUITextViews

于 2009-07-26T18:59:52.760 に答える
47

iOS 5 ではUIEdgeInsetsMake(-8,-8,-8,-8);うまく動作するようです。

于 2012-05-08T12:36:13.957 に答える
43

実際の余白はユーザーのフォントサイズ設定などで変わる可能性があるため、ハードコードされた値を含む回答は絶対に避けます。

これはuser1687195の回答で、変更せずに書かれていますtextContainer.lineFragmentPaddingドキュメントではこれは意図した使用法ではないと述べているため)。

これは、iOS 7 以降でうまく機能します。

self.textView.textContainerInset = UIEdgeInsetsMake(
                                      0,
                                      -self.textView.textContainer.lineFragmentPadding,
                                      0,
                                      -self.textView.textContainer.lineFragmentPadding);

これは事実上同じ結果ですが、 lineFragmentPadding プロパティを誤用しないという点で少しすっきりしています。

于 2016-04-24T18:36:34.113 に答える
13

Fattie の非常に役立つ回答の更新版を次に示します。iOS 10 および 11 でレイアウトを機能させるのに役立つ 2 つの重要な行が追加されました (おそらく下位のものでも)。

@IBDesignable class UITextViewFixed: UITextView {
    override func layoutSubviews() {
        super.layoutSubviews()
        setup()
    }
    func setup() {
        translatesAutoresizingMaskIntoConstraints = true
        textContainerInset = UIEdgeInsets.zero
        textContainer.lineFragmentPadding = 0
        translatesAutoresizingMaskIntoConstraints = false
    }
}

重要な行は 2 つのtranslatesAutoresizingMaskIntoConstraints = <true/false>ステートメントです。

これは驚くべきことに、私のすべての状況ですべてのマージンを削除します!

は最初のレスポンダーではありませんが、受け入れられた回答に記載されている方法をtextView使用して解決できない奇妙な下部マージンが発生する可能性があります。sizeThatFits

textView をタップすると、突然奇妙な下マージンが消え、すべてが本来のように見えましたが、textView がfirstResponder.

そのため、呼び出しの間にフレーム/境界を手動で設定するときに、有効化と無効化が役立つことを Stack Overflowで読みました。translatesAutoresizingMaskIntoConstraints

幸いなことに、これはフレーム設定だけでなく、2 つの呼び出しsetup()の間に挟まれた 2つの行でも機能します。translatesAutoresizingMaskIntoConstraints

これは、たとえば、を使用してビューのフレームを計算するときに非常に役立ちます。正しいサイズが返されます (以前は返されませんでした)。systemLayoutSizeFittingUIView

言及された元の回答のように:

インスペクタで scrollEnabled をオフにすることを忘れないでください! そのソリューションは、実行時だけでなく、ストーリーボードでも適切に機能します。

これで、本当に完了です。

于 2018-02-14T14:37:43.460 に答える
12

iOS 10 の場合、次の行は上下のパディングの削除に機能します。

captionTextView.textContainerInset = UIEdgeInsetsMake(0, 0, 0, 0)
于 2016-10-12T06:38:16.090 に答える
4

はめ込みソリューションを実行すると、右側と下部にまだパディングがありました。また、テキストの配置が問題を引き起こしていました。私が見つけた唯一の確実な方法は、境界にクリップされた別のビュー内にテキスト ビューを配置することでした。

于 2011-03-31T23:49:05.607 に答える
1

もう1つのアプローチを見つけました。UITextView のサブビューからテキストを含むビューを取得し、サブクラスの layoutSubview メソッドで設定します。

- (void)layoutSubviews {
    [super layoutSubviews];

    const int textViewIndex = 1;
    UIView *textView = [self.subviews objectAtIndex:textViewIndex];
    textView.frame = CGRectMake(
                                 kStatusViewContentOffset,
                                 0.0f,
                                 self.bounds.size.width - (2.0f * kStatusViewContentOffset),
                                 self.bounds.size.height - kStatusViewContentOffset);
}
于 2013-02-28T10:17:28.253 に答える
1

HTML 文字列を設定し、下部のパディングを避けたい場合は、ブロック タグ、つまり、divおよびを使用していないことを確認してくださいp

私の場合はこれが原因でした。ブロックタグの出現をタグなどに置き換えることで、簡単にテストできますspan

于 2020-01-03T17:07:52.080 に答える
1

textView のスクロールもテキストの位置に影響を与え、垂直方向の中央に配置されていないように見えます。スクロールを無効にし、上部のインセットを 0 に設定することで、テキストをビューの中央に配置することができました。

    textView.scrollEnabled = NO;
    textView.textContainerInset = UIEdgeInsetsMake(0, textView.textContainerInset.left, textView.textContainerInset.bottom, textView.textContainerInset.right);

何らかの理由でまだ理解できていませんが、入力を開始する前にカーソルはまだ中央に配置されていませんが、入力を開始するとすぐにテキストが中央に配置されます。

于 2016-12-25T19:37:05.553 に答える
-4
[firstNameTextField setContentVerticalAlignment:UIControlContentVerticalAlignmentCenter];
于 2011-08-11T21:48:18.497 に答える