2009-04-13 7 views
70

Sto cercando di creare un UITableView con filari di altezza variabile, come spiegato nella risposta alla this questionCome determinare l'altezza di UIWebView in base al contenuto, all'interno di UITableView con altezza variabile?

Il mio problema è ogni cella contiene un UIWebView con diversi contenuti (caricato staticamente) Io non riesco a capire come calcolare la corretta altezza in base al contenuto. C'è un modo per fare questo? Ho provato cose come questa:

(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath { 
     WebViewCell *cell = (WebViewCell*)[self tableView:tableView cellForRowAtIndexPath:indexPath]; 
     [cell setNeedsLayout]; 
     [cell layoutIfNeeded]; 
     return cell.bounds.size.height; 
    } 

le cellule stesse vengono caricati da un pennino, che è semplicemente un UITableViewCell contenente un UIWebView. (Andrebbe anche bene se le celle si aggiustassero al massimo del contenuto html, sebbene l'altezza variabile sarebbe più bella).

+0

Hai mai capito come si fa? Le risposte sottostanti sembrano farti aumentare l'altezza, ma non prima di averne bisogno. Come si può calcolare l'altezza per heightForRowAtIndexPath è necessario fare affidamento su una chiamata callback (delegato webview) in webViewDidFinishLoad? – pbx

+0

Ciao, allora finalmente come si determina l'altezza della webview Sto avendo lo stesso problema ... –

+0

Chiunque ha una soluzione ???? Ancora non riesco a capirlo ... – mikemike396

risposta

76

Questo codice è probabilmente troppo lento per l'utilizzo della vista tabella, ma fa il trucco. Non sembra che ci sia un'alternativa, dato che UIWebView non offre accesso diretto al DOM.

In un controller di vista viewDidLoad carico un po 'di codice HTML in una webview e quando il caricamento è terminato, esegui qualche javascript per restituire l'altezza dell'elemento.

- (void)viewDidLoad 
{ 
    [super viewDidLoad]; 
    webview.delegate = self; 
    [webview loadHTMLString:@"<div id='foo' style='background: red'>The quick brown fox jumped over the lazy dog.</div>" baseURL:nil]; 
} 

- (void)webViewDidFinishLoad:(UIWebView *)webView 
{ 
    NSString *output = [webview stringByEvaluatingJavaScriptFromString:@"document.getElementById(\"foo\").offsetHeight;"]; 
    NSLog(@"height: %@", output); 
} 
+0

Sembra che possa essere fatto funzionare, tuttavia ho provato questo nella visualizzazione tabella e restituisce una stringa vuota (suppongo che la webview non abbia completato il caricamento). Sto pensando di poterlo precomputare magari con una webview offscreen e memorizzare i risultati per il tableview. – frankodwyer

+0

Stai misurando l'altezza nel webViewDidFinishLoad? Questo è il callback delegato che indica che il caricamento è completo. Non dovrebbe restituire una stringa vuota. – duncanwilcox

+0

Questo è quasi esattamente quello che faccio. Anche se sto avendo un problema con il fatto che la webview non può restituire le sue dimensioni fino a quando non ha completato il caricamento, che potrebbe non avere quando la tabella ha bisogno di conoscere le sue dimensioni. Qualcuno ha un'idea di come risolvere questo? –

28

Sono stato molto contento di trovare le vostre risposte, il trucco javascript ha funzionato bene per me.

Tuttavia, volevo dire che c'è anche il "sizeThatFits:" Metodo:

CGSize goodSize = [webView sizeThatFits:CGSizeMake(anyWidth,anyHeigth)]; 

Dobbiamo impostare una dimensione preferita diverso da zero, ma a parte questo, di solito funziona sempre!

In genere, poiché con UIWebViews, sembra funzionare solo sul secondo caricamento (utilizzo il metodo "loadHTMLString:", e sì chiamo "sizeThatFits:" dal metodo delegato "didFinishLoad:").

Quindi, è per questo che sono stato molto felice di trovare la soluzione che funziona in ogni caso.

+1

+1 questo merita qualche importante upvoting! – mvds

+0

Non riesco a farlo funzionare su iOS 4.2 – Shade

+0

@Shade: vedere la mia risposta su come farlo funzionare sulle versioni iOS più recenti. –

6

Questo sembra funzionare. Per adesso.

- (void)webViewDidFinishLoad:(UIWebView *)webView 
{ 
    CGFloat webViewHeight = 0.0f; 
    if (self.subviews.count > 0) { 
     UIView *scrollerView = [self.subviews objectAtIndex:0]; 
     if (scrollerView.subviews.count > 0) { 
      UIView *webDocView = scrollerView.subviews.lastObject; 
      if ([webDocView isKindOfClass:[NSClassFromString(@"UIWebDocumentView") class]]) 
       webViewHeight = webDocView.frame.size.height; 
     } 
    } 
} 

Dovrebbe restituire in modo sicuro 0 se non riesce.

+3

Come è meglio di: [webview stringByEvaluatingJavaScriptFromString: @ "document.getElementById (\" foo \ "). OffsetHeight;"] ;? Il problema è che la webview non può restituire le sue dimensioni fino a quando non ha completato il caricamento, che potrebbe non avere quando la tabella ha bisogno di conoscere le sue dimensioni. –

3

Se hai valori errati con sizeThatFits la prima volta ma non dopo, ecco una possibile causa che ho riscontrato: un bug con CSS esterno. Sembra che webViewDidFinisLoad venga chiamato a breve, prima che i CSS esterni vengano recuperati e il documento Web sia completamente compilato. Penso che il bug scompaia se ricarichi a causa della cache.

Un trucco: precarica il tuo CSS con un UIWebView fittizio nella tua applicazione.

SDK: IOS4

+0

Nel mio caso non è tanto il CSS che è stato caricato in ritardo, ma più specificamente un file di font nel CSS. – beetstra

4

Il problema con -sizeThatFits: è che non funziona out of the box, almeno non su iOS 4.1. Restituisce solo la dimensione corrente della visualizzazione Web (indipendentemente dal fatto che venga chiamata con CGSizeZero o una dimensione non zero arbitraria).

Ho scoperto che funziona effettivamente se si riduce l'altezza del frame di WebView prima di chiamare -sizeThatFits:.

Vedere la mia soluzione: How to determine the content size of a UIWebView?

+0

grazie per il puntatore. Ho visto la tua soluzione quando ho avuto questo problema, ma nel mio caso non ha funzionato meglio. Non mi ricordo davvero di cosa avevo bisogno, ma alla fine l'ho fatto in un modo diverso. – Shade

3

misurare un WebView funziona, ma solo quando ha caricato il suo contenuto

  • facendo WebView piccole (come 5px)
  • carico e attendere per la finitura
  • chiamando sizeToFit su di esso quindi
  • ottenendo la dimensione ALLORA
  • ricarica il tablev iew (ritorno all'altezza corretta per la cella)

annuncio:: D vedere la mia classe M42WebviewTableViewCell su GitHub, che lotta con questo

+0

Funziona! Grazie, ho usato prima l'approccio con javascript, ma questo funziona meglio per me. – Stan

2

L'approccio migliore è quello di utilizzare scrollView.contentSize.height proprietà, come qui di seguito.

- (void)webViewDidFinishLoad:(UIWebView *)webView 
{ 
    NSLog(@"%f",webView.scrollView.contentSize.height); 
} 
+1

Questo ha funzionato per me. Grazie. –

+0

Per me, è scrollView.contentSize.height - CGRectGetHeight (scrollView.frame). http://stackoverflow.com/a/39386880/1677041 – Itachi