82 Stimmen

iPhone UITableView. Wie schaltet man die alphabetische Liste mit nur einem Buchstaben wie in der Musik-App ein?

In der iPhone-Musik-App wird bei der Auswahl von Interpreten, Titeln oder Alben eine tableView mit einer vertikalen Liste von Einzelbuchstaben auf der rechten Seite der Benutzeroberfläche angezeigt, die einen schnellen Bildlauf ermöglicht. Wie kann ich diese Funktionalität in meiner App aktivieren?

Zum Wohl, Doug

133voto

zaph Punkte 110105

Geben Sie Ihre eigenen Indexzeichen ein:

- (NSArray *)sectionIndexTitlesForTableView:(UITableView *)tableView {
    return[NSArray arrayWithObjects:@"a", @"e", @"i", @"m", @"p", nil];
}

und dann:

- (NSInteger)tableView:(UITableView *)tableView sectionForSectionIndexTitle:(NSString
    *)title atIndex:(NSInteger)index {
        return <yourSectionIndexForTheSectionForSectionIndexTitle >;
}

Sie benötigen Abschnitte.

35voto

rwyland Punkte 1627

Ein weiterer Punkt, den Sie berücksichtigen müssen, ist die Lokalisierung der Abschnitte für jede Sprache. Nachdem ich ein wenig herumgestöbert habe, fand ich UILocalizedIndexedCollation als recht nützlich erweisen:

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

33voto

Kyle Clegg Punkte 37388

Ich habe einen alternativen Ansatz gefunden, um eine Alphabetliste mit einem einzigen Buchstaben zu bearbeiten, ohne Abschnitte zu verwenden. Es ist ähnlich wie Zaphs Antwort, aber anstatt einen Wert aus der Rückgabe eines neuen Index zu erhalten (da wir immer 1 Abschnitt haben werden), berechnen wir den Index für die Position des ersten Elements im Array, das mit einem bestimmten Zeichen beginnt, dann blättern Sie zu ihm.

Der Nachteil ist, dass dafür jedes Mal das Array durchsucht werden muss (ist das wirklich so schlimm?), aber ich konnte weder im iOS-Simulator noch auf meinem iPhone 4S eine Verzögerung oder ein langsames Verhalten feststellen.

- (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;
}

Hinzufügen einer Eigenschaft zum Speichern des zuletzt gewählten Index wie

 @property (assign, nonatomic) NSInteger previousSearchIndex;

und speichern diese Eigenschaft jedes Mal wie:

- (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;
}

und die Aktualisierung scrollToRow Code wie:

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

Machen Sie diese Methode noch besser und mit schöner Animation.

21voto

krut Punkte 547

Einige Leute fragten, ob es möglich sei, dies ohne Abschnitte zu tun. Ich wollte das Gleiche und habe eine Lösung gefunden, die zwar etwas fragwürdig ist und keinen Wert an sectionForSectionIndexTitle zurückgibt, aber wenn man in der Klemme sitzt und nicht für jeden Buchstaben des Alphabets einen Abschnitt erstellen will, ist das eine sichere Lösung. Entschuldigung an alle Code-Nazis im Voraus :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++;
    }
}

Es funktioniert gut, wenn Sie eine große Menge an Daten erhalten und die Aufteilung einen Haufen Arbeit erfordern würde :) Versucht, generische Variablen zu verwenden, so dass Sie wussten, was ich tat. d_itemsInTable ist ein NSArray von NSDictionaries, die ich Liste aus, um die UITableView bin.

3voto

Danny Punkte 409

Hier ist eine modifizierte Version von Kyles Funktion, die den Fall behandelt, dass Sie auf einen Index klicken, für den Sie keine Zeichenfolge haben:

- (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;
}

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X