iphone uiscrollview uitextfield

iphone - Deshabilitar el desplazamiento de UIScrollView cuando UITextField se convierte en el primero en responder



(11)

Basándose en la respuesta de Luke, para manejar el problema de que su solución desactiva por completo el desplazamiento automático, puede desactivarlo selectivamente de la siguiente manera:

// TextFieldScrollView #import <UIKit/UIKit.h> @interface TextFieldScrollView : UIScrollView @property (assign, nonatomic) IBInspectable BOOL preventAutoScroll; @end @implementation TextFieldScrollView - (void)scrollRectToVisible:(CGRect)rect animated:(BOOL)animated { if (self.preventAutoScroll == NO) { [super scrollRectToVisible:rect animated:animated]; } } @end

De esta manera, puede configurarlo completamente en Interface Builder para deshabilitar el desplazamiento automático, pero tiene control total en cualquier momento para volver a habilitarlo (aunque lo que desea es más allá de mí).

Cuando un UITextField , incrustado en un UIScrollView convierte en el primer respondedor, digamos que el usuario escribe un carácter, UIScrollView desplaza automáticamente a ese campo, ¿hay alguna forma de desactivarlo?

Duplicar rdar: // 16538222 sobre


Basándose en la respuesta de Moshe ...

Subclase UIScrollView y anula el siguiente método:

- (void)scrollRectToVisible:(CGRect)rect animated:(BOOL)animated

Déjalo vacío ¡Trabajo hecho!


Como mencionó Taketo, cuando un UITextField se convierte en el primer respondedor, su primera vista principal que es de tipo UIScrollView (si existe) se desplaza para hacer visible ese UITextField . El truco más fácil es simplemente envolver cada UITextField en un UIScrollView (o, idealmente, envolverlos todos en un solo dummy UIScrollView ). Esto es muy similar a la solución de Taketo, pero debería proporcionarle un rendimiento ligeramente mejor, y mantendrá su código (o su interfaz en Interface Builder) mucho más limpio en mi opinión.


Esta es la forma en que lo hago:

Es muy simple, puedes devolver tu propio contentOffset para cualquier scrollRectToVisible.

De esta forma, no está perjudicando el comportamiento normal y el flujo de cosas, simplemente proporcionando la misma funcionalidad en el mismo canal, con sus propias mejoras.

#import <UIKit/UIKit.h> @protocol ExtendedScrollViewDelegate <NSObject> - (CGPoint)scrollView:(UIScrollView*)scrollView offsetForScrollingToVisibleRect:(CGRect)rect; @end @interface ExtendedScrollView : UIScrollView @property (nonatomic, unsafe_unretained) id<ExtendedScrollViewDelegate> scrollToVisibleDelegate; @end #import "ExtendedScrollView.h" @implementation ExtendedScrollView - (void)scrollRectToVisible:(CGRect)rect animated:(BOOL)animated { if (_scrollToVisibleDelegate && [_scrollToVisibleDelegate respondsToSelector:@selector(scrollView:offsetForScrollingToVisibleRect:)]) { [self setContentOffset:[_scrollToVisibleDelegate scrollView:self offsetForScrollingToVisibleRect:rect] animated:animated]; } else { [super scrollRectToVisible:rect animated:animated]; } } @end


He estado luchando con el mismo problema y, finalmente, he encontrado una solución.

Investigué cómo se realiza el desplazamiento automático siguiendo el seguimiento de llamadas, y encontré que se llama a un [UIFieldEditor scrollSelectionToVisible] cuando se escribe una letra en el UITextField . Este método parece actuar en UIScrollView del ancestro más cercano del UITextField .

Por lo tanto, en textFieldDidBeginEditing , al envolver el UITextField con un nuevo UIScrollView con el mismo tamaño (es decir, insertar la vista entre el UITextField y su superview), esto bloqueará el desplazamiento automático. Finalmente, elimine este contenedor en textFieldDidEndEditing .

El código es como:

- (void)textFieldDidBeginEditing:(UITextField*)textField { UIScrollView *wrap = [[[UIScrollView alloc] initWithFrame:textField.frame] autorelease]; [textField.superview addSubview:wrap]; [textField setFrame:CGRectMake(0, 0, textField.frame.size.width, textField.frame.size.height)]; [wrap addSubview: textField]; } - (void)textFieldDidEndEditing:(UITextField*)textField { UIScrollView *wrap = (UIScrollView *)textField.superview; [textField setFrame:CGRectMake(wrap.frame.origin.x, wrap.frame.origin.y, wrap.frame.size.width, textField.frame.size.height)]; [wrap.superview addSubview:textField]; [wrap removeFromSuperview]; }

¡espero que esto ayude!


He intentado con la respuesta de @ TaketoSano, pero parece que no funciona. Mi caso es que no tengo una vista de desplazamiento, solo una vista con varios campos de texto.

Y finalmente, tengo una solución alternativa. Hay dos nombres de notificación predeterminados para el teclado que necesito:

  • UIKeyboardDidShowNotification cuando se UIKeyboardDidShowNotification el teclado;
  • UIKeyboardWillHideNotification cuando el teclado se ocultará.

Aquí está el código de muestra que utilicé:

- (void)viewDidLoad { [super viewDidLoad]; ... NSNotificationCenter * notificationCetner = [NSNotificationCenter defaultCenter]; [notificationCetner addObserver:self selector:@selector(_keyboardWasShown:) name:UIKeyboardDidShowNotification object:nil]; [notificationCetner addObserver:self selector:@selector(_keyboardWillHide:) name:UIKeyboardWillHideNotification object:nil]; } - (void)_keyboardWasShown:(NSNotification *)note { [self.view setFrame:(CGRect){{272.f, 55.f}, {480.f, 315.f}}]; } - (void)_keyboardWillHide:(NSNotification *)note { [self.view setFrame:(CGRect){{272.f, 226.5f}, {480.f, 315.f}}]; }

Aquí, el (CGRect){{272.f, 226.5f}, {480.f, 315.f}} es el marco predeterminado de la vista cuando el teclado está oculto. Y (CGRect){{272.f, 55.f}, {480.f, 315.f}} es el marco de la vista cuando se muestra el teclado.

Y, por cierto, el cambio de marco de la vista se aplicará la animación automáticamente, ¡esto es realmente perfecto!


No conozco ninguna propiedad de UIScrollView que permita eso. Sería una experiencia de usuario deficiente para poder desactivar eso, en mi humilde opinión.

Dicho esto, es posible crear una subclase de UIScrollView y anular algunos de sus métodos para verificar que el UITextfield no sea el primero en responder antes de desplazarse.


Parece UIScrollview que contiene UITextfield, ajusta automáticamente su desplazamiento de contenido; cuando textfield se convertirá en el primer respondedor. Esto puede resolverse agregando primero el campo de texto en la vista de desplazamiento del mismo tamaño y luego añadiendo a la vista de desplazamiento principal. en lugar de agregar directamente en scrollview principal

// Swift let rect = CGRect(x: 0, y: 0, width: 200, height: 50) let txtfld = UITextField() txtfld.frame = CGRect(x: 0, y: 0, width: rect.width, height: rect.height) let txtFieldContainerScrollView = UIScrollView() txtFieldContainerScrollView.frame = rect txtFieldContainerScrollView.addSubview(txtfld) // Now add this txtFieldContainerScrollView in desired UITableViewCell, UISCrollView.. etc self.mainScrollView.addSubview(txtFieldContainerScrollView) // Am33T


Tengo una vista de colección con un campo de texto en la parte superior, que imita el UITableView.tableHeaderView . Este campo de texto está ubicado en el espacio de desplazamiento de contenido negativo para que no interfiera con el resto de la vista de colección. Básicamente estoy detectando si el usuario está realizando o no el desplazamiento en la vista de desplazamiento y si el campo de texto es el primero en responder y si la vista de desplazamiento se está desplazando más allá de la parte superior del recuadro de contenido de la vista de desplazamiento. Este código exacto no necesariamente ayudará a nadie, pero podrían manipularlo para que se ajuste a su caso.

- (void)scrollViewDidScroll:(UIScrollView *)scrollView { // This is solving the issue where making the text field first responder // automatically scrolls the scrollview down by the height of the search bar. if (!scrollView.isDragging && !scrollView.isDecelerating && self.searchField.isFirstResponder && (scrollView.contentOffset.y < -scrollView.contentInset.top)) { [scrollView setContentOffset:CGPointMake(scrollView.contentOffset.x, -scrollView.contentInset.top) animated:NO]; } }


Tuve el mismo problema al deshabilitar el desplazamiento automático de una UITextView es una celda de UITableView . Pude resolverlo usando el siguiente enfoque:

@interface MyTableViewController : UITableViewController<UITextViewDelegate> @implementation MyTableViewController { BOOL preventScrolling; // ... } // ... set self as the delegate of the text view - (void)textViewDidBeginEditing:(UITextView *)textView { preventScrolling = YES; } - (void)scrollViewDidScroll:(UIScrollView *)scrollView { if (preventScrolling) { [self.tableView setContentOffset:CGPointMake(0, -self.tableView.contentInset.top) animated:NO]; } } - (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView { preventScrolling = NO; }

La definición de scrollViewWillBeginDragging se usa para restaurar el comportamiento de desplazamiento predeterminado, cuando el usuario mismo inicia el desplazamiento.


Una forma más fácil de detener el desplazamiento de desplazamiento de la vista cuando selecciona un campo de texto está en su viewController :: viewWillAppear () NO llame a [super viewWillAppear];

A continuación, puede controlar el desplazamiento como lo desee.