Desde iOS 7, un UITextView no se desplaza automáticamente para el cursor a medida que el usuario escribe el texto que fluye a una nueva línea. Este problema está bien documentada y en otros lugares. Para mí, la cuestión es todavía presente en iOS 7.1. ¿Qué estoy haciendo mal?

iOS 7.1 UITextView todavía no desplazamiento del cursor/cursor después de la nueva línea

He instalado Xcode 5.1 y específica de iOS 7.1. Estoy usando Diseño Automático.

He aquí cómo puedo colocar el texto en la vista de contenido sobre el teclado:

- (void)keyboardUp:(NSNotification *)notification
{
    NSDictionary *info = [notification userInfo];
    CGRect keyboardRect = [[info objectForKey:UIKeyboardFrameEndUserInfoKey] CGRectValue];
    keyboardRect = [self.view convertRect:keyboardRect fromView:nil];

    UIEdgeInsets contentInset = self.textView.contentInset;
    contentInset.bottom = keyboardRect.size.height;
    self.textView.contentInset = contentInset;
}

Lo que he intentado: he probado muchas de las soluciones publicado por LO que en esta cuestión en lo que se refiere a iOS 7. Todas las soluciones que he intentado hacer no parece que se mantienen bien para el texto vistas a mostrar una atribuido cadena. En los siguientes tres pasos, en el que voy a describir cómo el más votado respuesta en TAN (https://stackoverflow.com/a/19277383/1239263) responde al usuario pulsando la tecla de retorno para la primera vez.

(1.) La vista de texto se convirtió en el primer respondedor en viewDidLoad. Desplácese hasta la parte inferior de la vista de texto donde se encuentra el cursor.

iOS 7.1 UITextView todavía no desplazamiento del cursor/cursor después de la nueva línea

(2.) Antes de escribir un solo carácter, pulse la tecla intro en el teclado. El símbolo de intercalación de desaparecer de la vista.

iOS 7.1 UITextView todavía no desplazamiento del cursor/cursor después de la nueva línea

(3.) Pulsando la tecla de retorno de nuevo, sin embargo, parece normalizar la situación. (Nota: al eliminar la última línea nueva, sin embargo, hace que el cursor desaparecerá una vez más).

iOS 7.1 UITextView todavía no desplazamiento del cursor/cursor después de la nueva línea

  • También se debe señalar que este desplazamiento problema es todavía presente en Apple app de Calendario después de la actualización a iOS 7.1. Crear un nuevo evento, desplácese hacia abajo hasta la sección «Notas», pulsar la tecla de retorno repetidas veces hasta que el cursor desaparece.
  • No estás haciendo nada malo. Es un bug.
  • Pero hubo muchos informes de error presentado a Apple acerca de este problema. Tal vez no no se supone que el conjunto de la contentInset de una vista de texto respaldada por el Texto del Kit. El llamado error en su mayoría desaparece si puedo evitar el establecimiento de la contentInset.
  • ¿Cuál es tu punto? Esto funcionó bien durante años y ahora no. Es un bug y Apple no se ha solucionado. Tengo un montón más de esos si desea ellos.
  • relájate amigo, es que no se como me escribió una mala crítica de su libro. Sólo estoy sugiriendo que Apple no puede ver este problema como un error; tal vez no lo estoy usando un Texto Kit de copia de UITextView correctamente.
  • En lugar de ajustar la contentInset de la UITextView, establecer el frame de UITextView & que problema habrá desaparecido.. Cuando teclados se muestra a continuación, reducir el marco de & cuando el teclado se esconde, a continuación, ajustar el marco.
  • Yo había respondido a mi pregunta con una solución similar (ya eliminado). Pero que no se mantiene para el caso de prueba descritos en los 3 pasos en mi post (es decir, pulsando la tecla de retorno).
  • Echa un vistazo a pedro steinburgers post, este es exactamente el problema se resuelve con una gran explicación – petersteinberger.com/blog/2014/fixing-uitextview-on-ios-7
  • El problema se CORRIGIÓ en iOS 8.

InformationsquelleAutor bilobatum | 2014-03-11

5 Comentarios

  1. 11

    Mejora de la solución del código para UITextView descendiente de la clase:

    #define SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(v) ([[[UIDevice currentDevice] systemVersion] compare:v options:NSNumericSearch] != NSOrderedAscending)
    #define is_iOS7 SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(@"7.0")
    #define is_iOS8 SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(@"8.0")
    @implementation MyTextView {
    BOOL settingText;
    }
    - (id)initWithFrame:(CGRect)frame {
    self = [super initWithFrame:frame];
    if (self) {
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(handleTextViewDidChangeNotification:) name:UITextViewTextDidChangeNotification object:self];
    }
    return self;
    }
    - (void)scrollToCaretInTextView:(UITextView *)textView animated:(BOOL)animated {
    CGRect rect = [textView caretRectForPosition:textView.selectedTextRange.end];
    rect.size.height += textView.textContainerInset.bottom;
    [textView scrollRectToVisible:rect animated:animated];
    }
    - (void)handleTextViewDidChangeNotification:(NSNotification *)notification {
    if (notification.object == self && is_iOS7 && !is_iOS8 && !settingText) {
    UITextView *textView = self;
    if ([textView.text hasSuffix:@"\n"]) {
    [CATransaction setCompletionBlock:^{
    [self scrollToCaretInTextView:textView animated:NO];
    }];
    } else {
    [self scrollToCaretInTextView:textView animated:NO];
    }
    }
    }
    - (void)setText:(NSString *)text {
    settingText = YES;
    [super setText:text];
    settingText = NO;
    }

    Nota no funciona cuando Abajo se pulsa la tecla en el teclado de Bluetooth.

    • Me gusta (a pesar de su inicializador es incompleta). Presumiblemente setAttributedText: también tendrá que ser reemplazado. Me alegro de que iOS 8 corrige este error.
    • Inicializador fue corregido.
  2. 9

    Una solución sólida debe sostener en las siguientes situaciones:

    (1.) una vista de texto para mostrar un atribuye cadena

    (2.) una nueva línea creada pulsando la tecla intro en el teclado

    (3.) una nueva línea creada por escribir el texto que desborda a la línea siguiente

    (4.) copiar y pegar texto

    (5.) una nueva línea creada pulsando la tecla de retorno para la primera vez (ver los 3 pasos en el OP)

    (6.) la rotación del dispositivo

    (7.) algunos caso no creo que…

    Para satisfacer estos requisitos en iOS 7.1, parece como si todavía es necesario manualmente desplácese hasta el símbolo de intercalación.

    Es común ver a las soluciones que manualmente desplácese hasta el símbolo de intercalación cuando la vista de texto delegado método textViewDidChange: se llama. Sin embargo, he encontrado que esta técnica no satisfacer situación #5 arriba. Incluso una llamada a layoutIfNeeded antes del desplazamiento a la intercalación no ayuda. En cambio, tuve que desplazar el cursor dentro de un CATransaction finalización del bloque:

    //this seems to satisfy all of the requirements listed above–if you are targeting iOS 7.1
    - (void)textViewDidChange:(UITextView *)textView
    {
    if ([textView.text hasSuffix:@"\n"]) {
    [CATransaction setCompletionBlock:^{
    [self scrollToCaretInTextView:textView animated:NO];
    }];
    } else {
    [self scrollToCaretInTextView:textView animated:NO];
    }
    }

    ¿Por qué funciona esto? Yo no tengo ni idea. Tienes que preguntarle a un ingeniero de Apple.

    Para la integridad, aquí todo el código relacionado con mi solución:

    #import "ViewController.h"
    @interface ViewController () <UITextViewDelegate>
    @property (weak, nonatomic) IBOutlet UITextView *textView; //full-screen
    @end
    @implementation ViewController
    - (void)viewDidLoad
    {
    [super viewDidLoad];
    NSString *string = @"All work and no play makes Jack a dull boy.\n\nAll work and no play makes Jack a dull boy. All work and no play makes Jack a dull boy. All work and no play makes Jack a dull boy. All work and no play makes Jack a dull boy. All work and no play makes Jack a dull boy. All work and no play makes Jack a dull boy. All work and no play makes Jack a dull boy. All work and no play makes Jack a dull boy.";
    NSAttributedString *attrString = [[NSAttributedString alloc] initWithString:string attributes:@{NSFontAttributeName: [UIFont fontWithName:@"Verdana" size:30.0]}];
    self.textView.attributedText = attrString;
    self.textView.delegate = self;
    self.textView.backgroundColor = [UIColor yellowColor];
    [self.textView becomeFirstResponder];
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardIsUp:) name:UIKeyboardDidShowNotification object:nil];
    }
    //helper method
    - (void)scrollToCaretInTextView:(UITextView *)textView animated:(BOOL)animated
    {
    CGRect rect = [textView caretRectForPosition:textView.selectedTextRange.end];
    rect.size.height += textView.textContainerInset.bottom;
    [textView scrollRectToVisible:rect animated:animated];
    }
    - (void)keyboardIsUp:(NSNotification *)notification
    {
    NSDictionary *info = [notification userInfo];
    CGRect keyboardRect = [[info objectForKey:UIKeyboardFrameEndUserInfoKey] CGRectValue];
    keyboardRect = [self.view convertRect:keyboardRect fromView:nil];
    UIEdgeInsets inset = self.textView.contentInset;
    inset.bottom = keyboardRect.size.height;
    self.textView.contentInset = inset;
    self.textView.scrollIndicatorInsets = inset;
    [self scrollToCaretInTextView:self.textView animated:YES];
    }
    - (void)textViewDidChange:(UITextView *)textView
    {
    if ([textView.text hasSuffix:@"\n"]) {
    [CATransaction setCompletionBlock:^{
    [self scrollToCaretInTextView:textView animated:NO];
    }];
    } else {
    [self scrollToCaretInTextView:textView animated:NO];
    }
    }
    @end

    Si usted encuentra una situación en la que esto no funciona, por favor hágamelo saber.

    • Su solución no funciona con la tecla hacia Abajo en el teclado de Bluetooth.
    • Se rompe método setText de texto siempre será desplazado a la final si el nuevo texto @»\n» sufijo.
  3. 3

    Lo resuelto por la obtención de la posición actual del cursor y ajustar a ella, aquí está mi método:

    - (void) alignTextView:(UITextView *)textView withAnimation:(BOOL)shouldAnimate {
    //where the blinky caret is
    CGRect caretRect = [textView caretRectForPosition:textView.selectedTextRange.start];
    CGFloat offscreen = caretRect.origin.y + caretRect.size.height - (textView.contentOffset.y + textView.bounds.size.height - textView.contentInset.bottom - textView.contentInset.top);
    CGPoint offsetP = textView.contentOffset;
    offsetP.y += offscreen + 3; //3 px -- margin puts caret 3 px above bottom
    if (offsetP.y >= 0) {
    if (shouldAnimate) {
    [UIView animateWithDuration:0.2 animations:^{
    [textView setContentOffset:offsetP];
    }];
    }
    else {
    [textView setContentOffset:offsetP];
    }
    }
    }

    Si sólo necesita para orientar después de que el usuario pulse return /enter, trate de:

    - (void) textViewDidChange:(UITextView *)textView {
    if ([textView.text hasSuffix:@"\n"]) {
    [self alignTextView:textView withAnimation:NO];
    }
    }

    Hágamelo saber si funciona para usted!

    • suena como su solución es sólo una solución parcial. la vista de texto siempre debe mostrar el cursor a pesar de la OS de error. Además, el uso de contentInset es más fácil que cambiar el punto de vista del marco de la OMI.
    • Lo que si sólo vas a usar el símbolo de intercalación si el usuario presiona enter, vea las ediciones.
    • No funciona porque el carácter de nueva línea aún no está establecido en la vista de texto cuando textView:shouldChangeTextInRange:replacementText: se llama.
    • Vamos a darle una oportunidad más, ver las actualizaciones!
    • Ok, eso funciona. Te voy a dar un +1, pero voy a aplazar la selección de una respuesta para un poco. Con iOS 7.1, yo estaba realmente esperando a evitar el manual de desplazamiento hacks para hacer algo que estaba disponible de forma gratuita en iOS 6.
    • Esperemos que surge algo!
    • Me encontré con un problema con su solución cuando la vista de texto muestra un atribuye cadena. El primer toque en la tecla de retorno oculta el cursor detrás del teclado.
    • Eso es muy extraño, me pregunto ¿qué acerca de la atribuye cadena causa de que. Va completamente fuera de la pantalla?
    • Sí, desaparece completamente.

  4. 0

    No puedo encontrar la fuente original, pero funciona en iOS7.1

     - (void)textViewDidChangeSelection:(UITextView *)textView
    {
    if ([textView.text characterAtIndex:textView.text.length-1] != ' ') {
    textView.text = [textView.text stringByAppendingString:@" "];
    }
    NSRange range0 = textView.selectedRange;
    NSRange range = range0;
    if (range0.location == textView.text.length) {
    range = NSMakeRange(range0.location - 1, range0.length);
    } else if (range0.length > 0 &&
    range0.location + range0.length == textView.text.length) {
    range = NSMakeRange(range0.location, range0.length - 1);
    }
    if (!NSEqualRanges(range, range0)) {
    textView.selectedRange = range;
    }
    }
    • ¿Has probado esta solución con una vista de texto que muestra un atribuye cadena? Yo no podía llegar a trabajar.
  5. 0

    Algunos han hecho una subclase que resuelve todos los scrolling0related problemas en UITextView. La aplicación no podría ser más fácil – interruptor de UITextView con la subclase PSPDFTextView.

    Un post sobre ello, mostrando lo que es fijo (Con bonitas animaciones Gif) está aquí: La fijación de UITextView en iOS 7

    El git está aquí: PSPDFTextView

Dejar respuesta

Please enter your comment!
Please enter your name here