iphone - fields - Evita que UITextView salte al configurar el texto mediante programación.
text field ios 11 (13)
Antigua pregunta pero tuve el mismo problema con la aplicación iOS 7. Requiere cambiar el contentOffset un poco después del ciclo de ejecución. Aquí hay una idea rápida.
self.clueString = [self.level clueText];
CGPoint point = self.clueText.contentOffset;
self.clueText.attributedText = self.clueString;
double delayInSeconds = 0.001; // after the run loop update
dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(delayInSeconds * NSEC_PER_SEC));
dispatch_after(popTime, dispatch_get_main_queue(), ^(void){
[self.clueText setContentOffset:point animated:NO];
});
Tengo que actualizar una pequeña cantidad de texto en un UITextView con desplazamiento. Solo insertaré un carácter donde el cursor está actualmente, y lo haré presionando un botón en mi barra de navegación.
Mi problema es que siempre que llamo al método setText de la vista de texto, salta a la parte inferior del texto. He intentado usar contentOffset y restablecer el rango seleccionado, ¡pero no funciona! Aquí está mi ejemplo:
// Remember offset and selection
CGPoint contentOffset = [entryTextView contentOffset];
NSRange selectedRange = [entryTextView selectedRange];
// Update text
entryTextView.text = entryTextView.text;
// Try and reset offset and selection
[entryTextView setContentOffset:contentOffset animated:NO];
[entryTextView setSelectedRange: selectedRange];
¿Hay alguna manera de actualizar el texto sin ningún movimiento de desplazamiento ... como si hubieran escrito algo en el teclado?
Editar:
He intentado usar el método textViewDidChange: delegate pero aún no se está desplazando hasta la ubicación original.
- (void)textViewDidChange:(UITextView *)textView {
if (self.programChanged) {
[textView setSelectedRange:self.selectedRange];
[textView setContentOffset:self.contentOffset animated:NO];
self.programChanged = NO;
}
}
- (void)changeButtonPressed:(id)sender {
// Remember position
self.programChanged = YES;
self.contentOffset = [entryTextView contentOffset];
self.selectedRange = [entryTextView selectedRange];
// Update text
entryTextView.text = entryTextView.text;
}
Eche un vistazo a la UITextViewDelegate, creo que el método textViewDidChangeSelection puede permitirle hacer lo que necesita.
Encontré una solución que funciona de manera confiable en iOS 6 y 7 (y probablemente en versiones anteriores). En una subclase de UITextView, haga lo siguiente:
@interface MyTextView ()
@property (nonatomic) BOOL needToResetScrollPosition;
@end
@implementation MyTextView
- (void)setText:(NSString *)text
{
[super setText:text];
self.needToResetScrollPosition = YES;
}
- (void)layoutSubviews
{
[super layoutSubviews];
if (self.needToResetScrollPosition) {
self.contentOffset = CGPointMake(0, 0);
self.needToResetScrollPosition = NO;
}
}
Ninguna de las otras respuestas funciona en iOS 7 porque ajustará las compensaciones de desplazamiento en el tiempo de visualización.
Esta decisión funciona para iOS 8:
let offset = textView.contentOffset
textView.text = newText
textView.layoutIfNeeded()
textView.setContentOffset(offset, animated: false)
Es necesario llamar exactamente setContentOffset:animated:
porque solo esto cancelará la animación. textView.contentOffset = offset
no cancelará la animación y no ayudará.
Finalmente prueba esto, comprobado en iOS 10.
let offset = textView.contentOffset
textView.attributedText = newValue
OperationQueue.main.addOperation {
self.textView.setContentOffset(offset, animated: false)
}
Golpeé un problema similar, si no el mismo, en IOS9. Cambiar las características de un texto a, por ejemplo, BOLD causó que la vista se desplace de la selección fuera de la vista. Ordené esto agregando una llamada a scrollRangeToVisible después del setSelectedRange:
[self setSelectedRange:range];
[self scrollRangeToVisible:range];
Las siguientes dos soluciones no me funcionan en iOS 8.0.
textView.scrollEnabled = NO;
[textView.setText: text];
textView.scrollEnabled = YES;
y
CGPoint offset = textView.contentOffset;
[textView.setText: text];
[textView setContentOffset:offset];
Configuré un delegado a la vista de texto para monitorear el evento de desplazamiento, y noté que después de mi operación para restaurar el desplazamiento, el desplazamiento se restablece a 0 nuevamente. Entonces, en lugar de eso, uso la cola de operaciones principal para asegurarme de que mi operación de restauración se realice después de la opción "restablecer a 0".
Aquí está mi solución que funciona para iOS 8.0.
CGPoint offset = self.textView.contentOffset;
self.textView.attributedText = replace;
[[NSOperationQueue mainQueue] addOperationWithBlock: ^{
[self.textView setContentOffset: offset];
}];
Ninguna de las soluciones sugeridas funcionó para mí. -setContentOffset: animated: se activa con -setText: 3 veces con YES animado y contentOffset del final (menos el margen predeterminado de 8 puntos de un UITextView). Envolví el -setText: en un guardia:
textView.contentOffsetAnimatedCallsDisabled = YES;
textView.text = text;
textView.contentOffsetAnimatedCallsDisabled = NO;
En una subclase UITextView en -setContentOffset: animated: put
if (contentOffsetAnimatedCallsDisabled) return; // early return
entre tu otra lógica. No olvides la súper llamada. Esto funciona.
Rafael
No es una solución tan elegante, pero funciona, a quién le importa:
- (IBAction)changeTextProgrammaticaly{
myTextView.text = @"Some text";
[NSTimer scheduledTimerWithTimeInterval:0.1 target:self selector:@selector(rewindOffset) userInfo:nil repeats:NO];
}
- (void)rewindOffset{
[myTextView setContentOffset:CGPointMake(0,0) animated: NO];
}
Para editar el texto de un UITextView, necesita actualizar el campo textStorage:
[_textView.textStorage beginEditing];
NSRange replace = NSMakeRange(10, 2); //enter your editing range
[_textView.textStorage replaceCharactersInRange:replace withString:@"ha ha$ "];
//if you want to edit the attributes
NSRange attributeRange = NSMakeRange(10, 5); //enter your editing attribute range
[_textView.textStorage addAttribute:NSBackgroundColorAttributeName value:[UIColor greenColor] range:attributeRange];
[_textView.textStorage endEditing];
Buena suerte
Si usas iPhone 3.0 o posterior, puedes resolver este problema:
textView.scrollEnabled = NO;
//You should know where the cursor will be(if you update your text by appending/inserting/deleting you can know the selected range) so keep it in a NSRange variable.
Then update text:
textView.text = yourText;
textView.scrollEnabled = YES;
textView.selectedRange = range;//you keep before
Debería funcionar ahora (no más saltos)
Saludos Meir Assayag
Sobre la base de la sugerencia de Meir, aquí está el código que elimina la selección mediante programación (sí, sé que hay un botón del menú de selección que también lo hace, pero estoy haciendo algo un poco raro) sin desplazar la vista de texto.
NSRange selectedRange = textView.selectedRange;
textView.scrollEnabled = NO;
// I''m deleting text. Replace this line with whatever insertions/changes you want
textView.text = [textView.text
stringByReplacingCharactersInRange:selectedRange withString:@""];
selectedRange.length = 0;
// If you''re inserting text, you might want to increment selectedRange.location to be
// after the text you inserted
textView.selectedRange = selectedRange;
textView.scrollEnabled = YES;
en iOS 7. Parece que hay un error con sizeThatFits y con linebreaks en su UITextView La solución que encontré que funciona es envolverlo deshabilitando el desplazamiento. Me gusta esto:
textView.scrollEnabled = NO;
CGSize newSize = [textView sizeThatFits:CGSizeMake(fixedWidth, MAXFLOAT)];
textView.scrollEnabled = YES;
y el salto extraño ha sido arreglado.