UITextView大量のテキストを表示する iOS アプリケーションを使用しています。
次に、のオフセット マージン パラメータを使用して、このテキストをページングしていますUITextView。
UITextView私の問題は、使用するフォントサイズと書体によって異なるように見えるため、のパディングが計算を混乱させることです。
のコンテンツを囲むパディングを削除することは可能UITextViewですか?
UITextView大量のテキストを表示する iOS アプリケーションを使用しています。
次に、のオフセット マージン パラメータを使用して、このテキストをページングしていますUITextView。
UITextView私の問題は、使用するフォントサイズと書体によって異なるように見えるため、のパディングが計算を混乱させることです。
のコンテンツを囲むパディングを削除することは可能UITextViewですか?
iOS 7.0 では、contentInset トリックが機能しなくなっていることがわかりました。これは、iOS 7 でマージン/パディングを取り除くために使用したコードです。
これにより、テキストの左端がコンテナーの左端に移動します。
textView.textContainer.lineFragmentPadding = 0
これにより、テキストの上部がコンテナーの上部に揃えられます。
textView.textContainerInset = .zero
マージン/パディングを完全に削除するには、両方の行が必要です。
これは、iOS で最も愚かなバグの 1 つです。
ここで指定されたクラスUITextViewFixedは広く使用されており、通常は全体として最も合理的なソリューションです。
クラスは次のとおりです。
@IBDesignable class UITextViewFixed: UITextView {
override func layoutSubviews() {
super.layoutSubviews()
setup()
}
func setup() {
textContainerInset = UIEdgeInsets.zero
textContainer.lineFragmentPadding = 0
}
}
インスペクタで scrollEnabled をオフにすることを忘れないでください!
ソリューションはストーリーボードで正しく機能します
ソリューションは実行時に適切に機能します
一般に、ほとんどの場合、これで十分です。
その場でテキストビューの高さを変更している場合でも、UITextViewFixed通常は必要なすべてを行います。
(その場で高さを変更する一般的な例は、ユーザーの入力に応じて変更することです。)
これはAppleの壊れたUITextViewです...

ここにあるUITextViewFixed:

もちろん、あなたがしなければならないことに注意してください...
(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 = 0にUITextViewFixed。
しかし...信じられないかもしれませんが...それは現在の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 には UITextView よりも多くの利点があります。UILabel には、この Q&A ページに記載されている問題はありません。
実際、私たち全員が通常「あきらめ」て UITextView を使用する理由は、UILabel の操作が難しいためです。特に、 UILabel にpaddingを正しく追加するのは非常に困難です。
実際、ここでは UILabel にパディングを「最終的に」正しく追加する方法についての完全な議論があります: UILabelにスペース/パディングを追加します。場合によっては、動的な高さのセルで難しいレイアウトを行っている場合、UILabel を使用して難しい方法で行う方がよい場合があります。
この回避策は、iOS 3.0 がリリースされた 2009 年に作成されました。適用されなくなりました。
私はまったく同じ問題に遭遇し、最終的には使用する必要がありました
nameField.contentInset = UIEdgeInsetsMake(-4, -8, 0, 0);
nameField はUITextViewです。たまたま使っていたフォントは Helvetica 16 ポイントでした。これは、私が描いていた特定のフィールド サイズのカスタム ソリューションにすぎません。これにより、左側のオフセットが左側と同じ高さになり、上部のオフセットが描画されたボックスに必要な場所になります。
さらに、これUITextViewsはデフォルトのアラインメントを使用している場所にのみ適用されるようです。つまり、
nameField.textAlignment = NSTextAlignmentLeft;
たとえば、右に揃えると、右端にUIEdgeInsetsMakeはまったく影響がないように見えます。
少なくとも、.contentInset プロパティを使用すると、フィールドを「正しい」位置に配置し、.content をオフセットすることなく偏差に対応できますUITextViews。
iOS 5 ではUIEdgeInsetsMake(-8,-8,-8,-8);うまく動作するようです。
実際の余白はユーザーのフォントサイズ設定などで変わる可能性があるため、ハードコードされた値を含む回答は絶対に避けます。
これはuser1687195の回答で、変更せずに書かれていますtextContainer.lineFragmentPadding(ドキュメントではこれは意図した使用法ではないと述べているため)。
これは、iOS 7 以降でうまく機能します。
self.textView.textContainerInset = UIEdgeInsetsMake(
0,
-self.textView.textContainer.lineFragmentPadding,
0,
-self.textView.textContainer.lineFragmentPadding);
これは事実上同じ結果ですが、 lineFragmentPadding プロパティを誤用しないという点で少しすっきりしています。
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 をオフにすることを忘れないでください! そのソリューションは、実行時だけでなく、ストーリーボードでも適切に機能します。
これで、本当に完了です。
iOS 10 の場合、次の行は上下のパディングの削除に機能します。
captionTextView.textContainerInset = UIEdgeInsetsMake(0, 0, 0, 0)
はめ込みソリューションを実行すると、右側と下部にまだパディングがありました。また、テキストの配置が問題を引き起こしていました。私が見つけた唯一の確実な方法は、境界にクリップされた別のビュー内にテキスト ビューを配置することでした。
もう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);
}
HTML 文字列を設定し、下部のパディングを避けたい場合は、ブロック タグ、つまり、divおよびを使用していないことを確認してくださいp。
私の場合はこれが原因でした。ブロックタグの出現をタグなどに置き換えることで、簡単にテストできますspan。
textView のスクロールもテキストの位置に影響を与え、垂直方向の中央に配置されていないように見えます。スクロールを無効にし、上部のインセットを 0 に設定することで、テキストをビューの中央に配置することができました。
textView.scrollEnabled = NO;
textView.textContainerInset = UIEdgeInsetsMake(0, textView.textContainerInset.left, textView.textContainerInset.bottom, textView.textContainerInset.right);
何らかの理由でまだ理解できていませんが、入力を開始する前にカーソルはまだ中央に配置されていませんが、入力を開始するとすぐにテキストが中央に配置されます。
[firstNameTextField setContentVerticalAlignment:UIControlContentVerticalAlignmentCenter];