Alternative zu iOS7 UITextView contentize.height

78

Ich portiere eine der Apps von iOS 6.1 auf iOS 7. Ich verwende ein Layout, bei dem es eine gibt UITextView, die eine feste Breite hat, deren Höhe jedoch auf der Größe des Inhalts basiert. Für iOS 6.1 war es ausreichend, die Höhe des Inhalts zu überprüfen und als Rahmenhöhe für die Textansicht festzulegen, aber unter iOS 7 funktioniert dies nicht.

Wie kann ich dann eine UITextViewmit einer festen Breite, aber dynamischen Höhe basierend auf dem angezeigten Text erstellen ?

HINWEIS: Ich erstelle diese Ansichten aus Code, nicht mit Interface Builder.

Zoltan Varadi
quelle

Antworten:

180

Mit dem folgenden Code können Sie die Höhe Ihres UITextView abhängig von einer festen Breite ändern (es funktioniert unter iOS 7 und der vorherigen Version):

- (CGFloat)textViewHeightForAttributedText:(NSAttributedString *)text andWidth:(CGFloat)width
{
    UITextView *textView = [[UITextView alloc] init];
    [textView setAttributedText:text];
    CGSize size = [textView sizeThatFits:CGSizeMake(width, FLT_MAX)];
    return size.height;
}

Mit dieser Funktion nehmen Sie einen NSAttributedString und eine feste Breite, um die benötigte Höhe zurückzugeben.

Wenn Sie den Rahmen aus einem Text mit einer bestimmten Schriftart berechnen möchten, müssen Sie den folgenden Code verwenden:

- (CGSize)text:(NSString *)text sizeWithFont:(UIFont *)font constrainedToSize:(CGSize)size
{
    if (SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(@"7.0"))
    {
        CGRect frame = [text boundingRectWithSize:size
                                          options:(NSStringDrawingUsesLineFragmentOrigin | NSStringDrawingUsesFontLeading)
                                       attributes:@{NSFontAttributeName:font}
                                          context:nil];
        return frame.size;
    }
    else
    {
        return [text sizeWithFont:font constrainedToSize:size];
    }
}

Sie können dies SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TOin Ihrer prefix.pch-Datei in Ihrem Projekt wie folgt hinzufügen :

#define SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(v)  ([[[UIDevice currentDevice] systemVersion] compare:v options:NSNumericSearch] != NSOrderedAscending)

Sie können den vorherigen Test auch ersetzen SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(v)durch:

if ([text respondsToSelector:@selector(boundingRectWithSize:options:attributes:context:)])‌
Jordan Montel
quelle
Ich kann es dir erst nach 24 Stunden geben. Sei geduldig, es gehört dir :)
Zoltan Varadi
16
Vielleicht solltest du auf die Antworten verlinken, aus denen du sie genommen hast? stackoverflow.com/questions/18368567/…
andrew-caulfield
@ Jordan Montel, für eine andere Frage: Wenn ich eine feste Breite und Höhe habe, wie kann ich die beste Schriftgröße für eine zugewiesene Zeichenfolge finden? Ich habe das ähnliche Problem auf iOS7 (auf iOS6 kann ich das tun)
LiangWang
1
@ Jacky: Versuch und Irrtum; Erhöhen oder verringern Sie die Größe um 1, bis die berechnete Höhe zu groß ist. Oder machen Sie es Größe 1000 und passen Sie die Größe automatisch an.
Cœur
Diese Antwort ist bereits falsch. Versuchen Sie, viel Text in ein solches Textfeld einzugeben. Plötzlich falsche Größe? Zumindest NSStringDrawingUsesFontLeadingist extra
user2159978
42

Dies funktionierte für mich für iOS6 und 7:

CGSize textViewSize = [self.myTextView sizeThatFits:CGSizeMake(self.myTextView.frame.size.width, FLT_MAX)];
    self.myTextView.height = textViewSize.height;
Ana
quelle
Hallo, ja, es weckt mich ... Ich werde "txtviewHeight.frame.size.height" anstelle von "txtviewHeight.contentSize.height" verwendet
Mani
Warum wird die Objekthöhe für ein Objekt vom Typ "UITextView" nicht gefunden?
Hexark
@ HexarktextView.bounds.size.height
Benutzer
21

Verwendet in iOS7 UITextViewdas NSLayoutManagerLayout von Text:

// If YES, then the layout manager may perform glyph generation and layout for a given portion of the text, without having glyphs or layout for preceding portions.  The default is NO.  Turning this setting on will significantly alter which portions of the text will have glyph generation or layout performed when a given generation-causing method is invoked.  It also gives significant performance benefits, especially for large documents.
@property(NS_NONATOMIC_IOSONLY) BOOL allowsNonContiguousLayout;

deaktivieren allowsNonContiguousLayout, um zu beheben contentSize:

textView.layoutManager.allowsNonContiguousLayout = NO;
Nova
quelle
7
Ihre Antwort passt nicht zur Frage, aber zu meinem Problem. Also
stimme
Dadurch wird die Inhaltsgröße für mich nicht festgelegt. Das Scrollen ist deaktiviert.
Dvole
Dieser Code hat mein Problem gelöst, aber was bedeutet die generationsverursachende Methode für Ihren Kommentar?
Code Farmer
15

Verwenden Sie diese kleine Funktion

-(CGSize) getContentSize:(UITextView*) myTextView{
    return [myTextView sizeThatFits:CGSizeMake(myTextView.frame.size.width, FLT_MAX)];
}
Blake Hamilton
quelle
Funktioniert in iOS6 und iOS7 für mich. Vielen Dank!
Paul Brady
4

Meine endgültige Lösung basiert auf HotJards, enthält jedoch sowohl die oberen als auch die unteren Einfügungen des Textcontainers, anstatt 2 * fabs (textView.contentInset.top) zu verwenden:

- (CGFloat)textViewHeight:(UITextView *)textView
{
    return ceilf([textView.layoutManager usedRectForTextContainer:textView.textContainer].size.height +
                 textView.textContainerInset.top +
                 textView.textContainerInset.bottom);
}
xZenon
quelle
3

Mit dieser Methode gibt es einfachere Lösungen:

+(void)adjustTextViewHeightToContent:(UITextView *)textView;
{
    if([[UIDevice currentDevice].systemVersion floatValue] >= 7.0f){
        textView.height = [textView.layoutManager usedRectForTextContainer:textView.textContainer].size.height+2*fabs(textView.contentInset.top);
    }else{
        textView.height = textView.contentSize.height;
    }
}

UPD : funktioniert nur zum Anzeigen von Text (isEditable = NO)

HotJard
quelle
Es scheint, als ob Ihre Lösung nicht funktioniert. Wenn die Textansicht zur zweiten Zeilenmethode wechselt, usedRectForTextContainerwird dieselbe Höhe zurückgegeben.
Valerii Pavlov
Oh, vielleicht verwende ich es nur zum Anzeigen von Text
HotJard
1
   _textView.textContainerInset = UIEdgeInsetsZero;
   _textView.textContainer.lineFragmentPadding = 0;

Vergessen Sie nur nicht das lineFragmentPadding

ChaoWang
quelle
0

einfache Lösung - textView.isScrollEnabled = false funktioniert perfekt, wenn Sie sich in einer anderen Bildlaufansicht oder in einer tableView-Zelle befindenUITableViewAutomaticDimension

Kirow
quelle
0

@ Anas, @Blake Hamilton-Lösung in swift .

var contentHeight: CGFloat = textView.sizeThatFits(textView.frame.size).height

Das Gute für mich war, dass dies auch das Richtige zurückgibt contentSize, wenn isScrollEnableauf false gesetzt ist. Bei der Einstellung false wurde die Rahmengröße der Textansicht anstelle der Inhaltsgröße zurückgegeben.

Baran Emre
quelle