En la aplicación de música del iPhone, al seleccionar Artista, Canciones o Álbumes, se presenta una vista de tabla con una lista vertical de letras individuales en el lado derecho de la interfaz de usuario que permite un desplazamiento rápido. ¿Cómo habilito esta funcionalidad en mi aplicación?
Saludos, Doug
ios
iphone
objective-c
uitableview
dugla
fuente
fuente
Otra cosa que debes considerar es la localización de las secciones para cada idioma. Después de investigar un poco, me pareció
UILocalizedIndexedCollation
bastante útil:- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section { return [[[UILocalizedIndexedCollation currentCollation] sectionTitles] objectAtIndex:section]; } - (NSArray *)sectionIndexTitlesForTableView:(UITableView *)tableView { return [[UILocalizedIndexedCollation currentCollation] sectionIndexTitles]; } - (NSInteger)tableView:(UITableView *)tableView sectionForSectionIndexTitle:(NSString *)title atIndex:(NSInteger)index { return [[UILocalizedIndexedCollation currentCollation] sectionForSectionIndexTitleAtIndex:index]; }
https://developer.apple.com/documentation/uikit/uilocalizedindexedcollation
fuente
Se me ocurrió un enfoque alternativo para manejar una lista alfabética de una sola letra sin usar secciones. Es similar a la respuesta de Zaph, pero en lugar de obtener cualquier valor al devolver un nuevo índice (ya que siempre tendremos 1 sección), calculamos el índice para la ubicación del primer elemento en la matriz que comienza con un cierto carácter, luego nos desplazamos lo.
La desventaja es que esto requiere buscar la matriz cada vez (¿es esto absolutamente terrible?), Sin embargo, no noté ningún retraso o comportamiento lento en el simulador de iOS o en mi iPhone 4S.
- (NSArray *)sectionIndexTitlesForTableView:(UITableView *)tableView { return[NSArray arrayWithObjects:@"A", @"B", @"C", @"D", @"E", @"F", @"G", @"H", @"I", @"J", @"K", @"L", @"M", @"N", @"O", @"P", @"Q", @"R", @"S", @"T", @"U", @"V", @"W", @"X", @"Y", @"Z", nil]; } - (NSInteger)tableView:(UITableView *)tableView sectionForSectionIndexTitle:(NSString *)title atIndex:(NSInteger)index { NSInteger newRow = [self indexForFirstChar:title inArray:self.yourStringArray]; NSIndexPath *newIndexPath = [NSIndexPath indexPathForRow:newRow inSection:0]; [tableView scrollToRowAtIndexPath:newIndexPath atScrollPosition:UITableViewScrollPositionTop animated:NO]; return index; } // Return the index for the location of the first item in an array that begins with a certain character - (NSInteger)indexForFirstChar:(NSString *)character inArray:(NSArray *)array { NSUInteger count = 0; for (NSString *str in array) { if ([str hasPrefix:character]) { return count; } count++; } return 0; }
agregando propiedad para almacenar el último índice seleccionado como
@property (assign, nonatomic) NSInteger previousSearchIndex;
y almacenar esta propiedad cada vez como:
- (NSInteger)indexForFirstChar:(NSString *)character inArray:(NSArray *)array { NSUInteger count = 0; for (NSString *str in array) { if ([str hasPrefix:character]) { self.previousSearchIndex = count; return count; } count++; } return self.previousSearchIndex; }
y actualizando
scrollToRow
código como:[tableView scrollToRowAtIndexPath:newIndexPath atScrollPosition:UITableViewScrollPositionTop animated:YES];
Haz este método aún mejor y con buena animación.
fuente
Mucha gente preguntó si era posible hacer esto sin secciones. Quería lo mismo y encontré una solución que puede ser un poco turbia y no devuelve un valor a sectionForSectionIndexTitle, pero si estás en una esquina y no quieres tener que hacer una sección para cada letra del alfabeto, esto es una solución segura. Perdón por cualquier código nazis de antemano. :PAG
- (NSArray *)sectionIndexTitlesForTableView:(UITableView *)tableView { if (thisTableDataIsShowing) { NSMutableArray *charactersForSort = [[NSMutableArray alloc] init]; for (NSDictionary *item in d_itemsInTable) { if (![charactersForSort containsObject:[[item valueForKey:@"character_field_to_sort_by"] substringToIndex:1]]) { [charactersForSort addObject:[[item valueForKey:@"character_field_to_sort_by"] substringToIndex:1]]; } } return charactersForSort; } return nil; } - (NSInteger)tableView:(UITableView *)tableView sectionForSectionIndexTitle:(NSString *)title atIndex:(NSInteger)index { BOOL found = NO; NSInteger b = 0; for (NSDictionary *item in d_itemsInTable) { if ([[[item valueForKey:@"character_field_to_sort_by"] substringToIndex:1] isEqualToString:title]) if (!found) { [d_yourTableView scrollToRowAtIndexPath:[NSIndexPath indexPathForRow:b inSection:0] atScrollPosition:UITableViewScrollPositionTop animated:NO]; found = YES; } b++; } }
Funciona muy bien si obtiene una gran cantidad de datos y dividirlos requeriría mucho trabajo. :) Intenté usar variables genéricas para que supieras lo que estaba haciendo. d_itemsInTable es un NSArray de NSDictionaries que incluyo en UITableView.
fuente
Aquí hay una versión modificada de la función de Kyle que maneja el caso de hacer clic en un índice para el que no tiene una cadena:
- (NSInteger)indexForFirstChar:(NSString *)character inArray:(NSArray *)array { char testChar = [character characterAtIndex:0]; __block int retIdx = 0; __block int lastIdx = 0; [array enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) { char firstChar = [obj characterAtIndex:0]; if (testChar == firstChar) { retIdx = idx; *stop = YES; } //if we overshot the target, just use whatever previous one was if (testChar < firstChar) { retIdx = lastIdx; *stop = YES; } lastIdx = idx; }]; return retIdx; }
fuente
Si está usando un
NSFetchedResultsController
, puede hacer lo siguiente:- (NSArray *)sectionIndexTitlesForTableView:(UITableView *)tableView { return [frc sectionIndexTitles]; } - (NSInteger)tableView:(UITableView *)tableView sectionForSectionIndexTitle:(NSString *)title atIndex:(NSInteger)index { return [frc sectionForSectionIndexTitle:title atIndex:index]; }
fuente
Implementar los métodos delegados
-sectionIndexTitlesForTableView:
y-tableView:sectionForSectionIndexTitle:atIndex:
Consulte la
UITableViewDataSource
documentación para obtener más información.fuente
Aquí hay una solución simple en Swift, asumiendo que tiene los encabezados de sus títulos en una matriz. Si no se pudo encontrar el título, devolverá el índice anterior en la matriz.
func sectionIndexTitlesForTableView(tableView: UITableView) -> [String]? { return "ABCDEFGHIJKLMNOPQRSTUVWXYZ".characters.flatMap{String($0)} } func tableView(tableView: UITableView, sectionForSectionIndexTitle title: String, atIndex index: Int) -> Int { return self.headerTitles.filter{$0 <= title}.count - 1 }
fuente
return self.headerTitles.count - self.headerTitles.filter{$0 > title}.count
retorno para devolver el índice de la primera sección coincidente en lugar de la última para el título de índice dado.Si está utilizando MonoTouch, anule el método SectionIndexTitles (UITableView) en la clase UITableViewDataSource. Simplemente devuelva una matriz de cadenas y la subclase se encarga del resto.
class TableViewDataSource : UITableViewDataSource { public override string[] SectionIndexTitles(UITableView tableView) { return new string[] { /*your string values */}; } }
* solo una pista para aquellos de nosotros que usamos C # y Mono (.NET) para escribir aplicaciones de iPhone. :)
fuente