ios - tamaño - teclado ipad separado como juntar
¿Cómo filtrar UICollectionView y mantener el teclado arriba? (9)
Acabo de añadir
[searchBar becomeFirstResponder];
después de llamar
[collectionView reloadData];
He agregado una UISearchBar
a una UICollectionView
y en la searchBar:textDidChange:
delegada searchBar:textDidChange:
filtre mi modelo y llame a [collectionView reloadData]
. reloadData
(así como reloadSection, etc.) quiere quitar el primer respondedor del campo de texto de la barra de búsqueda, descartando así el teclado.
Estoy tratando de construir un filtro de "actualización en vivo" y es molesto que el teclado desaparezca después de cada carácter escrito.
¿Algunas ideas?
Acabo de crear una pequeña aplicación de prueba. El siguiente código no oculta el teclado al ingresar caracteres en la barra de búsqueda. Dicho esto, [UITableView reloadData] no renuncia al respondedor.
- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section {
return arc4random() % 10;
}
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath {
UICollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:@"Cell" forIndexPath:indexPath];
return cell;
}
- (void)searchBar:(UISearchBar *)searchBar textDidChange:(NSString *)searchText {
[self.collectionView reloadData];
}
¿Estás seguro, no te estás resignando en algún lado?
Así es como lo logré. Tenía mi barra UISearchBar como vista complementaria de encabezado en mi vista de colección. En el texto de cambio para el delegado de la barra de búsqueda, puse una marca de que la búsqueda está activa (o no) y recargué la vista de colección
- (void)searchBar:(UISearchBar *)_searchBar textDidChange:(NSString *)searchText
{
if([searchText isEqualToString:@""])
{
activeSearch = FALSE;
}
else
{
activeSearch = TRUE;
}
[self filterContentForSearchText:searchText scope:nil];
[self.collectionView reloadData];
}
Luego, en el cellForItemAtIndexPath, compruebo si el teclado responde primero y la búsqueda está activa; si no, lo hago primero:
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
...
if(activeSearch && ![searchBar isFirstResponder])
{
[searchBar becomeFirstResponder];
}
}
Creo que está llamando al método -resignFirstResponder
en el delegado de la barra de búsqueda, lo que causa cada vez que ingresa el valor que se descarta
Está en la ruta correcta acerca de los métodos de la fuente de datos y recargar datos. Use una matriz para almacenar todos los valores, otra matriz para cargar la vista de colección y en cada letra ingresada en el filtro de la barra de búsqueda, cargue la matriz de la fuente de datos y luego vuelva a cargar
Bueno, creo que es mejor mantener el teclado. Ese es el estilo de IU correcto una vez que haya terminado de ingresar el texto para buscar, puede descartarlo manualmente. Creo que es la mejor opción para un filtro de actualización en vivo.
Si está utilizando un botón para buscar, puede incluir la opción de ocultación del teclado allí. Pero la actualización en vivo no se puede implementar cuando se usa dicha opción.
En la función de delegado de searchBar, uso performBatchUpdates, primero, recargo collectionView luego llamo [self.searchBar becomeFirstResponder] para mostrar el teclado
- (void)searchBarTextDidBeginEditing:(UISearchBar *)searchBar{
[self setEditing:NO animated:YES];
[searchBar setShowsCancelButton:YES animated:YES];
[self.collectionView performBatchUpdates:^{
[self.collectionView reloadData];
} completion:^(BOOL finished) {
[self.searchBar becomeFirstResponder];
}];
}
La respuesta es no volver a cargar la sección que tiene el campo de texto. Resolví este problema al colocar todos los elementos en una sola búsqueda, por lo que fue posible volver a cargar esa única sección.
La pantalla existente que estaba modificando mostraba el índice a la derecha con las letras para navegar a cada sección, lo que significa que había muchas secciones que dificultan saber cómo volver a cargar cada una de esas secciones sin desordenar el estado interno. Para que funcione cuando el campo de texto se convierte en el primer respondedor, la organización de la vista de colección cambia para colocar todos los elementos en una sola sección que se vuelve a cargar cuando se ejecuta la búsqueda. Ahora la sección superior no se vuelve a cargar, por lo que no pierde el enfoque.
De esta manera no es necesario ningún comportamiento indefinido como las otras respuestas enumeradas para esta pregunta.
Me encontré con el mismo problema recientemente y me tomó un tiempo arreglarlo. El problema es que cuando el campo de texto está anidado en ReusableCollectionView, lo siguiente no funciona.
[self.collectionView reloadData];
[self.textField becomeFirstResponder];
Además, para mí funcionó bien en el simulador pero no funcionó en el dispositivo.
Configuración del controlador de vista como campo de texto delegado e implementación
- (BOOL)textFieldShouldEndEditing:(UITextField *)textField {
return NO;
}
no funcionó porque la vista de la colección de resultados no se actualizó. Mi conjetura es que, antes de volver a cargar su colección de vistas, intenta eliminar el foco de todos los controles anidados, pero no puede, devolvemos NO del método de delegado de campo de texto.
Así que la solución para mí fue dejar que el sistema eliminara el foco del campo de texto y luego recuperarlo después de la recarga. La pregunta era cuándo hacer eso.
Primero, he tratado de hacerlo en el
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
pero cuando no había elementos en la colección (lo cual es un caso normal durante el filtrado), este método no fue llamado.
Eventualmente resolví esto de la siguiente manera. Creé la subclase UICollectionReusableView implementando dos métodos: -prepareForReuse y -drawRect :. El primero contiene la llamada -setNeedsDesplay, que programa la llamada drawRect en el siguiente ciclo de dibujo. El segundo restaura el enfoque llamando a [self.textField becomeFirstResponder] si el indicador correspondiente está establecido en YES. Así que la idea era llamar a BecomeFirstResponder "más tarde" pero no demasiado tarde, de lo contrario ocurre un "salto" extraño de teclado.
Mi vista de colección reutilizable personalizada se ve así:
@interface MyCollectionReusableView : UICollectionReusableView
@property (nonatomic, assign) BOOL restoreFocus;
@property (nonatomic, strong) UITextField *textField;
@end
@implementation MyCollectionReusableView
@synthesize restoreFocus;
@synthesize textField;
- (void)setTextField:(UITextField *)value {
textField = value;
[self addSubview:textField];
}
- (void)drawRect:(CGRect)rect {
[super drawRect:rect];
if (self.restoreFocus) {
[self.textField becomeFirstResponder];
}
}
- (void)prepareForReuse {
[self setNeedsDisplay];
}
Luego en mi View Controller:
- (void)viewDidLoad {
[super viewDidLoad];
[self.collectionView registerClass:[MyCollectionReusableView class] forSupplementaryViewOfKind:UICollectionElementKindSectionHeader withReuseIdentifier:HeaderReuseIdentifier];
[self.textField addTarget:self action:@selector(textFieldDidChange:) forControlEvents:UIControlEventEditingChanged];
}
- (UICollectionReusableView *)collectionView:(UICollectionView *)collectionView viewForSupplementaryElementOfKind:(NSString *)kind atIndexPath:(NSIndexPath *)indexPath {
if (UICollectionElementKindSectionHeader == kind) {
MyCollectionReusableView *view = [collectionView dequeueReusableSupplementaryViewOfKind:UICollectionElementKindSectionHeader withReuseIdentifier:HeaderReuseIdentifier forIndexPath:indexPath];
//add textField to the reusable view
if (nil == view.textField) {
view.textField = self.textField;
}
//set restore focus flag to the reusable view
view.restoreFocus = self.restoreFocus;
self.restoreFocus = NO;
return view;
}
return nil;
}
- (void)textFieldDidChange:(UITextField *)textField {
self.restoreFocus = YES;
[self.collectionView reloadData];
}
Probablemente no sea la solución más elegante, pero funciona. :)
Resuelto:
UISearchBar *searchBar = [[UISearchBar alloc] initWithFrame:CGRectMake(0.0, 0.0, 726.0f, 44.0f)];
[_collectionView addSubview:searchBar];
searchBar.delegate = self;
[(UICollectionViewFlowLayout *)_collectionView.collectionViewLayout setSectionInset:UIEdgeInsetsMake(64, 20, 20, 20)];
- (void)searchBar:(UISearchBar *)searchBar textDidChange:(NSString *)searchText {
[_collectionView reloadData];
[searchBar becomeFirstResponder];
}
Si ha agregado UISearchBar
como encabezado a UICollectionView
la llamada reloadData
"actualizará" el encabezado eliminando y volviendo a agregar UISearchBar
lo que UISearchBar
que pierda el firstResponder
.
Puede agregar su UISearchBar
de otra manera, sin usar el encabezado, o anular reloadData
, verificar si la barra de búsqueda está actualmente en el primer Respuesta, y si es así después de llamar a super
, haga:
// If we''ve lost first-responder, restore it.
if ((wasFirstResponder) && (![self.searchBar isFirstResponder])) {
[self.searchBar becomeFirstResponder];
}