iOS secondary list, only one at a time

Posted by dave_2008 on Sat, 04 Jan 2020 20:28:20 +0100

There are many secondary lists and QQ group demo s on the Internet, but the best one is the one that suits me. I wrote a one that suits me. Record it. In the future, you can use common D + V directly

gif chart first

  • The first is data
    NSArray *data = @[@{
                          @"title":@"Nothing in the world seems to stand up to the scrutiny later",
                          @"cellData":@[@{
                                            @"content":@"For example, later you changed"
                                            },
                                        @{
                                            @"content":@"And then I did"
                                            }]
                          },
                      @{
                          @"title":@"Later, my old friends were scattered",
                          @"cellData":@[@{
                                            @"content":@"New people come here"
                                            },
                                        @{
                                            @"content":@"And then there was silence"
                                            },
                                        @{
                                            @"content":@"The past turns into a river"
                                            }]
                          },
                      @{
                          @"title":@"The misty blue sky and rain",
                          @"cellData":@[@{
                                            @"content":@"Lost youth"
                                            },@{
                                            @"content":@"The rest of the year"
                                            },
                                        @{
                                            @"content":@"The attic in another country is cold"
                                            }]
                          },
                      @{
                          @"title":@"I still rely on a little bit of strength",
                          @"cellData":@[@{
                                            @"content":@"But it has deviated from its former direction"
                                            },
                                        @{
                                            @"content":@"Half a bottle of wine"
                                            },
                                        @{
                                            @"content":@"Forgotten."
                                            }]
                          }];
  • Create model
    HeaderModel.h
#import <Foundation/Foundation.h>
#import "CellModel.h"
@interface HeaderModel : NSObject
@property (nonatomic,copy) NSString *title;
@property (nonatomic,strong) NSArray *cellData;
@end

HeaderModel.m

#import "HeaderModel.h"

@implementation HeaderModel
+(NSDictionary *)mj_objectClassInArray
{
    return @{
             @"cellData":@"CellModel"
             };
}
@end

CellModel.h

#import <Foundation/Foundation.h>
#import "MJExtension.h"
@interface CellModel : NSObject
@property (nonatomic,copy) NSString *content;
@end

CellModel.m

#import "CellModel.h"
@implementation CellModel
MJCodingImplementation
@end
  • UIViewController
#import "ViewController.h"
#import "HeaderModel.h"
#import "Cell.h"
#import "CellModel.h"
#import "HeaderView.h"
@interface ViewController ()
<UITableViewDelegate,UITableViewDataSource,HeaderViewDelegate>
{
    int _currentRow;
    int _currentSection;
}
@property (nonatomic, strong)UITableView *tableView;
@property(nonatomic,strong)NSMutableArray * headViewArray;
@property (nonatomic,strong) NSMutableArray *data;
@end

@implementation ViewController

-(NSMutableArray *)data
{
    if (!_data) {
        _data = [NSMutableArray array];
    }
    return _data;
}

- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view, typically from a nib.    

    self.data = [HeaderModel mj_objectArrayWithKeyValuesArray:data];


    self.headViewArray = [NSMutableArray array];
    int i = 0;
    for (HeaderModel *model in self.data) {
        HeaderView *headerView = [[HeaderView alloc]init];
        headerView.headerModel = model;
        headerView.delegate = self;
        headerView.index = i;
        i++;
        [self.headViewArray addObject:headerView];
    }


    [self.view addSubview:self.tableView];
}
  • Create tableView
-(UITableView *)tableView
{
    if (!_tableView) {
        _tableView = [[UITableView alloc]initWithFrame:CGRectMake(0, 10, self.view.width, self.view.height - 20) style:UITableViewStylePlain];
        _tableView.delegate = self;
        _tableView.dataSource = self;
        _tableView.estimatedRowHeight = 0;
        _tableView.estimatedSectionHeaderHeight = 0;
        _tableView.estimatedSectionFooterHeight = 0;
        _tableView.backgroundColor = [UIColor whiteColor];
        _tableView.separatorStyle = UITableViewCellSeparatorStyleNone;
    }
    return _tableView;
}
  • UITableviewDelegate—UITableviewDataSource
- (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section {
    return 60;
}

-(UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section
{
    return self.headViewArray[section];
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{
    HeaderView* headView = self.headViewArray[section];
    HeaderModel *headerModel = self.data[section];
    return headView.open?headerModel.cellData.count:0;
}
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView{
    return [self.headViewArray count];
}

-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    Cell *cell = [Cell cellWithTableView:tableView];
    HeaderModel *headerModel = self.data[indexPath.section];
    CellModel *model = headerModel.cellData[indexPath.row];
    cell.model = model;
    return cell;
}
-(CGFloat)tableView:(UITableView*)tableView heightForRowAtIndexPath:(NSIndexPath*)indexPath
{
    return 50;
}

-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
    [tableView deselectRowAtIndexPath:indexPath animated:YES];
    NSLog(@"click---%ld section and %ld row",(long)indexPath.section,(long)indexPath.row);
}
#pragma mark - HeadViewdelegate
-(void)selectedWith:(HeaderView *)view{
    _currentRow = -1;
    if (view.open) {
        for(int i = 0;i<[self.headViewArray count];i++)
        {
            HeaderView *head = [self.headViewArray objectAtIndex:i];
            head.open = NO;
            [UIView animateWithDuration:0.15 delay:0 options:UIViewAnimationOptionAllowUserInteraction animations:^{
                head.backBtn.layer.transform = CATransform3DMakeRotation(0, 0, 0, 1);
            } completion:NULL];
        }
        [_tableView reloadData];
        return;
    }
    _currentSection = (int)view.index;
    [self reset];
}
//Interface reset
- (void)reset
{
    for(int i = 0;i<[self.headViewArray count];i++)
    {
        HeaderView *head = [self.headViewArray objectAtIndex:i];
        if(head.index == _currentSection)
        {
            head.open = YES;
            [UIView animateWithDuration:0.15 delay:0 options:UIViewAnimationOptionAllowUserInteraction animations:^{
                head.backBtn.layer.transform = CATransform3DMakeRotation(M_PI, 0, 0, 1);
            } completion:NULL];
        }else {
            [UIView animateWithDuration:0.15 delay:0 options:UIViewAnimationOptionAllowUserInteraction animations:^{
                head.backBtn.layer.transform = CATransform3DMakeRotation(0, 0, 0, 1);
            } completion:NULL];
            head.open = NO;
        }
    }

    [_tableView reloadData];
}
  • Create SectionHeaderView
    HeaderView.h
#import <UIKit/UIKit.h>
@class HeaderView,HeaderModel;
@protocol HeaderViewDelegate <NSObject>
-(void)selectedWith:(HeaderView *)view;
@end
@interface HeaderView : UIView
@property (nonatomic,weak) id<HeaderViewDelegate> delegate;
@property(nonatomic, assign) NSInteger index;
@property(nonatomic, assign) BOOL open;
@property(nonatomic, retain) UIButton* backBtn;
@property(nonatomic, strong) HeaderModel * headerModel;

@end

HeaderView.m

#import "HeaderView.h"
#import "UIView+Extension.h"
#import "HeaderModel.h"
@interface HeaderView()
@property (nonatomic,strong) UIView *backView;
@property (nonatomic,weak) UILabel *label;

@end
@implementation HeaderView
-(instancetype)initWithFrame:(CGRect)frame
{
    if (self = [super initWithFrame:frame]) {
        _open = NO;

        CGFloat titleFont = 15;

        self.backgroundColor = [UIColor whiteColor];

        UIView *backView = [[UIView alloc]init];
        backView.backgroundColor = [UIColor whiteColor];
        self.backView = backView;
        [self addSubview:backView];

        //time
        UILabel *label = [[UILabel alloc]init];
        label.font = [UIFont systemFontOfSize:titleFont] ;
        label.textColor = [UIColor blackColor];
        label.textAlignment = NSTextAlignmentLeft;
        [backView addSubview:label];
        self.label = label;

        //Arrow
        UIButton* btn = [UIButton buttonWithType:UIButtonTypeCustom];
        [btn addTarget:self action:@selector(doSelected) forControlEvents:UIControlEventTouchUpInside];
        [self addGestureRecognizer:[[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(doSelected)]];
        [btn setImage:[UIImage imageNamed:@"down arrow-4"] forState:UIControlStateNormal];
        [btn.imageView setContentMode:UIViewContentModeScaleAspectFill];
        [backView addSubview:btn];
        self.backBtn = btn;
    }
    return self;
}

-(void)layoutSubviews
{
    [super layoutSubviews];
    //position
    self.backView.frame = CGRectMake(0, 5, self.width, self.height - 10);
    self.label.frame = CGRectMake(10, (self.backView.height - 40)/2, self.backView.width - 60, 40);

    self.backBtn.frame = CGRectMake(self.width - self.height +10, 0, self.height - 10, self.height - 10);
}

-(void)setHeaderModel:(HeaderModel *)headerModel
{
    _headerModel = headerModel;
    self.label.text = headerModel.title;

}
-(void)doSelected{
    if (_delegate && [_delegate respondsToSelector:@selector(selectedWith:)]){
        [_delegate selectedWith:self];
    }
}
  • Create Cell
    Cell.h
#import <UIKit/UIKit.h>
@class CellModel;
@interface Cell : UITableViewCell
+(instancetype)cellWithTableView:(UITableView *)tableView;
@property (nonatomic,strong) CellModel *model;
@end

Cell.m

#import "Cell.h"
#import "CellModel.h"
#import "UIView+Extension.h"
@interface Cell ()

@property (nonatomic,weak) UILabel *piCiLabel;

@end
@implementation Cell
+(instancetype)cellWithTableView:(UITableView *)tableView
{
    static NSString *CellID = @"Cell";
    Cell *cell = [tableView dequeueReusableCellWithIdentifier:CellID];
    if (cell == nil) {
        cell = [[Cell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellID];
        cell.selectionStyle = UITableViewCellSelectionStyleNone;
    }
    return cell;
}
- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier
{
    self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
    if (self) {
        // Add all the child controls you may display
        self.backgroundColor = [UIColor whiteColor];

        UILabel *piCiLabel = [[UILabel alloc]init];
        piCiLabel.font = [UIFont systemFontOfSize:14] ;
        piCiLabel.textColor = [UIColor lightGrayColor];
        piCiLabel.textAlignment = NSTextAlignmentLeft;
        [self.contentView addSubview:piCiLabel];
        self.piCiLabel = piCiLabel;
    }
    return self;
}

-(void)setModel:(CellModel *)model
{
    _model = model;
    self.piCiLabel.text = model.content;
}

-(void)layoutSubviews
{
    [super layoutSubviews];
    self.piCiLabel.frame = CGRectMake(20, (self.height - 40)/2, self.width - 25, 40);
}
- (void)awakeFromNib {
    [super awakeFromNib];
    // Initialization code
}

- (void)setSelected:(BOOL)selected animated:(BOOL)animated {
    [super setSelected:selected animated:animated];

    // Configure the view for the selected state
}

@end

Recently, I found a problem. If there is more data in the list, click the second level list at the bottom, and the tableview will automatically roll back to the top. I always thought it was caused by refreshing the entire tableview. Later, I found that it was not. Just add these three attributes to the tableview

      _tableView.estimatedRowHeight = 0;
      _tableView.estimatedSectionHeaderHeight = 0;
      _tableView.estimatedSectionFooterHeight = 0;

Source address, welcome to download

Topics: REST