UITableView的右侧索引效果

在涉及到联系人或者选择城市这些列表的时候,经常会看到这种效果:


图片.png

这是一组数据源 [@"阿福",@"宝宝",@"大明", @"孙s", @"李龙", @"冠军", @"温馨", @"赵长明",@"cs", @"bg", @"lk", @"sg", @"##号"]。
这个效果有两个关键问题,第一是展示右侧索引,并且要提供点击每个字母的事件。第二是将数据源按字母分成不同的组,并在tableview的代理方法中返回。
针对第一个问题, 事实上,伟大的UITableView已经封装好了这个效果,直接调用Api就可以实现右侧的索引效果,并且可以指定文字颜色,索引的背景颜色,以及点击每个索引字母所触发的事件。

第二个问题,Apple当然也提供了解决办法,因为这个毕竟是一个太常见的需求了。从iOS3.0开始,苹果提供了一个UILocalizedIndexedCollation对象来管理索引。它就是配合tableview使用的。
这个对象很强大,提供了返回包含A-Z 字母的数组,和返回汉字的拼音首字母 以及按汉字的拼音首字母进行排序的功能,真是太实用了。有了这个对象,结合tableview的Api,实现这个效果简直不需要多少行代码。
先按官方文档做个介绍:

  • UILocalizedIndexedCollation
    An object that provides ways to organize, sort, and localize the data for a table view that has a section index
    一个提供了组织 排序和本地化含有右侧索引的tableView数据源的对象
  • Overview

Table views with section indexes are ideal for displaying and facilitating the access of data composed of many items organized by a sequential ordering scheme such as the alphabet. Users tap an index title to jump to the corresponding section. The initial table view of the Phone/Contacts application on the iPhone is an example. Note that the section titles can be different than the titles of the index. The table view’s data source uses the collation object to provide the table view with input for section titles and section index titles.
To prepare the data for a section index, your table-view controller creates a indexed-collation object and then, for each model object that is to be indexed, calls sectionForObject:collationStringSelector:. This method determines the section in which each of these objects should appear and returns an integer that identifies the section. The table-view controller then puts each object in a local array for its section. For each section array, the controller calls the sortedArrayFromArray:collationStringSelector: method to sort all of the objects in the section. The indexed-collation object is now the data store that the table-view controller uses to provide section-index data to the table view, as illustrated in Listing 1.
带有section indexes的TableViews适用于显示和管理一些这样的数据源,这些数据源往往可以按一系列标志进行排序,例如首字母。用户点击index title就可以跳转到对应的section。手机上的联系人应用就是一个例子.注意section titles可以和index 的titles不同。tableview 使用数据源提供section titles和section index titles
为了准备段索引的数据,table-view控制器创建一个indexed-collation对象,然后对每一个要被索引的对象,调用sectionForObject:collationStringSelector:方法,这个方法会决定该对象应该出现在哪个section并返回一个integer来标志这个section.table view控制器会将每个对象加入到section对应的数组。对于section的每一个数组,控制器可以调用sortedArrayFromArray:collationStringSelector方法对section的数组里的所有对象进行局部排序。indexed-collation对象现在是数据容器,table-view控制器用它来向table view提供段索引数据,如下面所示:

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

直接上代码


图片.png

定义了一个模型,name接收数据源的字符串。
控制器中首先定义全局变量

@interface ViewController () <UITableViewDelegate,UITableViewDataSource>
@property (weak, nonatomic) IBOutlet UITableView *tableview;

@property (nonatomic, strong) NSMutableArray *sectionArr;

@end

@implementation ViewController {
    
    //全局索引集合
    UILocalizedIndexedCollation *collation;
}
- (void)viewDidLoad {
    [super viewDidLoad];
    

    NSArray *testArr = @[@"阿福",@"宝宝",@"大明", @"孙s", @"李龙", @"冠军", @"温馨", @"赵长明",@"cs", @"bg", @"lk", @"sg", @"##号"];
    NSMutableArray *personArr = [NSMutableArray arrayWithCapacity:testArr.count];
    
    
    for (NSString *str in testArr) {
        Object *v = [[Object alloc] init];
        v.name = str;
        
        [personArr addObject:v];
    }
    
    //初始化UILocalizedIndexedCollation对象
    collation = [UILocalizedIndexedCollation currentCollation];
    //这个对象中包含26个大写字母A-Z 和 #
    NSArray *titles = collation.sectionTitles;
    
    //定义一个二维数组,数组中的共有27个元素,每个元素又是一个数组,分别对应字母A、B、C、D...#的数据
    NSMutableArray *secionArray = [NSMutableArray arrayWithCapacity:titles.count];
    //向二维数组中添加小数组
    for (int i = 0; i < titles.count; i++) {
        NSMutableArray *subArr = [NSMutableArray array];
        [secionArray addObject:subArr];
    }
    
    for (Object *v in personArr) {
        //这个方法会根据@selector中的方法返回的字符串的拼音首字母,找到这个首字母对应的下标index
        NSInteger section = [collation sectionForObject:v collationStringSelector:@selector(name)];
        //根据index取出二维数组中的一维数组数组元素
        NSMutableArray *subArr = secionArray[section];
        //将这个对象加入到一维数组数组中  也就是以字母A开头的对象如阿福会被加入到A字母所对应数组,其他字母同理
        [subArr addObject:v];
    }
    
    //遍历二维数组,取出每一个一维数组,在对数组中的对象按照字母进行下排序。
    for (NSMutableArray *arr in secionArray) {
        
        NSArray *sortArr = [collation sortedArrayFromArray:arr collationStringSelector:@selector(name)];
        
        [arr removeAllObjects];
        [arr addObjectsFromArray:sortArr];
    }
    
    _sectionArr = secionArray;
    
    //定义tableview右侧section的外观
    //文字颜色
    _tableview.sectionIndexColor = [UIColor blackColor];
    //背景颜色
    _tableview.sectionIndexBackgroundColor = [UIColor clearColor];
   //触摸section区域时候的背景颜色 _tableview.sectionIndexTrackingBackgroundColor = [UIColor greenColor];
    _tableview.sectionIndexMinimumDisplayRowCount = 13;
}

tableview的delegate和datasource方法

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
    
    return [collation sectionTitles].count;
}


- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
    
    return [[_sectionArr objectAtIndex:section] count];
}


- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    
    static NSString *cellid = @"cell";
    
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellid];
    
    if (!cell) {
        cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellid];
    }
    
    Object *v = [[_sectionArr objectAtIndex:indexPath.section] objectAtIndex:indexPath.row];
    
    cell.textLabel.text = v.name;
    
    return cell;
}

- (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section {
    
    return [_sectionArr[section] count] == 0 ? 0 : 15;
}

/**返回右侧索引所包含的内容*/
- (NSArray<NSString *> *)sectionIndexTitlesForTableView:(UITableView *)tableView {
    NSMutableArray *sections = [collation.sectionTitles mutableCopy];
    
    //往索引数组的开始处添加一个放大镜🔍 放大镜是系统定义好的一个常量字符串表示UITableViewIndexSearch 当然除了放大镜外也可以添加其他文字
    [sections insertObject:UITableViewIndexSearch  atIndex:0];
    return sections;
    
}

//返回每个section的title
- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section {
    
    return [[collation sectionTitles] objectAtIndex:section];
}

//点击右侧索引后跳转到的section
- (NSInteger)tableView:(UITableView *)tableView sectionForSectionIndexTitle:(NSString *)title atIndex:(NSInteger)index {
    
    return 0;
}

代码地址 :https://gitee.com/helantage/tableviewYouCeSuoYinXiaoGuo.git

PS:
感觉tableview的索引条将表视图往左边挤了一点?别担心,只是颜色问题。只要如此设置即可

 

    //索引条背景的颜色(清空颜色就不会感觉索引条将tableview往左边挤)

        [_tableView setSectionIndexBackgroundColor:[UIColor clearColor]];

        //索引条文字的颜色

        [_tableView setSectionIndexColor:[UIColor darkGrayColor]];
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 206,839评论 6 482
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,543评论 2 382
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 153,116评论 0 344
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,371评论 1 279
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,384评论 5 374
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,111评论 1 285
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,416评论 3 400
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,053评论 0 259
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,558评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,007评论 2 325
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,117评论 1 334
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,756评论 4 324
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,324评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,315评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,539评论 1 262
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,578评论 2 355
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,877评论 2 345

推荐阅读更多精彩内容