iPhone UITableView। म्यूजिक ऐप जैसी एकल अक्षर वर्णमाला सूची को कैसे चालू करें?


82

IPhone संगीत ऐप में, कलाकार, गाने या एल्बम का चयन करते हुए, UI के दाहिने तरफ सिंगल लेटर्स की वर्टिकली सूची के साथ एक टेबल व्यू प्रस्तुत करता है जो तेजी से स्क्रॉल करने में सक्षम बनाता है। मैं अपने ऐप में इस कार्यक्षमता को कैसे सक्षम करूं?

चीयर्स, डौग

जवाबों:


133

अपने स्वयं के सूचकांक वर्णों की आपूर्ति करें:

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

आपको अनुभागों की आवश्यकता होगी।


21
क्या वर्गों (फ्लैट सूची के लिए) के बिना अनुक्रमित होने का एक तरीका है?
The uSeFuL

12
@ThEuSeFuL आपको अनुभाग हेडर दिखाए बिना अनुभाग हो सकते हैं। यह अंतिम उपयोगकर्ता के लिए एक फ्लैट सूची की तरह दिखेगा।
जॉन हुल

10
"yourSectionIndexForTheSectionForSectionIndexTitle" का क्या अर्थ है?
रावूरिनंदन

2
@ravoorinandan वह अनिवार्य रूप से आपके शीर्षक सरणी में शीर्षक चर के सूचकांक को वापस करने का मतलब है। इसलिए यदि शीर्षक @ "a" है, तो इसे 0. वापस आ जाना चाहिए। यदि शीर्षक @ "i" है, तो इसे 2, और इसके बाद वापस करना चाहिए। आप यहां दिखाए गए दोनों तरीकों से सरणी को उपलब्ध कर सकते हैं और फिर दूसरी विधि में [सरणी indexOfObject: शीर्षक] को कॉल कर सकते हैं। हालांकि मैं कहूंगा कि इसका उत्तर (UILocalizedIndexedCollation से संबंधित) शायद बेहतर है।
ब्रायन सचेटा

बस के मामले में, किसी ने भी मेरी जैसी ही गलती की, स्टोरीबोर्ड में टेबल व्यू का चयन करें और अपने इच्छित रंग में टेक्स्ट का रंग बदलें। मेरे मामले में, पाठ रंग स्वचालित रूप से स्पष्ट रंग के रूप में चुना गया था और इसलिए सूचकांक सूचीबद्ध नहीं था। मैं काफी समय बर्बाद कर रहा हूं कि यह क्या मुद्दा है।
विंसेंट जॉय

35

कुछ और जिन पर आपको विचार करना है, प्रत्येक भाषा के अनुभागों को स्थानीय बनाना है। लगभग थोड़ा खोदने के बाद, मुझे 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


34

मैं अनुभागों का उपयोग किए बिना एकल अक्षर वर्णमाला सूची को संभालने के लिए एक वैकल्पिक दृष्टिकोण के साथ आया था। यह ज़ैफ़ के उत्तर के समान है, लेकिन एक नया सूचकांक वापस करने से कोई मूल्य प्राप्त करने के बजाय (क्योंकि हमारे पास हमेशा 1 खंड होगा), हम उस सरणी में पहले आइटम के स्थान के लिए सूचकांक की गणना करते हैं जो एक निश्चित चरित्र से शुरू होता है, फिर स्क्रॉल करें यह करने के लिए।

नकारात्मक पक्ष यह है कि हर बार सरणी की खोज करना आवश्यक है (क्या यह बिल्कुल भयानक है?), हालांकि मैंने आईओएस सिम्युलेटर या अपने आईफोन 4 एस पर किसी भी अंतराल या धीमे व्यवहार को नोटिस नहीं किया।

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

इस विधि को और भी अच्छे और अच्छे एनीमेशन के साथ करें।


14
बस तब से ही इसका मतलब है कि मुझे वर्णमाला के प्रकार में लिखना नहीं आता है!
पॉल सीज़न ने

1
हे। यह भी एक बुरा समाधान नहीं है ... सेब ने मुझे अपने कोड नमूने में इसका उपयोग करते हुए कोको शिविर के लिए स्वीकार किया। क्या इसका मतलब है कि वे आधिकारिक तौर पर इसका समर्थन करते हैं या नहीं ... मुझे नहीं पता;)
काइल क्लेग

@PaCCezanne वास्तव में, इसे क्लीनर बनाने के लिए मैं आपको अपने सरणी के माध्यम से लूप का सुझाव देता हूं और सभी स्ट्रिंग के ऊपरी अक्षरों को पहले पकड़ता हूं ताकि आपकी सूची गतिशील हो जिसमें आपके पास कोई क्यू नहीं होगा यदि आपके पास कोई आइटम नहीं है पत्र के साथ शुरू करें। मुझे बताएं कि क्या आप मुझे यह दिखाने के लिए अपना कोड अपडेट करना चाहते हैं।
काइल क्लेग

धन्यवाद। मैंने वास्तव में एक और ऐप में काम किया था। यह व्यवहार में बहुत अजीब लग रहा था। किनारे पर AZ सरणी बहुत व्याख्यात्मक है। जब आपके पास केवल कुछ पत्र होते हैं, जो आपके पास होगा यदि आपके पास केवल बहुत कम संख्या में गाने हैं या यदि आपने बहुत सारे फ़िल्टर किए हैं, तो पक्ष के साथ अक्षरों का उद्देश्य अजीब लगता है।
पॉल सेज़न

1
@Mingebag यह इंडैग फॉरफ़र्स्टचेयर के रिटर्न वैल्यू को हर बार कॉल करने की जाँच करके डीबग करने का प्रयास करें। यह हर बार 0 से 25 के बीच होना चाहिए। यदि यह> 25 है, तो शायद आपके पास गैर-वर्णमाला वर्ण या कुछ और है, जिसके कारण यह बहुत अधिक मूल्य लौटाता है।
काइल क्लेग

21

लोगों के एक समूह ने पूछा कि क्या बिना वर्गों के ऐसा करना संभव है। मैं एक ही चीज़ चाहता था और मुझे एक हल मिला जो थोड़ा छायादार हो सकता है और सेक्शनफ़ोरनेक्शनइंडेक्सटेक्स्टिटल के लिए कोई वैल्यू नहीं देता है, लेकिन अगर आप एक कोने में हैं और नहीं चाहते तो अल्फ़ाज़ के हर अक्षर के लिए एक सेक्शन बनाना पड़ेगा एक निश्चित समाधान है। अग्रिम में किसी भी कोड नाजियों को क्षमा करें। : पी

- (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 NSD शब्दकोशों का एक NSArray है जिसे मैं UITableView में सूचीबद्ध कर रहा हूँ।


1
मज़ा फैक्स: अगर तुम वापस -1, यह संकलक चेतावनी पर ध्यान नहीं देगा, और sectionForSectionIndexTitle विधि से उस अनुभाग के लिए स्क्रॉल करने की कोशिश मत
elimirks

वास्तव में कमाल का नमूना धन्यवाद शायद निधि = हाँ के बाद एक ब्रेक जोड़ना; यह भी बुरा नहीं होगा कि ^ ^
मिंगबाग

3

यहां काइल के फ़ंक्शन का एक संशोधित संस्करण है जो एक इंडेक्स पर क्लिक करने के मामले को संभालता है जिसके लिए आपके पास एक स्ट्रिंग नहीं है:

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

3

यदि आप उपयोग कर रहे हैं NSFetchedResultsController, तो आप बस कर सकते हैं:

- (NSArray *)sectionIndexTitlesForTableView:(UITableView *)tableView {
    return [frc sectionIndexTitles];
}

- (NSInteger)tableView:(UITableView *)tableView sectionForSectionIndexTitle:(NSString *)title atIndex:(NSInteger)index {
    return [frc sectionForSectionIndexTitle:title atIndex:index];
}


2

यहाँ स्विफ्ट में एक सरल समाधान है, यह मानते हुए कि आपके शीर्षक शीर्षक एक सरणी में हैं। यदि शीर्षक नहीं मिला, तो यह सरणी में पिछले सूचकांक को लौटा देगा।

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कि दिए गए सूचकांक शीर्षक के लिए अंतिम मिलान अनुभाग के बजाय पहले के सूचकांक को वापस करने के लिए दूसरी वापसी रेखा को बदलना बेहतर है ।
क्रिस सी

ग्राहक क्या उम्मीद करता है, इस पर निर्भर करता है। संभावना है, जो भी कार्यक्षमता आप चुनते हैं, वे जो चाहते हैं उसके विपरीत होंगे। :)
सामह

0

यदि आप MonoTouch का उपयोग कर रहे हैं, तो UITableViewDataSource वर्ग में SectionIndexTield (UITableView) विधि को ओवरराइड करें। बस स्ट्रिंग्स की एक सरणी लौटाएं और उपवर्ग बाकी की देखभाल करता है।

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

* iPhone एप्लिकेशन लिखने के लिए C # और मोनो (.NET) का उपयोग करने वाले हम में से केवल एक व्यक्ति के लिए एक संकेत। :)

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.