iphone - ¿Cómo obligo a UITextView a desplazarse a la parte superior cada vez que cambio el texto?
ios (30)
OK, estoy teniendo algún problema con el UITextView
. Aquí está el problema:
Agrego texto a una UITextView
. El usuario hace doble clic para seleccionar algo. A continuación, UITextView
el texto en UITextView
(programáticamente como se UITextView
arriba) y el UITextView
desplaza hacia la parte inferior de la página donde hay un cursor.
Sin embargo, NO es donde el usuario hizo clic. SIEMPRE se desplaza hacia la parte inferior de la UITextView
independientemente de dónde haya hecho clic el usuario.
Así que aquí está mi pregunta: ¿Cómo UITextView
el UITextView
para desplazarse a la cima cada vez que cambio el texto? Intenté contentOffset
y scrollRangeToVisible
. Ni trabajo
Cualquier sugerencia sera apreciada.
Aquí están mis códigos. Funciona bien.
class MyViewController: ...
{
private offsetY: CGFloat = 0
@IBOutlet weak var textView: UITextView!
...
override viewWillAppear(...)
{
...
offsetY = self.textView.contentOffset.y
...
}
...
func refreshView() {
let offSetY = textView.contentOffset.y
self.textView.setContentOffset(CGPoint(x:0, y:0), animated: true)
DispatchQueue.main.asyncAfter(deadline: .now() + 0.3) {
[unowned self] in
self.textView.setContentOffset(CGPoint(x:0, y:self.offSetY),
animated: true)
self.textView.setNeedsDisplay()
}
}
Así es como funcionó en iOS 9 Release, así que textView se desplaza hacia arriba antes de aparecer en la pantalla
- (void)viewDidLoad
{
[super viewDidLoad];
textView.scrollEnabled = NO;
}
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
textView.scrollEnabled = YES;
}
Así es como lo hice
Swift 4:
extension UITextView {
override open func draw(_ rect: CGRect)
{
super.draw(rect)
setContentOffset(CGPoint.zero, animated: false)
}
}
Combinadas las respuestas anteriores, ahora debería funcionar:
talePageText.scrollEnabled = false
talePageText.textColor = UIColor.blackColor()
talePageText.font = UIFont(name: "Bradley Hand", size: 24.0)
talePageText.contentOffset = CGPointZero
talePageText.scrollRangeToVisible(NSRange(location:0, length:0))
talePageText.scrollEnabled = true
Como ninguna de estas soluciones funcionó para mí y perdí mucho tiempo juntando soluciones, finalmente esto me solucionó.
override func viewWillAppear(animated: Bool) {
dispatch_async(dispatch_get_main_queue(), {
let desiredOffset = CGPoint(x: 0, y: -self.textView.contentInset.top)
self.textView.setContentOffset(desiredOffset, animated: false)
})
}
Esto es realmente tonto de que este no sea el comportamiento predeterminado para este control.
Espero que esto ayude a alguien más.
Creo que la razón por la que algunas personas tienen problemas con este problema es porque están tratando de establecer la posición de desplazamiento de TextView
, antes de que TextView
este TextView
.
No hay nada para desplazarse, cuando el TextView
aún no ha aparecido.
Debes esperar a que TextView
aparezca primero, y luego establecer su posición de desplazamiento dentro del método viewDidAppear
como se muestra a continuación:
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
textView.setContentOffset(CGPoint.zero, animated: false)
}
Estaba usando attributeString en HTML con la vista de texto no editable. Establecer el desplazamiento del contenido tampoco me funcionó. Esto funcionó para mí: desactivar desplazamiento habilitado, establecer el texto y luego habilitar el desplazamiento de nuevo
[yourTextView setScrollEnabled:NO];
yourTextView.text = yourtext;
[yourTextView setScrollEnabled:YES];
Este código resuelve el problema y también ayuda a evitar el desplazamiento automático innecesario hasta el final de textView. Simplemente use el método setTextPreservingContentOffset:
lugar de configurar texto a textView directamente.
@interface ViewController () {
__weak IBOutlet UITextView *textView;
CGPoint lastContentOffset;
NSTimer *autoscrollTimer;
BOOL revertAnyContentOffsetChanges;
}
@end
@implementation ViewController
- (void)viewDidLoad
{
[super viewDidLoad];
[textView addObserver:self forKeyPath:@"contentOffset" options:NSKeyValueObservingOptionNew context:nil];
}
- (void)dealloc
{
[textView removeObserver:self forKeyPath:@"contentOffset"];
}
- (void)setTextPreservingContentOffset:(NSString *)text
{
lastContentOffset = textView.contentOffset;
[autoscrollTimer invalidate];
revertAnyContentOffsetChanges = YES;
textView.text = text;
autoscrollTimer = [NSTimer scheduledTimerWithTimeInterval:1 target:self selector:@selector(enableScrolling:) userInfo:nil repeats:NO];
autoscrollTimer.tolerance = 1;
}
- (void)enableScrolling:(NSTimer *)timer
{
revertAnyContentOffsetChanges = NO;
}
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
{
if (revertAnyContentOffsetChanges && [keyPath isEqualToString:@"contentOffset"] && [[change valueForKey:@"new"] CGPointValue].y != lastContentOffset.y) {
[textView setContentOffset:lastContentOffset animated:NO];
}
}
@end
Esto funcionó para mí. Se basa en la respuesta de RyanTCB pero es la variante Objective-C de la misma solución:
- (void) viewWillAppear:(BOOL)animated {
// For some reason the text view, which is a scroll view, did scroll to the end of the text which seems to hide the imprint etc at the beginning of the text.
// On some devices it is not obvious that there is more text when the user scrolls up.
// Therefore we need to scroll textView to the top.
[self.textView scrollRangeToVisible:NSMakeRange(0, 0)];
}
Intenta esto para mover el cursor a la parte superior del texto.
NSRange r = {0,0};
[yourTextView setSelectedRange:r];
Vea cómo va eso. Asegúrate de llamar a esto después de que todos tus eventos hayan sido despedidos o lo que sea que estés haciendo ya está hecho.
Intenta usar esta solución de 2 líneas:
view.layoutIfNeeded()
textView.contentOffset = CGPointMake(textView.contentInset.left, textView.contentInset.top)
Mi problema es establecer textView para desplazarse hacia arriba cuando apareció la vista. Para iOS 10.3.2 y Swift 3.
Solución 1:
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
// It doesn''t work. Very strange.
self.textView.setContentOffset(CGPoint.zero, animated: false)
}
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
// It works, but with an animation effection.
self.textView.setContentOffset(CGPoint.zero, animated: false)
}
Solución 2:
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
// It works.
self.textView.contentOffset = CGPoint.zero
}
No estoy seguro si entiendo tu pregunta, pero ¿estás intentando simplemente desplazar la vista hacia la parte superior? Si es así deberías hacer
[textview scrollRectToVisible:CGRectMake(0,0,1,1) animated:YES];
Para iOS 10 y Swift 3 lo hice:
override func viewDidLoad() {
super.viewDidLoad()
textview.isScrollEnabled = false
}
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
textView.isScrollEnabled = true
}
Funcionó para mí, no estoy seguro si está teniendo el problema con la última versión de Swift y iOS.
Para mí bien funciona este código:
textView.attributedText = newText //or textView.text = ...
//this part of code scrolls to top
textView.contentOffset.y = -64
textView.scrollEnabled = false
textView.layoutIfNeeded() //if don''t work, try to delete this line
textView.scrollEnabled = true
Para desplazarse a la posición exacta y mostrarla en la parte superior de la pantalla, utilizo este código:
var scrollToLocation = 50 //<needed position>
textView.contentOffset.y = textView.contentSize.height
textView.scrollRangeToVisible(NSRange.init(location: scrollToLocation, length: 1))
Configurando contentOffset.y se desplaza al final del texto, y luego scrollRangeToVisible se desplaza hasta el valor de scrollToLocation. De este modo, la posición necesaria aparece en la primera línea de scrollView.
Para mí en iOS 9, se detuvo para que funcionase para mí con una cadena atribuida con el método scrollRangeToVisible (la 1 fila era con letra en negrita, otras filas eran con fuente regular)
Entonces tuve que usar:
textViewMain.attributedText = attributedString
textViewMain.scrollRangeToVisible(NSRange(location:0, length:0))
delay(0.0, closure: {
self.textViewMain.scrollRectToVisible(CGRectMake(0, 0, 10, 10), animated: false)
})
donde el retraso es:
func delay(delay:Double, closure:()->Void) {
dispatch_after(
dispatch_time(
DISPATCH_TIME_NOW,
Int64(delay * Double(NSEC_PER_SEC))
),
dispatch_get_main_queue(), closure)
}
Problema resuelto: iOS = 10.2 Swift 3 UITextView
Acabo de usar la siguiente línea:
displayText.contentOffset.y = 0
Si alguien tiene este problema en iOS 8, encontré que simplemente establecía la UITextView''s
texto UITextView''s
, y luego scrollRangeToVisible
con un NSRange
con la location:0
, length:0
, funcionó. Mi vista de texto no era editable, y probé tanto seleccionable como no seleccionable (ninguna configuración afectó el resultado). Aquí hay un ejemplo de Swift:
myTextView.text = "Text that is long enough to scroll"
myTextView.scrollRangeToVisible(NSRange(location:0, length:0))
Swift 2 Respuesta:
textView.scrollEnabled = false
/* Set the content of your textView here */
textView.scrollEnabled = true
Esto evita que textView se desplace hasta el final del texto después de configurarlo.
Tengo una respuesta actualizada que hará que la vista de texto aparezca correctamente y sin que el usuario experimente una animación de desplazamiento.
override func viewWillAppear(animated: Bool) {
dispatch_async(dispatch_get_main_queue(), {
self.introductionText.scrollRangeToVisible(NSMakeRange(0, 0))
})
Tuve el problema, pero en mi caso, la vista de texto es la subvista de una vista personalizada y se agregó a ViewController. Ninguna de las soluciones funcionó para mí. Para resolver el problema, se agregó 0.1 segundos de retraso y luego habilitó el desplazamiento. Funcionó para mí
textView.isScrollEnabled = false
..
textView.text = // set your text here
let dispatchTime = DispatchTime.now() + 0.1
DispatchQueue.main.asyncAfter(deadline: dispatchTime) {
self.textView.isScrollEnabled = true
}
Vocación
scrollRangeToVisible(NSMakeRange(0, 0))
funciona pero llámalo
override func viewDidAppear(animated: Bool)
Y aquí está mi solución ...
override func viewDidLoad() {
textView.scrollEnabled = false
textView.text = "your text"
}
override func viewDidAppear(animated: Bool) {
textView.scrollEnabled = true
}
solo puedes usar este código
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
textView.scrollRangeToVisible(NSMakeRange(0, 0))
}
En Swift 3:
viewWillLayoutSubviews es el lugar para hacer cambios. viewWillAppear también debería funcionar, pero lógicamente, el diseño debería realizarse en viewWillLayoutSubviews .
En cuanto a los métodos, scrollRangeToVisible y setContentOffset funcionarán. Sin embargo, setContentOffset permite activar o desactivar la animación.
Suponga que UITextView se denomina comoUITextView . Aquí está el código:
// Connects to the TextView in the interface builder.
@IBOutlet weak var yourUITextView: UITextView!
/// Overrides the viewWillLayoutSubviews of the super class.
override func viewWillLayoutSubviews() {
// Ensures the super class is happy.
super.viewWillLayoutSubviews()
// Option 1:
// Scrolls to a range of text, (0,0) in this very case, animated.
yourUITextView.scrollRangeToVisible(NSRange(location: 0, length: 0))
// Option 2:
// Sets the offset directly, optional animation.
yourUITextView.setContentOffset(CGPoint(x: 0, y: 0), animated: false)
}
UITextView*note;
[note setContentOffset:CGPointZero animated:YES];
Esto lo hace por mí.
Versión Swift (Swift 4.1 con iOS 11 en Xcode 9.3):
note.setContentOffset(CGPoint.zero, animated: true)
-(void) viewDidAppear:(BOOL)animated{
[mytextView scrollRangeToVisible:NSMakeRange(0,0)];}
- (void)viewWillAppear:(BOOL)animated{
[mytextView scrollRangeToVisible:NSMakeRange(0,0)];}
-
ViewWillappear
lo hará de manera instantánea antes de que el usuario lo note, pero la secciónViewDidDisappear
lo animará de forma perezosa. -
[mytextView setContentOffset:CGPointZero animated:YES];
NO funciona a veces (no sé por qué), así que use scrollrangetovisible rather.
-(void)viewWillLayoutSubviews{
[super viewWillLayoutSubviews];
[textview setContentOffset:CGPointZero animated:NO];
}
[self.textView scrollRectToVisible:CGRectMake(0, 0, 320, self.textView.frame.size.height) animated:NO];
[txtView setContentOffset:CGPointMake(0.0, 0.0) animated:YES];
Esta línea de código funciona para mí.