在iPhone音乐应用程序中,选择“艺术家”,“歌曲”或“专辑”将在UI的右侧显示一个tableView,其中包含单个字母的垂直列表,从而可以快速滚动。如何在我的应用程序中启用此功能?
干杯,道格
Answers:
提供您自己的索引字符:
- (NSArray *)sectionIndexTitlesForTableView:(UITableView *)tableView {
return[NSArray arrayWithObjects:@"a", @"e", @"i", @"m", @"p", nil];
}
然后:
- (NSInteger)tableView:(UITableView *)tableView sectionForSectionIndexTitle:(NSString
*)title atIndex:(NSInteger)index {
return <yourSectionIndexForTheSectionForSectionIndexTitle >;
}
您将需要一些部分。
您还需要考虑的是本地化每种语言的部分。深入研究后,我发现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返回值,但是如果您身处一个角落并且不想为字母表中的每个字母制作一个部分,是肯定的解决方法。抱歉,请提前输入任何代码。:P
- (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是NSDictionaries的NSArray,我将其列出到UITableView中。
这是Kyle函数的修改版本,可以处理单击没有字符串的索引的情况:
- (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;
}
如果您使用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,请重写UITableViewDataSource类中的SectionIndexTitles(UITableView)方法。只需返回一个字符串数组,子类将负责其余的工作。
class TableViewDataSource : UITableViewDataSource
{
public override string[] SectionIndexTitles(UITableView tableView)
{
return new string[] { /*your string values */};
}
}
*仅向使用C#和Mono(.NET)编写iPhone应用程序的人提供提示。:)