Jak przenieść sugestię korekty UITextView powyżej tekstu

Używam UITextView, aby z grubsza odtworzyć pole tekstowe SMS nad klawiaturą. Używam UITextView zamiast pola, dzięki czemu może rozszerzać się o wiele linii.

Problem polega na tym, że w moim UITextView sugestie poprawek pojawiają się poniżej tekstu, powodując, że są częściowo zasłonięte przez klawiaturę.

W aplikacji SMS sugestie pojawiają się nad tekstem. Umieszczenie nie wydaje się być własnością UITextView, lub UITextInputTraits.

Jakiś pomysł jak odtworzyć to zachowanie? Dzięki!

Author: DougW, 2009-12-30

7 answers

Problem polega na tym, że klawiatura jest zaimplementowana jako oddzielny UIWindow, a nie jako widok w głównym UIWindow, więc układ z nią jest trudny. Oto kilka wskazówek we właściwym kierunku:

  • Przeszukaj Właściwość -windows aplikacji, aby znaleźć prywatne okno UITextEffectsWindow i znaleźć jego ramkę. To jest klawiatura
  • Przeszukaj podview TextView, aby znaleźć prywatny widok UIAutocorrectInlinePrompt. To jest bańka autokorekty.
  • przenieś ten subview do oddzielny widok owijarki (dodany do widoku tekstowego), a następnie przenieś ten widok tak, aby znajdował się powyżej wspomnianego okna klawiatury.

Zauważysz dwie wzmianki o" prywatnym " powyżej. To niesie ze sobą wszystkie istotne zastrzeżenia. Nie mam pojęcia, dlaczego Apple zezwoliło na utrzymywanie się problemu, gdy nawet ich aplikacje musiały go obejść.

 8
Author: Rob Napier,
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-01-01 20:10:21

Wykonując wyszukiwanie UIAutocorrectInlinePrompt w nadpisanym lub zmienionym layoutSubViews, można zmienić układ korekty tak, aby pojawił się powyżej. Możesz to zrobić bez wywoływania żadnych prywatnych interfejsów API, szukając widoków subs poszczególnych klas ustawionych w sposób, w jaki można ich oczekiwać. Ten przykład sprawdza, który Widok jest który, sprawdza, czy korekta nie znajduje się już nad tekstem i przesuwa korektę powyżej, a następnie rysuje ją na oknie że nie jest ograniczony przez sam UITextView. Oczywiście, jeśli apple zmieni podstawową implementację, to nie przeniesie korekty. Dodaj to do nadpisanej lub przekręconej implementacji layoutSubViews.

- (void) moveSpellingCorrection {
 for (UIView *view in self.subviews)
 {
  if ([[[view class] description] isEqualToString:@"UIAutocorrectInlinePrompt"])
  {
   UIView *correctionShadowView = nil; // [view correctionShadowView];

   for (UIView *subview in view.subviews)
   {
    if ([[[subview class] description] isEqualToString:@"UIAutocorrectShadowView"])
    {
     correctionShadowView = subview;
     break;
    }
   }

   if (correctionShadowView)
   {
    UIView *typedTextView = nil; //[view typedTextView];
    UIView *correctionView = nil; //[view correctionView];

    for (UIView *subview in view.subviews)
    {
     if ([[[subview class] description] isEqualToString:@"UIAutocorrectTextView"])
     {
      if (CGRectContainsRect(correctionShadowView.frame,subview.frame))
      {
       correctionView = subview;
      }
      else
      { 
       typedTextView = subview;
      }
     }

    }
    if (correctionView && typedTextView)
    {

     CGRect textRect = [typedTextView frame];
     CGRect correctionRect = [correctionView frame];
     if (textRect.origin.y < correctionRect.origin.y)
     {
      CGAffineTransform moveUp = CGAffineTransformMakeTranslation(0,-50.0);
      [correctionView setTransform: moveUp];
      [correctionShadowView setTransform: moveUp];

      CGRect windowPos = [self convertRect: view.frame toView: nil ];
      [view removeFromSuperview];
      [self.window addSubview: view];
      view.frame = windowPos;
     }

    }
   }

  }

 }
}
 3
Author: Johnno,
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-02-17 17:36:13

Rzeczywiście robi

textview.scrollEnabled = NO;

Ustawi bańkę na górze tekstu... zastrzeżenie jest to, że tracisz przewijanie, w moim przypadku nie był to problem z powodu posiadania pola tekstowego tylko do celów wprowadzania z limitem znaków

 1
Author: Heavy_Bullets,
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
2013-06-12 16:01:28

W rzeczywistości klawiatura po prostu używa wyniku- [UITextInput textInputView], aby określić, gdzie umieścić widok korekty (i zapytać, czy Widok obsługuje korektę). Więc wszystko co musisz zrobić to:

- (UIView *)textInputView {
  for (UIWindow *window in [UIApplication sharedApplication].windows) {
    if ([window isKindOfClass:NSClassFromString(@"UITextEffectsWindow")] && 
        window != self.window) {
      return window;
    }
  }

  // Fallback just in case the UITextEffectsWindow has not yet been created.
  return self;
}

Zauważ, że prawdopodobnie będziesz musiał zaktualizować -[uitextinput firstRectForRange:], aby użyć układu współrzędnych okna / urządzenia, więc możesz to zrobić:

- (CGRect)firstRectForRange:(CoreTextTokenTextRange *)range {
  CGRect firstRect = [self firstRectForRangeInternal:range];

  return [self convertRect:firstRect toView:[self textInputView]];
}

(w powyższym kontekście self jest klasą implementującą UITextInput).

 1
Author: Scott Grant,
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
2015-01-23 13:20:41

Jeśli dolna część UITextView wyczyści klawiaturę, powinieneś być w stanie zmienić rozmiar UITextView tak, aby był wystarczająco wysoki, aby zobaczyć poprawki. Same poprawki nie są wyświetlane poza ramką UITextView.

Jeśli chcesz naśladować to, co dostajesz w aplikacji SMS (poprawki powyżej), prawdopodobnie będziesz musiał rzucić własne.

 0
Author: Matt Long,
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
2009-12-30 03:23:12

Umieszczając poniższą metodę, adjustAutocorrectPromptView w layoutSubviews działało dla mnie w portret i krajobraz. Mam kategorię, która zapewnia dolne i górne metody na widoku, ale masz pomysł.

NSArray * subviewsWithDescription(UIView *view, NSString *description)
{
    return [view.subviews filteredArrayUsingPredicate:[NSPredicate predicateWithFormat:[NSString stringWithFormat:@"class.description == '%@'", description]]];
}

- (void) adjustAutocorrectPromptView;
{
    UIView *autocorrectPromptView = [subviewsWithDescription(self, @"UIAutocorrectInlinePrompt") lastObject];

    if (! autocorrectPromptView)
    {
        return;
    }

    UIView *correctionShadowView = [subviewsWithDescription(autocorrectPromptView, @"UIAutocorrectShadowView") lastObject];

    if (! correctionShadowView)
    {
        return;
    }

    UIView *typedTextView = nil; //[view typedTextView];
    UIView *correctionView = nil; //[view correctionView];

    for (UIView *subview in subviewsWithDescription(autocorrectPromptView, @"UIAutocorrectTextView"))
    {
        if (CGRectContainsRect(correctionShadowView.frame,subview.frame))
        {
            correctionView = subview;
        }
        else
        {
            typedTextView = subview;
        }
    }

    if (correctionView && typedTextView)
    {
        if (typedTextView.top < correctionView.top)
        {
            correctionView.bottom = typedTextView.top;
            correctionShadowView.center = correctionView.center;
        }
    }
}
 0
Author: Kirby Todd,
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
2013-01-25 08:46:59

Upewnij się, że delegat kontrolera widoku nasłuchuje powiadomienia, gdy pojawi się klawiatura, aby zmienić rozmiar UITextView, aby klawiatura nie zasłaniała widoku UITextView. Wtedy twoja korekta nie zostanie zasłonięta przez klawiaturę. Zobacz:

Http://www.iphonedevsdk.com/forum/iphone-sdk-development/12641-uitextview-scroll-while-editing.html

Oto Kopia kodu z tej strony w przypadku, gdy oryginalny link jest uszkodzony:

// the amount of vertical shift upwards keep the Notes text view visible as the keyboard appears
#define kOFFSET_FOR_KEYBOARD                    140.0

// the duration of the animation for the view shift
#define kVerticalOffsetAnimationDuration        0.50

- (IBAction)textFieldDoneEditing:(id)sender
{
    [sender resignFirstResponder];
}

- (IBAction)backgroundClick:(id)sender
{
    [latitudeField resignFirstResponder];
    [longitudeField resignFirstResponder];
    [notesField resignFirstResponder];

    if (viewShifted)
    {
        [UIView beginAnimations:nil context:NULL];
        [UIView setAnimationDuration:kVerticalOffsetAnimationDuration];

        CGRect rect = self.view.frame;
        rect.origin.y += kOFFSET_FOR_KEYBOARD;
        rect.size.height -= kOFFSET_FOR_KEYBOARD;
        self.view.frame = rect;

        [UIView commitAnimations];

        viewShifted = FALSE;
    }       
}

- (BOOL)textViewShouldBeginEditing:(UITextView *)textView
{
    if (!viewShifted) {     // don't shift if it's already shifted

        [UIView beginAnimations:nil context:NULL];
        [UIView setAnimationDuration:kVerticalOffsetAnimationDuration];

        CGRect rect = self.view.frame;      
        rect.origin.y -= kOFFSET_FOR_KEYBOARD;
        rect.size.height += kOFFSET_FOR_KEYBOARD;
        self.view.frame = rect;

        [UIView commitAnimations];

        viewShifted = TRUE;
    }
    return YES;
}
 -2
Author: lucius,
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
2009-12-31 19:39:34