史上最简单的tableview多级菜单

在我们的日常开发工作中,UITableview用的频率是很高的,主要用来进行数据展示,以及其他的必要时候的使用。

一、像QQ好友列表那样可以展开一级的tableviwe表格

  *****注:主要是点击tableviwe的headerview进行数据的操作,刷新表格,从而实现row的出现和消失,下面是主要的代码*****
二级菜单.gif

1.创建必要的类

1.1用于储存数据的模型类DetailModel

@interface DetailModel : NSObject
/** 标题,内容   */
@property (nonatomic ,strong) NSString *title;
/** 是否展开   */
@property (nonatomic , assign) BOOL isOpen;
/** 数组   */
@property (nonatomic , copy) NSMutableArray *subTitle;
/** model的级别   */
@property (nonatomic , assign) NSInteger modelLeval;
/**
 判断这个模型里面应该展示的数据个数,也就是打开的数据的个数

 @return 数据的个数
 */
+ (NSInteger)numberOfOpen:(DetailModel *)model;

/**
 返回这个模型里面所有打开的模型数组

 @param model 需要查看的模型
 @return 模型里面所有打开的模型的数组
 */
+ (NSMutableArray *)subTitleOfOpen:(DetailModel *)model;
@end

1.2用于展示可点击列表的view类DetailView,并且定义协议DetailViewDelegate

@protocol DetailViewDelegate <NSObject>

- (void)DetailView:(DetailView *)dv IsOpen:(BOOL)isOpen;

@end

@interface DetailView : UIView
/** 标题,内容   */
@property (nonatomic ,strong) NSString *title;
/** 是否展开   */
@property (nonatomic , assign) BOOL isOpen;
/** 所在的表格   */
@property (nonatomic ,strong) UITableView *tabble;
/** view对应的数据模型   */
@property (nonatomic ,strong) DetailModel *model;
/** 协议的属性   */
@property (nonatomic , assign) id<DetailViewDelegate> delegate;
@end

2.进行数据准备

2.1将子标题添加到model的subTitle里面

- (void)setSubTitle:(NSMutableArray *)subTitle
{
    NSMutableArray *subs = [NSMutableArray array];
    if ([subTitle  isEqual: @""]) {
        [subs removeAllObjects];
        return ;
    }
    
    for (NSDictionary *dic in subTitle) {
        DetailModel *dm = [[DetailModel alloc] init];
        [dm setValuesForKeysWithDictionary:dic];
        [subs addObject:dm];
    }
    _subTitle = subs;
}

2.2根据传进来的model判断处于打开状态的model数量,即可以展示的模型个数

+ (NSInteger)numberOfOpen:(DetailModel *)model
{
    NSInteger num = 0;
//    1.计算model的子标题的个数
    num = model.isOpen ? model.subTitle.count : 0;
//    2.判断model是否为打开状态,若是的话进行递归操作
    if (num) {
        for (DetailModel *submodel in model.subTitle) {
            num += [DetailModel numberOfOpen:submodel];
        }
    }
    return num;
}

2.3根据传进来的model找出所有可以展示的模型的个数,添加到指定数组并返回

+ (NSMutableArray *)subTitleOfOpen:(DetailModel *)model
{
    NSMutableArray *array = [NSMutableArray array];
    NSInteger num = 0;
//    1.若果是打开状态就直接将子标题数组添加到需要返回的数组里面
    if (model.isOpen) {
        [array addObjectsFromArray:model.subTitle];
//    2.便利数组查看数组模型中是否都为打开状态
        for (NSInteger i = 0; i < model.subTitle.count; i ++) {
            DetailModel *submodel = model.subTitle[i];
//            3.进行递归查询,子标题是否为打开状态
            NSMutableArray *dmsA = [DetailModel subTitleOfOpen:submodel];
           
            if (dmsA.count) {
                for (NSInteger j = 0; j < dmsA.count; j ++) {
                    num ++;
                    DetailModel *detailModel = dmsA[j];
//                    判断需要添加模型的位置,若是最后面则进行add操作,若是中间的就进行insert操作
                    if (num + i + 1 > array.count) {
                        [array addObject:detailModel];
                    } else {
                        [array insertObject:detailModel atIndex:num + i];
                    }
                    
                }
            }
        }
    }
    return array;
}

3.添加用于展示数据的UITableview,展示可点击的列表(只写必要的方法)

3.1将表格的headerview换成自定义的detailview并设置其代理,用于监听点击事件

- (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section
{
    DetailModel *dm = self.array[section];
    DetailView *dv = [[DetailView alloc] init];
    dv.model = dm;
    dv.delegate = self;
    return dv;
}

3.2实现代理方法,进行数据刷新

#pragma mark   --- DetailView的代理事件
- (void)DetailView:(DetailView *)dv IsOpen:(BOOL)isOpen
{
    NSLog(@"----delegate-----%d--%@",isOpen,dv.model);
    dv.model.isOpen = isOpen;
    [self.tableView reloadData];
}

附上DetailView的通知代理的点击方法

- (void)DetailViewClick:(UITapGestureRecognizer *)tap
{
    self.isOpen = !self.isOpen;
    [_delegate DetailView:(DetailView *)tap.view IsOpen:self.isOpen];
}

至此就可以实现类似QQ好友列表的tableview的两级菜单点击


二、实现多级菜单的点击(在二级菜单上进行稍微的修改就行)

注:主要适用于菜单列表详细的项目,如行政区域划分等

多级菜单.gif

1.创建必要的类(只有自定义cell其余的按照二级菜单来)

@interface DetailTableViewCell : UITableViewCell

/**  DetailVi  */
@property (nonatomic ,strong) DetailModel *dm;

/** self.dv   */
@property (nonatomic ,strong) DetailView *dv;
@end

2.进行数据展示(数据准备的按二级菜单来,数据展示也只写多出的部分,其余都为二级菜单照搬即可)

2.1计算出需要展示的row的个数

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
    DetailModel *dm = self.array[section];
    NSInteger ss = [DetailModel numberOfOpen:dm];
    NSLog(@"这组里面有%ld",ss);
    return ss;
}

2.2返回指定的cell

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    DetailModel *dm = self.array[indexPath.section];
    self.dmsArray = [DetailModel subTitleOfOpen:dm];
    DetailModel *dms = self.dmsArray[indexPath.row];
    
    NSString *cell_normal = @"cell_normal";
    NSString *cell_detail = @"cell_Detail";
    if (dms.subTitle == nil) {
        
        UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cell_normal];
        if (!cell) {
            cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cell_normal];
        }
        cell.textLabel.text = dms.title;
        return cell;
    } else {
        DetailTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cell_detail];
        if (!cell) {
            cell = [[DetailTableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cell_detail];
        }
        cell.dm = dms;
        cell.dv.delegate = self;
        return cell;
    }
   
}
*****注:加上下面的方法可以防止tableview出现白条*****
- (CGFloat)tableView:(UITableView *)tableView heightForFooterInSection:(NSInteger)section
{
    return CGFLOAT_MIN;
}

-----------------------至此已经实现了多级菜单-----------------------------

理解多级菜单的主旨就好了,本身还是一个tableview,只是对section里面的数据进行整理,出现多级点击的效果

求助!!!求助!!!求助!!!小编想在代码里面实现如图里面所展示的北京市为一级菜单就是+1海淀区是二级菜单就+2中关村是三级菜单就+3以此类推的效果,试了好多方法都不行,如果有大神看到的话,请指点一二,拜谢

下面附上demo的地址:MenueTableview

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

推荐阅读更多精彩内容