В музыкальном приложении для iPhone при выборе «Исполнитель», «Песни» или «Альбомы» отображается tableView с вертикальным списком отдельных букв в правой части пользовательского интерфейса, который обеспечивает быструю прокрутку. Как включить эту функцию в моем приложении?
Привет, Дуг
ios
iphone
objective-c
uitableview
дугла
источник
источник
Еще вам нужно учесть локализацию разделов для каждого языка. Немного покопавшись, я обнаружил,
UILocalizedIndexedCollation
что это весьма полезно:- (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
источник
Я придумал альтернативный подход к работе с однобуквенным алфавитным списком без использования разделов. Он похож на ответ Zaph, но вместо того, чтобы получить какое-либо значение при возврате нового индекса (поскольку у нас всегда будет 1 раздел), мы вычисляем индекс для местоположения первого элемента в массиве, который начинается с определенного символа, а затем прокручиваем к нему.
Обратной стороной является необходимость поиска в массиве каждый раз (это ужасно?), Однако я не заметил каких-либо задержек или медленного поведения в симуляторе iOS или на моем 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; }
добавление свойства для хранения последнего выбранного индекса, например
@property (assign, nonatomic) NSInteger previousSearchIndex;
и сохраняя это свойство каждый раз, например:
- (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; }
и обновление
scrollToRow
кода, например:[tableView scrollToRowAtIndexPath:newIndexPath atScrollPosition:UITableViewScrollPositionTop animated:YES];
Сделайте этот метод еще лучше и с красивой анимацией.
источник
Группа людей спрашивала, можно ли это сделать без разделов. Я хотел того же, и я нашел решение, которое может быть немного сомнительным и не возвращает значение sectionForSectionIndexTitle, но если вы находитесь в углу и не хотите создавать раздел для каждой буквы алфавита, это верное решение. Извините за любой код нацистов заранее. :П
- (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++; } }
Он отлично работает, если вы получаете большой объем данных, и для его разбиения потребуется много работы. :) Пытался использовать общие переменные, чтобы вы знали, что я делаю. d_itemsInTable - это NSArray NSDictionaries, которые я перечисляю в UITableView.
источник
Вот модифицированная версия функции Кайла, которая обрабатывает случай щелчка по индексу, для которого у вас нет строки:
- (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; }
источник
Если вы используете a
NSFetchedResultsController
, вы можете просто сделать:- (NSArray *)sectionIndexTitlesForTableView:(UITableView *)tableView { return [frc sectionIndexTitles]; } - (NSInteger)tableView:(UITableView *)tableView sectionForSectionIndexTitle:(NSString *)title atIndex:(NSInteger)index { return [frc sectionForSectionIndexTitle:title atIndex:index]; }
источник
Реализуйте методы делегата
-sectionIndexTitlesForTableView:
и-tableView:sectionForSectionIndexTitle:atIndex:
См.
UITableViewDataSource
Документацию для получения дополнительной информации.источник
Вот простое решение в Swift, если у вас есть заголовки заголовков в массиве. Если заголовок найти не удалось, он вернет предыдущий индекс в массиве.
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 }
источник
return self.headerTitles.count - self.headerTitles.filter{$0 > title}.count
чтобы она возвращала индекс первой, а не последней совпадающей секции для данного заголовка индекса.Если вы используете MonoTouch, переопределите метод SectionIndexTitles (UITableView) в классе UITableViewDataSource. Просто верните массив строк, а все остальное сделает подкласс.
class TableViewDataSource : UITableViewDataSource { public override string[] SectionIndexTitles(UITableView tableView) { return new string[] { /*your string values */}; } }
* просто подсказка для тех из нас, кто использует C # и Mono (.NET) для написания приложений для iPhone. :)
источник