2009-04-13 10 views
70

Próbuję utworzyć UITableView ze zmiennymi rzędach wysokości jak wyjaśniono w odpowiedzi na this questionJak określić wysokość UIWebView na podstawie zawartości, w zmiennej wysokości UITableView?

mój problem jest każda komórka zawiera UIWebView z różnych (statycznie załadowany) treści nie mogę dowiedzieć się, jak obliczyć właściwą wysokość w oparciu o zawartość. Czy jest jakiś sposób na zrobienie tego? Próbowałem rzeczy tak:

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

Komórki same są ładowane z nib, który jest po prostu UITableViewCell zawierający UIWebView. (Byłoby dobrze, gdyby komórki dostosowały się do największej zawartości html, chociaż wysokość zmiennej byłaby lepsza).

+0

Czy kiedykolwiek zastanawiałeś się, jak to zrobić? Poniższe odpowiedzi podnoszą wysokość, ale dopiero po jej zakończeniu. Jak obliczyć wysokość dla heightForRowAtIndexPath Czy musisz polegać na wywołaniu wywołania zwrotnego (webview delegate) w webViewDidFinishLoad? – pbx

+0

Cześć, wreszcie, w jaki sposób określasz wysokość widoku sieciowego Mam również ten sam problem ... –

+0

Ktoś ma rozwiązanie? Nadal nie mogę tego zrozumieć .. – mikemike396

Odpowiedz

76

Ten kod jest prawdopodobnie zbyt wolny dla użycia widoku tabeli, ale działa. Wygląda na to, że nie ma alternatywy, ponieważ UIWebView nie oferuje bezpośredniego dostępu do DOM.

W kontrolerze widoku viewDidLoad ładuję kod HTML w widoku sieciowym, a po zakończeniu ładowania uruchom trochę javascript, aby zwrócić wysokość elementu.

- (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

Wygląda na to, że może to być praca, jednak próbowałem tego w widoku tabeli i zwraca pusty ciąg (domyślam się, że przeglądarka nie zakończyła ładowania). Sądzę, że mógłbym to wstępnie skomponować za pomocą offscreen webview i buforować wyniki dla tableview. – frankodwyer

+0

Czy mierzysz wysokość w webViewDidFinishLoad? To wywołanie zwrotne delegata wskazujące, że ładowanie zostało zakończone. Nie powinien zwracać pustego ciągu. – duncanwilcox

+0

To prawie dokładnie to, co robię. Chociaż mam problem z tym, że przeglądarka nie może zwrócić swojego rozmiaru, dopóki nie zakończy ładowania, co może nie mieć, gdy tabela musi znać jej rozmiar. Czy ktoś ma pomysł, jak rozwiązać ten problem? –

28

Bardzo miło było znaleźć odpowiedzi, sztuczka javascript działała dobrze dla mnie.

Jednak chciałem powiedzieć, że istnieje również „sizeThatFits:” metoda:

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

Musimy ustawić preferowany rozmiar różny od zera, ale poza tym, to zazwyczaj zawsze działa!

Zwykle, ponieważ dzięki UIWebView wydaje się działać tylko przy drugim ładowaniu (używam metody "loadHTMLString:" i tak nazywam "sizeThatFits:" z metody delegata "didFinishLoad:").

Dlatego też bardzo się cieszę, że mogę znaleźć rozwiązanie, które działa w każdym przypadku.

+1

+1 to zasługuje na kilka ważnych zmian! – mvds

+0

Nie mogę tego uruchomić na iOS 4.2 – Shade

+0

@Shade: Zobacz moją odpowiedź, jak zrobić to w nowszych wersjach iOS. –

6

To wydaje się działać. Na razie.

- (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; 
     } 
    } 
} 

Powinno bezpiecznie zwrócić 0, jeśli się nie powiedzie.

+3

Jak to jest lepsze niż: [webview stringByEvaluatingJavaScriptFromString: @ "document.getElementById (\" foo \ "). OffsetHeight;"] ;? Problem polega na tym, że widok internetowy nie może zwrócić rozmiaru, dopóki nie zakończy się ładowanie, co może nie mieć, gdy tabela musi znać jego rozmiar. –

3

Jeśli masz złe wartości z sizeThatFits po raz pierwszy, ale nie po, tutaj możliwe przyczyny napotkane: błąd z zewnętrznego CSS. Wygląda na to, że webViewDidFinisLoad jest wywoływany wkrótce, zanim zewnętrzny kod CSS zostanie pobrany, a dokument internetowy w pełni zbudowany. Myślę, że błąd zniknie, jeśli przeładujesz z powodu pamięci podręcznej.

Sztuczka: wstępnie wczytaj swój CSS za pomocą fikcyjnego interfejsu UIWebView w aplikacji.

SDK: iOS4

+0

W moim przypadku nie było tak dużo CSS, który został załadowany późno, ale dokładniej plik czcionek w CSS. – beetstra

4

Problem z -sizeThatFits: jest to, że nie działa po wyjęciu z pudełka, a przynajmniej nie na iOS 4.1. Po prostu zwraca bieżący rozmiar webView (bez względu na to, czy jest wywoływany z CGSizeZero, czy z dowolnego niezerowego rozmiaru).

Dowiedziałem się, że to działa, jeśli zmniejszysz wysokość ramki webView przed wywołaniem -sizeThatFits:.

Zobacz moje rozwiązanie: How to determine the content size of a UIWebView?

+0

dziękuję za wskaźnik. Widziałem twoje rozwiązanie, gdy miałem ten problem, ale w moim przypadku nie działa lepiej. Naprawdę nie pamiętam, czego potrzebowałem, ale w końcu zrobiłem to inaczej. – Shade

3

pomiaru webview działa, ale tylko wtedy, gdy jest załadowana zawartość

  • dokonywania WebView małe (jak 5px)
  • obciążenie go i czekać na wykończenie
  • Wywołanie sizeToFit na nim następnie
  • uzyskanie rozmiaru THEN
  • ponowne załadowanie tablev iew (powrót prawidłowej wysokości na komórkę)

ogłoszenia:: D zobaczyć moją klasę M42WebviewTableViewCell na github, który zmaga się z tym

+0

To działa! Dzięki, użyłem przed podejściem z javascript, ale ten działa lepiej dla mnie. – Stan

2

Lepszym sposobem jest użycie scrollView.contentSize.height nieruchomości, jak poniżej.

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

To zadziałało dla mnie. Dzięki. –

+0

Dla mnie jest to scrollView.contentSize.height - CGRectGetHeight (scrollView.frame). http://stackoverflow.com/a/39386880/1677041 – Itachi