UITextView w UITableViewCell płynna automatyczna zmiana rozmiaru pokazuje i ukrywa klawiaturę na iPadzie, ale działa na iPhonie

Zaimplementowałem Niestandardowy UITableViewCell, który zawiera UITextView, który automatycznie zmienia rozmiar jako typy użytkowników, podobny do pola "uwagi" w aplikacji Kontakty. Działa poprawnie na moim iPhonie, ale kiedy testuję go na iPadzie, dostaję bardzo dziwne zachowanie: kiedy dojdziesz do końca linii, klawiatura chowa się na milisekundę, a następnie natychmiast pokazuje się ponownie. Zapisałbym to jako tylko dziwaczny błąd, ale faktycznie powoduje utratę danych, ponieważ jeśli jesteś pisząc, traci znak lub dwa. Oto Mój kod:

Kod

// returns the proper height/size for the UITextView based on the string it contains.
// If no string, it assumes a space so that it will always have one line.
- (CGSize)textViewSize:(UITextView*)textView {
     float fudgeFactor = 16.0;
     CGSize tallerSize = CGSizeMake(textView.frame.size.width-fudgeFactor, kMaxFieldHeight);
     NSString *testString = @" ";
     if ([textView.text length] > 0) {
          testString = textView.text;
     }
     CGSize stringSize = [testString sizeWithFont:textView.font constrainedToSize:tallerSize lineBreakMode:UILineBreakModeWordWrap];
     return stringSize;
}

// based on the proper text view size, sets the UITextView's frame
- (void) setTextViewSize:(UITextView*)textView {
     CGSize stringSize = [self textViewSize:textView];
     if (stringSize.height != textView.frame.size.height) {
          [textView setFrame:CGRectMake(textView.frame.origin.x,
                                        textView.frame.origin.y,
                                        textView.frame.size.width,
                                        stringSize.height+10)];  // +10 to allow for the space above the text itself 
     }
}

// as per: https://stackoverflow.com/questions/3749746/uitextview-in-a-uitableviewcell-smooth-auto-resize
- (void)textViewDidChange:(UITextView *)textView {

     [self setTextViewSize:textView]; // set proper text view size
     UIView *contentView = textView.superview;
     // (1) the padding above and below the UITextView should each be 6px, so UITextView's
     // height + 12 should equal the height of the UITableViewCell
     // (2) if they are not equal, then update the height of the UITableViewCell
     if ((textView.frame.size.height + 12.0f) != contentView.frame.size.height) {
         [myTableView beginUpdates];
         [myTableView endUpdates];

         [contentView setFrame:CGRectMake(0,
                                          0,
                                          contentView.frame.size.width,
                                          (textView.frame.size.height+12.0f))];
     }
}

- (CGFloat)tableView:(UITableView  *)tableView heightForRowAtIndexPath:(NSIndexPath  *)indexPath {
     int height;
     UITextView *textView = myTextView;
     [self setTextViewSize:textView];
     height = textView.frame.size.height + 12;
     if (height < 44) { // minimum height of 44
          height = 44;
          [textView setFrame:CGRectMake(textView.frame.origin.x,
                                        textView.frame.origin.y,
                                        textView.frame.size.width,
                                        44-12)];
      }
      return (CGFloat)height;
}

Problemy

Oto co się dzieje

  1. ten kod działa w 100% poprawnie na moim iPhonie i w symulatorze iPhone ' a. W miarę wpisywania tekstu UITextView rośnie płynnie, a wraz z nim UITableViewCell.
  2. na iPad simulator, jednak robi się wkręcone. Działa dobrze podczas pisania w pierwszej linii, ale kiedy dojdziesz do końca linii, klawiatura znika, a następnie pojawia się natychmiast, tak, że jeśli Użytkownik kontynuuje pisanie aplikacja pomija znak lub dwa.
  3. Oto kilka dodatkowych uwag na temat dziwnych zachowań, które zauważyłem, które mogą pomóc wyjaśnić:
    • odkryłem również, że usunięcie linii {[1] } w funkcji textViewDidChange:(UITextView *)textView sprawia, że UITextView rośnie prawidłowo, a także nie pokazuje i nie ukrywa klawiatury, ale niestety, UITableViewCell nie rośnie do właściwego wzrost.
    • UPDATE: wykonując te instrukcje, jestem teraz w stanie zatrzymać dziwny ruch tekstu; ale klawiatura wciąż się ukrywa i pokazuje, co jest bardzo dziwne.

Czy ktoś ma jakieś pomysły, jak sprawić, by klawiatura ciągle się pokazywała, a nie chować i pokazywać, gdy dojdziesz do końca linii na iPadzie?

P. S.: Nie jestem zainteresowany używaniem ThreeTwenty.

Author: Community, 2010-10-25

2 answers

Powinieneś zwrócić NO IN:

 -(BOOL) textViewShouldEndEditing:(UITextView *)textView

Jeśli chcesz wyświetlać klawiaturę przez cały czas. Powinieneś obsługiwać przypadki, które klawiatura powinna być ukryta, zwracając YES do tej funkcji delegata.

Edit:

Wykopałem trochę więcej, gdy [tableview endUpdates] wywołane, to w zasadzie robi 3 rzeczy:

  1. wyłącza interakcję użytkownika na tableView
  2. aktualizuje zmiany komórek
  3. umożliwia interakcję z użytkownikiem na tableView

Różnica między zestawami SDK (platformami) wynosi [UIView setUserInteractionEnabled] metoda. Ponieważ UITableView nie nadpisuje metody setUserInteractionEnabled, jest ona wywoływana z super (UIView).

IPhone po wywołaniu setUserInteractionEnabled szuka prywatnego pola _shouldResignFirstResponderWithInteractiondisabled które domyślnie zwraca NO , więc nie rezygnuje z pierwszego odpowiedzi (UITextView)

Ale na iPadzie nie ma takiego sprawdzania AFAIK, więc rezygnuje UITextView na Krok 1 i ustawia fokus i robi pierwszy responder na Krok 3

Zasadniczo, textViewShouldEndEditing, który pozwala zachować ostrość, zgodnie z dokumentami SDK, jest jedyną opcją.

Metoda ta jest wywoływana, gdy tekst widok jest proszony o rezygnację z pierwszego status respondenta. Może to wystąpić gdy użytkownik próbuje zmienić edycja ostrości do innej kontroli. Zanim fokus faktycznie się zmieni, jednak Widok tekstowy nazywa to sposób, aby dać szansę swojemu delegatowi aby zdecydować, czy powinno.

 14
Author: Deniz Mert Edincik,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-10-30 18:29:41

Miałem ten sam problem w aplikacji na iPada i wymyśliłem inne rozwiązanie bez obliczania wysokości samego tekstu.

Najpierw Utwórz niestandardowy UITableViewCell w IB z polem UITextField umieszczonym w widoku zawartości komórki. Ważne jest, aby ustawić scrollEnabledNA NO, a autoresizingMask na flexibleWidth i flexibleHeight.


W kontrolerze ViewController zaimplementuj metodę delegata widoku tekstu - textViewDidChanged: jak poniżej, gdzie textHeight jest zmienną instancyjną typu CGFloat i -tableViewNeedsToUpdateHeight jest niestandardową metodą, którą zdefiniujemy w następnym kroku.

- (void)textViewDidChange:(UITextView *)textView
{
    CGFloat newTextHeight = [textView contentSize].height;

    if (newTextHeight != textHeight)
    {
        textHeight = newTextHeight;
        [self tableViewNeedsToUpdateHeight];
    }
}

Metoda - tableViewNeedsToUpdateHeight wywołuje widok tabeli beginUpdatesi endUpdates, więc sam widok tabeli wywoła metodę delegate -tableView:heightForRowAtIndexPath:.

- (void)tableViewNeedsToUpdateHeight
{
    BOOL animationsEnabled = [UIView areAnimationsEnabled];
    [UIView setAnimationsEnabled:NO];
    [table beginUpdates];
    [table endUpdates];
    [UIView setAnimationsEnabled:animationsEnabled];
}

W widoku tabeli - tableView: heightForRowAtIndexPath: metoda delegata musimy obliczyć nową wysokość dla komórki widoku tekstowego na podstawie textHeight .

Najpierw musimy zmienić rozmiar wysokości komórek widoku tekstowego na maksymalną dostępną wysokość (po odjęciu wysokości wszystkich innych komórek w widoku tabeli). Następnie sprawdzamy, czy textHeight jest większy niż obliczona wysokość.

- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{   
    CGFloat heightForRow = 44.0;

    if ([indexPath row] == kRowWithTextViewEmbedded)
    {
        CGFloat tableViewHeight = [tableView bounds].size.height;
        heightForRow = tableViewHeight - ((kYourTableViewsNumberOfRows - 1) * heightForRow);

        if (heightForRow < textHeight) 
        {
            heightForRow = textHeight;
        }
    }

    return heightForRow;
}

Aby uzyskać lepsze wrażenia użytkownika, ustaw wstawki zawartości widoku tabeli dla dołu na np. 50.0.

Przetestowałem go na iPadzie z iOS 4.2.1 i działa zgodnie z oczekiwaniami.

Florian

 10
Author: Florian Mielke,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-01-30 14:19:47