ios iPhone UITableView。如何像音乐应用那样开启单字母字母列表?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/1655119/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
iPhone UITableView. How do turn on the single letter alphabetical list like the Music App?
提问by dugla
In the iPhone music app, selecting Artist, Songs, or Albums presents a tableView with a verticl list of single letters at the righthand side of the UI that enables rapid scrolling. How do I enable this functionality in my app?
在 iPhone 音乐应用程序中,选择艺术家、歌曲或专辑会在 UI 的右侧显示一个带有单个字母的垂直列表的 tableView,可以快速滚动。如何在我的应用中启用此功能?
Cheers, Doug
干杯,道格
回答by zaph
Supply your own index characters:
提供您自己的索引字符:
- (NSArray *)sectionIndexTitlesForTableView:(UITableView *)tableView {
return[NSArray arrayWithObjects:@"a", @"e", @"i", @"m", @"p", nil];
}
and then:
进而:
- (NSInteger)tableView:(UITableView *)tableView sectionForSectionIndexTitle:(NSString
*)title atIndex:(NSInteger)index {
return <yourSectionIndexForTheSectionForSectionIndexTitle >;
}
You will need sections.
您将需要部分。
回答by rwyland
Something else you have to consider is localizing the sections for each language. After digging around a bit, I found UILocalizedIndexedCollation
to be quite useful:
您必须考虑的另一件事是本地化每种语言的部分。经过一番挖掘,我发现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
https://developer.apple.com/documentation/uikit/uilocalizedindexedcollation
回答by Kyle Clegg
I came up with an alternative approach to handling a single letter alphabet list without using sections. It's similar to Zaph's answer but instead of getting any value from returning a new index (since we'll always have 1 section), we calculate the index for the location of the first item in the array that begins with a certain character, then scroll to it.
我想出了一种替代方法来处理单个字母表列表而不使用节。它类似于 Zaph 的答案,但不是从返回新索引中获取任何值(因为我们总是有 1 个部分),我们计算数组中以某个字符开头的第一个项目的位置的索引,然后滚动到它。
The downside is this requires searching the array every time (is this absolutely terrible?), however I didn't notice any lag or slow behavior in the iOS simulator or on my iPhone 4S.
缺点是每次都需要搜索数组(这绝对可怕吗?),但是我没有注意到 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;
}
adding property to store last selected index like
添加属性以存储最后选择的索引,例如
@property (assign, nonatomic) NSInteger previousSearchIndex;
and storing this property every time like:
并每次都存储此属性,例如:
- (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;
}
and updating scrollToRow
code like:
并更新scrollToRow
代码,如:
[tableView scrollToRowAtIndexPath:newIndexPath atScrollPosition:UITableViewScrollPositionTop animated:YES];
Do this method even better and with nice animation.
用漂亮的动画更好地执行此方法。
回答by krut
A bunch of people asked if it was possible to do this without sections. I wanted the same thing and I found a solution which might be a little shady and doesn't return a value to sectionForSectionIndexTitle but if you are in a corner and don't want to have to make a section for every letter of the alphabet this is a sure fix. Sorry to any code Nazis in advance. :P
很多人问是否可以在没有部分的情况下做到这一点。我想要同样的东西,我找到了一个可能有点阴暗的解决方案,并且不会向 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++;
}
}
It works great if you are getting a large amount of data and sectioning it would take a bunch of work. :) Tried to use generic variables so you knew what I was doing. d_itemsInTable is an NSArray of NSDictionaries that I'm listing out to the UITableView.
如果您获得大量数据并对其进行切片将需要大量工作,它会非常有效。:) 尝试使用通用变量,所以你知道我在做什么。d_itemsInTable 是我列出到 UITableView 的 NSDictionaries 的 NSArray。
回答by Danny
Here is a modified version of Kyle's function that handles the case of clicking an index for which you do not have a string:
这是 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;
}
回答by Snowman
If you're using a NSFetchedResultsController
, you can just do:
如果您使用的是 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];
}
回答by Samah
Here's a simple solution in Swift, assuming you have your title headers in an array. If the title couldn't be found, it will return the previous index in the array.
这是 Swift 中的一个简单解决方案,假设您的标题标题位于数组中。如果找不到标题,它将返回数组中的前一个索引。
func sectionIndexTitlesForTableView(tableView: UITableView) -> [String]? {
return "ABCDEFGHIJKLMNOPQRSTUVWXYZ".characters.flatMap{String(class TableViewDataSource : UITableViewDataSource
{
public override string[] SectionIndexTitles(UITableView tableView)
{
return new string[] { /*your string values */};
}
}
)}
}
func tableView(tableView: UITableView, sectionForSectionIndexTitle title: String, atIndex index: Int) -> Int {
return self.headerTitles.filter{##代码## <= title}.count - 1
}
回答by Alex Reynolds
Implement the delegate methods -sectionIndexTitlesForTableView:
and -tableView:sectionForSectionIndexTitle:atIndex:
实现委托方法-sectionIndexTitlesForTableView:
和-tableView:sectionForSectionIndexTitle:atIndex:
See the UITableViewDataSource
documentation for more info.
有关UITableViewDataSource
更多信息,请参阅文档。
回答by benhorgen
If you're using MonoTouch, override the SectionIndexTitles(UITableView) method in the UITableViewDataSource class. Just return an array of strings and the subclass takes care of the rest.
如果您使用 MonoTouch,请覆盖 UITableViewDataSource 类中的 SectionIndexTitles(UITableView) 方法。只需返回一个字符串数组,子类会处理剩下的事情。
##代码##*just a hint for those of us using C# and Mono (.NET) to write iPhone apps. :)
*只是对我们这些使用 C# 和 Mono (.NET) 编写 iPhone 应用程序的人的一个提示。:)