Come dimensionare un UITextView al suo contenuto?


521

C'è un buon modo per adattare le dimensioni di un UITextViewper adeguarsi al suo contenuto? Ad esempio, ho un oggetto UITextViewche contiene una riga di testo:

"Hello world"

Aggiungo quindi un'altra riga di testo:

"Goodbye world"

C'è un buon modo in Cocoa Touch per ottenere il rectche conterrà tutte le linee nella vista testo in modo da poter regolare la vista padre di conseguenza?

Come altro esempio, guarda il campo delle note per gli eventi nell'applicazione Calendario - nota come la cella (e la UITextViewsua contiene) si espande per contenere tutte le righe di testo nella stringa delle note.


prendi in considerazione l'aggiornamento della risposta corretta, poiché quella accettata porta a calcoli non necessari, ora c'è una proprietà contentSize per questo problema.
Juan Boero,

Risposte:


610

Funziona con iOS 6.1 e iOS 7:

- (void)textViewDidChange:(UITextView *)textView
{
    CGFloat fixedWidth = textView.frame.size.width;
    CGSize newSize = [textView sizeThatFits:CGSizeMake(fixedWidth, MAXFLOAT)];
    CGRect newFrame = textView.frame;
    newFrame.size = CGSizeMake(fmaxf(newSize.width, fixedWidth), newSize.height);
    textView.frame = newFrame;
}

O in Swift (funziona con Swift 4.1 in iOS 11)

let fixedWidth = textView.frame.size.width
let newSize = textView.sizeThatFits(CGSize(width: fixedWidth, height: CGFloat.greatestFiniteMagnitude))
textView.frame.size = CGSize(width: max(newSize.width, fixedWidth), height: newSize.height)

Se desideri il supporto per iOS 6.1, dovresti anche:

textview.scrollEnabled = NO;

1
Testato su iOS 7 per ridimensionare un UITextView in un UITableViewCell. Funziona davvero alla grande. Questa è l'unica risposta che alla fine ha funzionato per me. Grazie!
Alex

37
Mi serviva textview.scrollEnabled = NO;per evitare che il testo venisse tagliato anche in iOS 7.
Brian

19
Consiglio di usare la CGFLOAT_MAXmacro invece di MAXFLOAT. Corretto su entrambe le piattaforme a 32/64 bit.
Eonil,

3
Colui che deve affrontare piccole fluttuazioni prima di entrare nella riga successiva aggiunge questo `NSRange bottom = NSMakeRange (textView.text.length -1, 1); [textView scrollRangeToVisible: bottom]; `
ajay_nasa

4
Perché ci sono due chiamate separate per sizeThatFits (...) nella versione Swift? Qual è la prima linea per?
Nekonari,

576

Questo non funziona più su iOS 7 o versioni successive

In realtà esiste un modo molto semplice per eseguire il ridimensionamento della UITextViewcorretta altezza del contenuto. Si può fare usando il UITextView contentSize.

CGRect frame = _textView.frame;
frame.size.height = _textView.contentSize.height;
_textView.frame = frame;

Una cosa da notare è che la corretta contentSizeè disponibile solo dopo il UITextViewè stato aggiunto alla vista con addSubview. Prima di ciò è uguale aframe.size

Questo non funzionerà se il layout automatico è attivo. Con il layout automatico, l'approccio generale è utilizzare il sizeThatFitsmetodo e aggiornare il constantvalore su un vincolo di altezza.

CGSize sizeThatShouldFitTheContent = [_textView sizeThatFits:_textView.frame.size];
heightConstraint.constant = sizeThatShouldFitTheContent.height;

heightConstraint è un vincolo di layout che in genere si configura tramite un IBOutlet collegando la proprietà al vincolo di altezza creato in uno storyboard.


Solo per aggiungere a questa straordinaria risposta, 2014, se tu:

[self.textView sizeToFit];

c'è una differenza di comportamento solo con iPhone6 ​​+ :

inserisci qui la descrizione dell'immagine

Solo con il 6+ (non i 5 o 6) aggiunge "un'altra riga vuota" a UITextView. La "soluzione RL" risolve perfettamente:

CGRect _f = self.mainPostText.frame;
_f.size.height = self.mainPostText.contentSize.height;
self.mainPostText.frame = _f;

Risolve il problema "extra line" su 6+.


2
Mi hai salvato la giornata. Stavo lottando con l'estensione della funzione di classe auto-calcolatrice dimenticando questo. Grazie.
Lukasz,

4
Aha! Stavo impostando l'altezza della vista di testo e quindi regolando l'altezza della vista di contenimento. Apparentemente, quando l'ho fatto, l'altezza della vista del testo veniva regolata. L'impostazione dell'altezza di visualizzazione contenuta fa prima funzionare le cose come previsto (o, meglio, sperato).
Hot Licks,

11
L'uso di [_textView sizeToFit] aggiorna la proprietà contentSize, eliminando in anticipo il requisito di aggiungerlo a scrollView.
Rodrigo,

1
Se si utilizza il completamento automatico, chiamare layoutIfNeededla superview. Quindi puoi prendere l'altezza da contentSize.
Phatmann,

4
Si tratta di ridimensionare il contenitore esterno però. Tale comportamento è cambiato in iOS 7. Nella domanda collegata mostrerò dove aggiungere sizeToFit e layoutIfNeeded.
Henrik Erlandsson,

93

Per fare un dimensionamento dinamico UITextViewall'interno di a UITableViewCell, ho scoperto che la seguente combinazione funziona in Xcode 6 con iOS 8 SDK:

  • Aggiungi a UITextViewa UITableViewCelle vincola ai lati
  • Impostare la UITextView's scrollEnabledproprietà NO. Con lo scorrimento abilitato, il frame del UITextViewè indipendente dalla sua dimensione del contenuto, ma con lo scroll disabilitato, c'è una relazione tra i due.
  • Se la tua tabella utilizza l'altezza di riga predefinita originale di 44, calcolerà automaticamente le altezze di riga, ma se hai modificato l'altezza di riga predefinita in qualcos'altro, potrebbe essere necessario attivare manualmente il calcolo automatico delle altezze di riga in viewDidLoad:

    tableView.estimatedRowHeight = 150;
    tableView.rowHeight = UITableViewAutomaticDimension;

Per le dimensioni dinamiche di sola lettura UITextView, tutto qui. Se stai consentendo agli utenti di modificare il testo nel tuo UITextView, devi anche:

  • Implementare il textViewDidChange:metodo del UITextViewDelegateprotocollo e dire tableViewa ridipingere se stesso ogni volta che il testo viene modificato:

    - (void)textViewDidChange:(UITextView *)textView;
    {
        [tableView beginUpdates];
        [tableView endUpdates];
    }
  • E non dimenticare di impostare il UITextViewdelegato da qualche parte, dentro Storyboardo dentrotableView:cellForRowAtIndexPath:


La migliore risposta per me Ha funzionato perfettamente e UITableViewAutomaticDimension è stato aggiunto in iOS 5, quindi è retrocompatibile.
smmelzer,

4
Non ha funzionato abbastanza per me. Il metodo textViewDidChange fa rimbalzare la mia vista tabella ogni volta che digito un carattere. Quello che suggerisco è che invece di utilizzare quel metodo, nel metodo tableView: cellForRowAtIndexPath, per la riga con la visualizzazione di testo su di essa, se ci si trova in una modalità di sola lettura impostata .scrollEnabled su NO e se ci si trova in una serie di viste di modifica scorrimento abilitato su SÌ. In questo modo quando lo visualizzi mostrerà sempre il testo completo e quando lo modifichi inizierà con il testo completo e man mano che aggiungi altro testo rimarranno le stesse dimensioni con il testo precedente che scorre dall'alto
SimonTheDiver

3
inoltre ho aggiunto un vincolo> = height alla visualizzazione di testo poiché un campo di testo vuoto non aveva altezza e non è stato possibile toccarlo per iniziare la modifica.
SimonTheDiver,

Soluzione eccellente Per me, tableView.rowHeight = UITableViewAutomaticDimensionnon era necessario.
Christopher Pickslay,

Grazie ancora Brett Donald! Ho dimenticato come fare e ho trovato la tua risposta ancora una volta oltre 1 anno dopo 😀.
Eric Conner,

76

Soluzione di lavoro molto semplice con codice e storyboard entrambi.

Per codice

textView.scrollEnabled = false

Di Storyboard

Deseleziona Abilita scorrimento

inserisci qui la descrizione dell'immagine

Non c'è bisogno di fare nulla a parte questo.


5
Questa risposta è corretta In StoryBoard hai il TextView AutoSize proprio come un UILabel. Tutto quello che dobbiamo fare è impostare scrollEnabled = false.
pnavk,

4
In sostanza, questo è corretto: se stai usando i vincoli di Autolayout e chiudi lo scorrimento, tutto funziona.
Dan Rosenstark,

2
Molte grazie. Era così semplice, basta disabilitare lo scorrimento nello storyboard o nel codice, sarà come UILabel con le righe 0.
samir105

@Mansuu .... Questa non è una soluzione garantita, in quanto ci sono cose che puoi fare per sovrascrivere la dimensione del contenuto intrinseco e se cambi il testo dopo che la vista è stata predisposta non si aggiornerà a meno che tu non lo imposti anche su. Ma queste cose rimangono vere anche per l'impostazione di numberOfLines = 0 su un campo di testo. Se questo non funziona, probabilmente hai altri vincoli che implicitamente imposteranno un'altezza.
Jake T.

2
@iOS se si aggiunge un vincolo di altezza, ridurre la priorità dei vincoli, altrimenti non funzionerà.
Alok

61

Veloce:

textView.sizeToFit()

14
Inoltre, ho scoperto che avevo bisogno di impostare lo scorrimento abilitato su false per farlo funzionare. textView.scrollEnabled = false
tmarkiewicz,

1
Dovresti ricordare di chiamare textView.layoutIfNeeded () dopo textView.sizeToFit ()
Daniel Kuta,

5
@tmarkiewicz Funziona quando il testo si adatta allo schermo del tuo dispositivo, ma sarà un problema quando il tuo testo è più grande dello spazio che c'è sullo schermo. Non potrai scorrere per vedere il resto del testo.
Francisco Romero,

Questa è la risposta !!! Non c'è bisogno di soluzioni più complicate !!! @FranciscoRomero Perché non mettere la visualizzazione di testo in una cella di tabella o in una cella della vista di raccolta, puoi sempre scorrere la vista della tabella o della raccolta ...
Ben Smith,

23

Nella mia (limitata) esperienza,

- (CGSize)sizeWithFont:(UIFont *)font forWidth:(CGFloat)width lineBreakMode:(UILineBreakMode)lineBreakMode

non rispetta i caratteri di nuova riga, quindi puoi finire con molto più corto di CGSizequanto effettivamente richiesto.

- (CGSize)sizeWithFont:(UIFont *)font constrainedToSize:(CGSize)size

sembra rispettare le nuove linee.

Inoltre, il testo non viene effettivamente visualizzato nella parte superiore di UITextView. Nel mio codice, ho impostato la nuova altezza di UITextViewa 24 pixel più grande dell'altezza restituita dai sizeOfFontmetodi.


3
Questo ha le dimensioni come se disegnasse il testo su un UILabel. Se imposti quella dimensione sul frame di uitextview, avrai comunque bisogno di uno scorrimento.
Kevlar,

22

In iOS6, puoi controllare la contentSizeproprietà di UITextView subito dopo aver impostato il testo. In iOS7, questo non funzionerà più. Se si desidera ripristinare questo comportamento per iOS7, inserire il seguente codice in una sottoclasse di UITextView.

- (void)setText:(NSString *)text
{
    [super setText:text];

    if (NSFoundationVersionNumber > NSFoundationVersionNumber_iOS_6_1) {
        CGRect rect = [self.textContainer.layoutManager usedRectForTextContainer:self.textContainer];
        UIEdgeInsets inset = self.textContainerInset;
        self.contentSize = UIEdgeInsetsInsetRect(rect, inset).size;
    }
}

2
Dove posso leggere di più al riguardo? Sono totalmente perso per quanto riguarda il comportamento apparentemente nuovo in iOS 7 in merito.
Stian Høiland,

Qual è il significato della dimensione variabile CGS?
Tchelow,

Ho rimosso le dimensioni, non doveva essere lì.
Phatmann,

18

Pubblicherò la soluzione giusta in fondo alla pagina nel caso qualcuno sia coraggioso (o abbastanza disperato) da leggere fino a questo punto.

Ecco il repository gitHub per coloro che non vogliono leggere tutto quel testo: resizableTextView

Funziona con iOs7 (e credo che funzionerà con iOs8) e con autolayout. Non hai bisogno di numeri magici, disabilita layout e cose del genere. Soluzione breve ed elegante.

Penso che tutto il codice relativo ai vincoli dovrebbe andare al updateConstraintsmetodo. Quindi, facciamo il nostro ResizableTextView.

Il primo problema che incontriamo qui è che non conosco le dimensioni reali del contenuto prima del viewDidLoadmetodo. Possiamo prendere una strada lunga e buggy e calcolarla in base alla dimensione del carattere, alle interruzioni di riga, ecc. Ma abbiamo bisogno di una soluzione solida, quindi faremo:

CGSize contentSize = [self sizeThatFits:CGSizeMake(self.frame.size.width, FLT_MAX)];

Quindi ora conosciamo il contenuto reale Dimensione indipendentemente da dove siamo: prima o dopo viewDidLoad. Ora aggiungi un vincolo di altezza su textView (tramite storyboard o codice, non importa come). Adatteremo quel valore con il nostro contentSize.height:

[self.constraints enumerateObjectsUsingBlock:^(NSLayoutConstraint *constraint, NSUInteger idx, BOOL *stop) {
    if (constraint.firstAttribute == NSLayoutAttributeHeight) {
        constraint.constant = contentSize.height;
        *stop = YES;
    }
}];

L'ultima cosa da fare è dirlo alla superclasse updateConstraints.

[super updateConstraints];

Ora la nostra classe si presenta come:

ResizableTextView.m

- (void) updateConstraints {
    CGSize contentSize = [self sizeThatFits:CGSizeMake(self.frame.size.width, FLT_MAX)];

    [self.constraints enumerateObjectsUsingBlock:^(NSLayoutConstraint *constraint, NSUInteger idx, BOOL *stop) {
        if (constraint.firstAttribute == NSLayoutAttributeHeight) {
            constraint.constant = contentSize.height;
            *stop = YES;
        }
    }];

    [super updateConstraints];
}

Bello e pulito, giusto? E non devi occuparti di quel codice nei tuoi controller !

Ma aspetta! SÌ ANIMAZIONE!

Puoi facilmente animare le modifiche per textViewallungare senza intoppi. Ecco un esempio:

    [self.view layoutIfNeeded];
    // do your own text change here.
    self.infoTextView.text = [NSString stringWithFormat:@"%@, %@", self.infoTextView.text, self.infoTextView.text];
    [self.infoTextView setNeedsUpdateConstraints];
    [self.infoTextView updateConstraintsIfNeeded];
    [UIView animateWithDuration:1 delay:0 options:UIViewAnimationOptionLayoutSubviews animations:^{
        [self.view layoutIfNeeded];
    } completion:nil];

4
Usa CGFLOAT_MAX, no FLT_MAX.
Rob Mayoff,

Vorrei poterti dare più di un voto positivo per questa fantastica soluzione !!
Scooter

13

Hai provato [textView sizeThatFits:textView.bounds] ?

Modifica: sizeThatFits restituisce la dimensione ma in realtà non ridimensiona il componente. Non sono sicuro se è quello che vuoi, o se [textView sizeToFit]è più quello che stavi cercando. In entrambi i casi, non so se si adatterà perfettamente al contenuto come desideri, ma è la prima cosa da provare.


2
sizetofit salva la giornata
michaelsnowden

9

Un altro metodo è trovare la dimensione che una particolare stringa prenderà usando il NSStringmetodo:

-(CGSize)sizeWithFont:(UIFont *)font constrainedToSize:(CGSize)size

Ciò restituisce la dimensione del rettangolo che si adatta alla stringa specificata con il carattere specificato. Passa in una dimensione con la larghezza desiderata e un'altezza massima, quindi puoi guardare l'altezza restituita per adattarla al testo. Esiste una versione che consente di specificare anche la modalità di interruzione di riga.

È quindi possibile utilizzare la dimensione restituita per modificare la dimensione della vista in modo che si adatti.


8

Se non hai il UITextViewpratico (ad esempio, stai dimensionando le celle della vista tabella), dovrai calcolare le dimensioni misurando la stringa, quindi tenendo conto degli 8 pt di riempimento su ciascun lato di a UITextView. Ad esempio, se conosci la larghezza desiderata della vista del testo e vuoi capire l'altezza corrispondente:

NSString * string = ...;
CGFloat textViewWidth = ...;
UIFont * font = ...;

CGSize size = CGSizeMake(textViewWidth - 8 - 8, 100000);
size.height = [string sizeWithFont:font constrainedToSize:size].height + 8 + 8;

Qui, ogni 8 rappresenta uno dei quattro bordi imbottiti e 100000 serve solo come dimensione massima molto grande.

In pratica, potresti voler aggiungere un extra font.leadingall'altezza; questo aggiunge una riga vuota sotto il testo, che potrebbe apparire migliore se ci sono controlli visivamente pesanti direttamente sotto la vista del testo.


risultato perfetto in iOS 8.1
Logica

L'imbottitura è stata la chiave per me
thibaut noah il

8

Possiamo farlo per vincoli.

  1. Imposta i vincoli di altezza per UITextView. inserisci qui la descrizione dell'immagine

2.Crea IBOutlet per quel vincolo di altezza.

 @property (weak, nonatomic) IBOutlet NSLayoutConstraint *txtheightconstraints;

3.non dimenticare di impostare il delegato per la visualizzazione del testo.

4.

-(void)textViewDidChange:(UITextView *)textView
{
    CGFloat fixedWidth = textView.frame.size.width;
    CGSize newSize = [textView sizeThatFits:CGSizeMake(fixedWidth, MAXFLOAT)];
    CGRect newFrame = textView.frame;
    newFrame.size = CGSizeMake(fmaxf(newSize.width, fixedWidth), newSize.height);
    NSLog(@"this is updating height%@",NSStringFromCGSize(newFrame.size));
    [UIView animateWithDuration:0.2 animations:^{
                  _txtheightconstraints.constant=newFrame.size.height;
    }];

}

quindi aggiorna il tuo vincolo in questo modo :)


questo è un soprannome FANTASTICO!
Fattie,

L'impostazione della costante deve essere seguita da [textView layoutIfNeeded]; nel blocco animazione. (Le animazioni di autolayout fanno così.)
Will Larche,

7

Sono sufficienti le seguenti cose:

  1. Ricorda solo di impostare lo scorrimento abilitato su NO per il tuo UITextView:

inserisci qui la descrizione dell'immagine

  1. Impostare correttamente i vincoli di layout automatico.

Puoi persino usare UITableViewAutomaticDimension.


6

In combinazione con la risposta di Mike McMaster, potresti voler fare qualcosa del tipo:

[myTextView setDelegate: self];

...

- (void)textViewDidChange:(UITextView *)textView {
  if (myTextView == textView) {
     // it changed.  Do resizing here.
  }
}

6

Ho scoperto un modo per ridimensionare l'altezza di un campo di testo in base al testo al suo interno e disporre anche un'etichetta sotto di essa in base all'altezza del campo di testo! Ecco il codice

UITextView *_textView = [[UITextView alloc] initWithFrame:CGRectMake(10, 10, 300, 10)];
NSString *str = @"This is a test text view to check the auto increment of height of a text view. This is only a test. The real data is something different.";
_textView.text = str;

[self.view addSubview:_textView];
CGRect frame = _textView.frame;
frame.size.height = _textView.contentSize.height;
_textView.frame = frame;

UILabel *lbl = [[UILabel alloc] initWithFrame:CGRectMake(10, 5 + frame.origin.y + frame.size.height, 300, 20)];
lbl.text = @"Hello!";
[self.view addSubview:lbl];

Qui il '5' in coordinata y di UILabel è il divario che voglio tra textView ed Label.
Dheeraj,

6

I ragazzi che usano il layout automatico e il tuo sizetofit non funzionano, quindi controlla una volta il tuo limite di larghezza. Se hai perso il vincolo di larghezza, l'altezza sarà precisa.

Non è necessario utilizzare altre API. solo una riga risolverebbe tutto il problema.

[_textView sizeToFit];

Qui, mi occupavo solo dell'altezza, mantenendo la larghezza fissa e avevo perso il vincolo di larghezza del mio TextView nello storyboard.

E questo era per mostrare il contenuto dinamico dei servizi.

Spero che questo possa aiutare ..


6

A partire da iOS 8, è possibile utilizzare le funzionalità di layout automatico di un UITableView per ridimensionare automaticamente un UITextView senza alcun codice personalizzato. Ho messo un progetto in github che lo dimostra in azione, ma ecco la chiave:

  1. UITextView deve avere lo scorrimento disabilitato, cosa che puoi fare a livello di codice o tramite il builder di interfacce. Non verrà ridimensionato se lo scorrimento è abilitato perché lo scorrimento consente di visualizzare il contenuto più grande.
  2. In viewDidLoad per UITableViewController, è necessario impostare un valore per stimatoRowHeight e quindi impostare rowHeightsu UITableViewAutomaticDimension.

- (void)viewDidLoad {
    [super viewDidLoad];
    self.tableView.estimatedRowHeight = self.tableView.rowHeight;
    self.tableView.rowHeight = UITableViewAutomaticDimension;
}
  1. La destinazione di distribuzione del progetto deve essere iOS 8 o successiva.

1
Questo tipo di risposte sono scoraggiate. È necessario pubblicare qui il codice pertinente.
Antzi,

5

Ho esaminato tutte le risposte e tutte mantengono una larghezza fissa e regola solo l'altezza. Se si desidera regolare anche la larghezza, è possibile utilizzare facilmente questo metodo:

quindi, quando si configura la visualizzazione del testo, impostare lo scorrimento disabilitato

textView.isScrollEnabled = false

e quindi nel metodo delegato func textViewDidChange(_ textView: UITextView)aggiungere questo codice:

func textViewDidChange(_ textView: UITextView) {
    let newSize = textView.sizeThatFits(CGSize(width: CGFloat.greatestFiniteMagnitude, height: CGFloat.greatestFiniteMagnitude))
    textView.frame = CGRect(origin: textView.frame.origin, size: newSize)
}

Uscite:

inserisci qui la descrizione dell'immagine

inserisci qui la descrizione dell'immagine


il metodo delegato non viene chiamato @Peter Stajger
Mansuu ....

4

Questo ha funzionato bene quando avevo bisogno di rendere il testo UITextViewadatto a un'area specifica:

// Il testo deve già essere aggiunto alla sottoview, altrimenti contentviewsize sarà errato.

- (void) reduceFontToFit: (UITextView *) tv {
    UIFont * font = tv.font;
    double pointSize = font.pointSize;

    while (tv.contentSize.height> tv.frame.size.height && pointSize> 7.0) {
        pointSize - = 1.0;
        UIFont * newFont = [UIFont fontWithName: font.fontName size: pointSize];
        tv.font = newFont;
    }
    if (pointSize! = font.pointSize)
        NSLog (@ "font fino a% .1f da% .1f", pointSize, tv.font.pointSize);
}

4

ecco la versione rapida di @jhibberd

    let cell:MsgTableViewCell! = self.tableView.dequeueReusableCellWithIdentifier("MsgTableViewCell", forIndexPath: indexPath) as? MsgTableViewCell
    cell.msgText.text = self.items[indexPath.row]
    var fixedWidth:CGFloat = cell.msgText.frame.size.width
    var size:CGSize = CGSize(width: fixedWidth,height: CGFloat.max)
    var newSize:CGSize = cell.msgText.sizeThatFits(size)
    var newFrame:CGRect = cell.msgText.frame;
    newFrame.size = CGSizeMake(CGFloat(fmaxf(Float(newSize.width), Float(fixedWidth))), newSize.height);
    cell.msgText.frame = newFrame
    cell.msgText.frame.size = newSize        
    return cell

6
La domanda è davvero indipendente dal linguaggio. È davvero necessario tornare indietro e scrivere porte rapide per tutte le risposte alle domande relative a UIKit? Sembra che sia una conversazione rumorosa.
eremzeit

il problema che la maggior parte di queste domande non ha un linguaggio di programmazione specifico, quindi lo troverai in google anche se cerchi un linguaggio rapido
Fareed Alnamrouti,

4

disabilita lo scorrimento

aggiungi constaints

e aggiungi il tuo testo

[yourTextView setText:@"your text"];
[yourTextView layoutIfNeeded];

se usi UIScrollViewdovresti aggiungere anche questo;

[yourScrollView layoutIfNeeded];

-(void)viewDidAppear:(BOOL)animated{
    CGRect contentRect = CGRectZero;

    for (UIView *view in self.yourScrollView.subviews) {
         contentRect = CGRectUnion(contentRect, view.frame);
    }
    self.yourScrollView.contentSize = contentRect.size;
}

3

Per iOS 7.0, invece di impostare l'uso frame.size.heightsu contentSize.height(che al momento non fa nulla) [textView sizeToFit].

Vedere questa domanda .


2

L'uso di UITextViewDelegate è il modo più semplice:

func textViewDidChange(_ textView: UITextView) {
    textView.sizeToFit()
    textviewHeight.constant = textView.contentSize.height
}

1

Spero che sia di aiuto:

- (void)textViewDidChange:(UITextView *)textView {
  CGSize textSize = textview.contentSize;
  if (textSize != textView.frame.size)
      textView.frame.size = textSize;
}

Questo non funziona! Causa un errore: "lvalue richiesto come operando di sinistra dell'assegnazione"
leviathan

Puoi solo assegnare a textView.frame.
jweyrich,

1

se qualcuno arriva qui, questa soluzione funziona per me, 1 "Ronnie Liew" +4 "user63934" (Il mio testo arriva dal servizio web): nota il 1000 (niente può essere così grande "nel mio caso")

UIFont *fontNormal = [UIFont fontWithName:FONTNAME size:FONTSIZE];

NSString *dealDescription = [client objectForKey:@"description"];

//4
CGSize textSize = [dealDescription sizeWithFont:fontNormal constrainedToSize:CGSizeMake(containerUIView.frame.size.width, 1000)];

CGRect dealDescRect = CGRectMake(10, 300, containerUIView.frame.size.width, textSize.height);

UITextView *dealDesc = [[[UITextView alloc] initWithFrame:dealDescRect] autorelease];

dealDesc.text = dealDescription;
//add the subview to the container
[containerUIView addSubview:dealDesc];

//1) after adding the view
CGRect frame = dealDesc.frame;
frame.size.height = dealDesc.contentSize.height;
dealDesc.frame = frame;

E questo è ... Saluti


1

Il modo migliore che ho scoperto per ridimensionare l'altezza di UITextView in base alla dimensione del testo.

CGSize textViewSize = [YOURTEXTVIEW.text sizeWithFont:[UIFont fontWithName:@"SAMPLE_FONT" size:14.0]
                       constrainedToSize:CGSizeMake(YOURTEXTVIEW.frame.size.width, FLT_MAX)];

oppure puoi UTILIZZARE

CGSize textViewSize = [YOURTEXTVIEW.text sizeWithFont:[UIFont fontWithName:@"SAMPLE_FONT" size:14.0]
                       constrainedToSize:CGSizeMake(YOURTEXTVIEW.frame.size.width, FLT_MAX) lineBreakMode:NSLineBreakByTruncatingTail];

1

Per coloro che desiderano che la visualizzazione di testo si sposti effettivamente verso l'alto e mantenga la posizione di fondo

CGRect frame = textView.frame;
frame.size.height = textView.contentSize.height;

if(frame.size.height > textView.frame.size.height){
    CGFloat diff = frame.size.height - textView.frame.size.height;
    textView.frame = CGRectMake(0, textView.frame.origin.y - diff, textView.frame.size.width, frame.size.height);
}
else if(frame.size.height < textView.frame.size.height){
    CGFloat diff = textView.frame.size.height - frame.size.height;
    textView.frame = CGRectMake(0, textView.frame.origin.y + diff, textView.frame.size.width, frame.size.height);
}

1

L'unico codice che funzionerà è quello che utilizza 'SizeToFit' come nella risposta jhibberd sopra ma in realtà non si raccoglierà a meno che non lo si chiami in ViewDidAppear o lo si colleghi all'evento modificato di testo UITextView.


1

Sulla base della risposta di Nikita Took sono arrivato alla seguente soluzione in Swift che funziona su iOS 8 con autolayout:

    descriptionTxt.scrollEnabled = false
    descriptionTxt.text = yourText

    var contentSize = descriptionTxt.sizeThatFits(CGSizeMake(descriptionTxt.frame.size.width, CGFloat.max))
    for c in descriptionTxt.constraints() {
        if c.isKindOfClass(NSLayoutConstraint) {
            var constraint = c as! NSLayoutConstraint
            if constraint.firstAttribute == NSLayoutAttribute.Height {
                constraint.constant = contentSize.height
                break
            }
        }
    }

1

Risposta rapida: il codice seguente calcola l'altezza di textView.

                let maximumLabelSize = CGSize(width: Double(textView.frame.size.width-100.0), height: DBL_MAX)
                let options = NSStringDrawingOptions.TruncatesLastVisibleLine | NSStringDrawingOptions.UsesLineFragmentOrigin
                let attribute = [NSFontAttributeName: textView.font!]
                let str = NSString(string: message)
                let labelBounds = str.boundingRectWithSize(maximumLabelSize,
                    options: NSStringDrawingOptions.UsesLineFragmentOrigin,
                    attributes: attribute,
                    context: nil)
                let myTextHeight = CGFloat(ceilf(Float(labelBounds.height)))

Ora puoi impostare l'altezza di textView su myTextHeight


Ci dispiace, cosa significa: let attribute = [NSFontAttributeName: textView.text.font!] questo codice Swift è davvero senza errori?) Intendi dire let attribute = [NSFontAttributeName: textView.font!]
Massmaker,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.