iPhone UITableView. How do turn on the single letter alphabetical list like the Music App?

后端 未结 9 898
再見小時候
再見小時候 2020-12-02 04:25

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 scr

相关标签:
9条回答
  • 2020-12-02 05:01

    If you're using a NSFetchedResultsController, you can just do:

    - (NSArray *)sectionIndexTitlesForTableView:(UITableView *)tableView {
        return [frc sectionIndexTitles];
    }
    
    - (NSInteger)tableView:(UITableView *)tableView sectionForSectionIndexTitle:(NSString *)title atIndex:(NSInteger)index {
        return [frc sectionForSectionIndexTitle:title atIndex:index];
    }
    
    0 讨论(0)
  • 2020-12-02 05:02

    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.

    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.

    - (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:

     [tableView scrollToRowAtIndexPath:newIndexPath atScrollPosition:UITableViewScrollPositionTop animated:YES];
    

    Do this method even better and with nice animation.

    0 讨论(0)
  • 2020-12-02 05:05

    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.

    class TableViewDataSource : UITableViewDataSource
    {
      public override string[] SectionIndexTitles(UITableView tableView) 
      { 
        return new string[] { /*your string values */};
      }
    }
    

    *just a hint for those of us using C# and Mono (.NET) to write iPhone apps. :)

    0 讨论(0)
  • 2020-12-02 05:06

    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.

    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
    }
    
    0 讨论(0)
  • 2020-12-02 05:08

    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:

    - (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;
    }
    
    0 讨论(0)
  • 2020-12-02 05:11

    Implement the delegate methods -sectionIndexTitlesForTableView: and -tableView:sectionForSectionIndexTitle:atIndex:

    See the UITableViewDataSource documentation for more info.

    0 讨论(0)
提交回复
热议问题