【Objective-c】UITableView 折疊效果

小編敲代碼實(shí)現(xiàn)項(xiàng)目功能時(shí)荣回,心中總會(huì)打上許多問號(hào)“ 遭贸?”,雖然項(xiàng)目的UI和功能都實(shí)現(xiàn)了心软,但總覺得自己的方法很low壕吹,沒有什么復(fù)用度和設(shè)計(jì)模式可言,處于低級(jí)階段删铃,離高新的目標(biāo)很是遙遠(yuǎn)6帷!猎唁!更不要說迎娶白富美了"~".......好了咒劲,扯了有點(diǎn)遠(yuǎn)了,言歸正傳:UITableView折疊效果(類似QQ聯(lián)系人的折疊)诫隅,在沒有看到大神博客的時(shí)候缎患,

我實(shí)現(xiàn)的套路如下:
1、使用Xib定制兩個(gè)Cell(一個(gè)標(biāo)題Cell阎肝,一個(gè)展開Cell)
2挤渔、折疊展開是通過改變tableView的section分區(qū)中cell的個(gè)數(shù),折疊時(shí)數(shù)量1风题,展開時(shí)數(shù)  量就有多個(gè)
3判导、兩個(gè)重要參數(shù):一個(gè)NSArray存儲(chǔ)內(nèi)容(后臺(tái)數(shù)據(jù)請(qǐng)求返回的)嫉父,
                               一個(gè)NSDictionary記錄“折疊展開”
4、改變“折疊”“展開狀態(tài)”眼刃,通過刷新整個(gè)tableIView展示

不足的是:
1绕辖、在cellForRow方法中要判斷是標(biāo)題Cell還是展開Cell
2、在cell的點(diǎn)擊方法中也是需要判斷是標(biāo)題Cell還是展開Cell
3擂红、刷新整個(gè)tableView仪际,消耗的資源比較大(當(dāng)然可以只是刷新某個(gè)section)

雖然實(shí)現(xiàn)的代碼量不多,邏輯也不復(fù)雜昵骤,但是要知道項(xiàng)目是會(huì)成長(zhǎng)的树碱,后續(xù)添加的功能需求只會(huì)越來越多,這就考驗(yàn)當(dāng)初設(shè)計(jì)時(shí):代碼的靈活度变秦、代碼的分工明不明細(xì)(影響代碼的可讀性)成榜、代碼的擴(kuò)展性等等,這就是我們經(jīng)潮拿担看到一些大神在實(shí)現(xiàn)一些簡(jiǎn)單功能的時(shí)候總會(huì)創(chuàng)建幾個(gè)分類赎婚,然后跳來跳去的,心中就疑惑就起來了.....

接下來談?wù)劥笊竦姆椒ǎ嫦驅(qū)ο蟮木幊趟枷耄?/h5>

1樱溉、依然是通過改變tableView的section分區(qū)中cell的個(gè)數(shù)挣输,不同的是折疊時(shí)為0,展開時(shí)是多個(gè)福贞,因?yàn)椴季种袠?biāo)題cell是在每個(gè)section的頭視圖顯示的(這樣在cellForRow中就不需要判斷)
2撩嚼、創(chuàng)建UITableViewHeaderFooterView的子類,自定義標(biāo)題內(nèi)容
3肚医、自定義cell,顯示展開后的cell
4向瓷、創(chuàng)建section模型肠套,存儲(chǔ)每組section的內(nèi)容
5、創(chuàng)建cell模型猖任,存儲(chǔ)展開后每個(gè)cell的內(nèi)容
6你稚、單獨(dú)刷新section

詳情請(qǐng)看代碼:

先看效果圖,有個(gè)概念


spring.gif
建立模型:
@interface SectionModel : NSObject
@property (nonatomic,assign) BOOL isExpand;
@property (nonatomic,strong) NSString *title;
@property (nonatomic,strong) NSArray *cellArray;
@end
@interface CellModel : NSObject
@property (nonatomic,strong) NSString *title;
@end
創(chuàng)建一個(gè)繼承于UITableViewHeaderFooterView的子類"SectionView"
@class SectionModel;
typedef void(^CallBackBlock)(BOOL);
@interface SectionView : UITableViewHeaderFooterView
@property (nonatomic,strong) SectionModel *model;
@property (nonatomic,strong) CallBackBlock block;
@end

.m文件

/* 在構(gòu)造方法中朱躺,創(chuàng)建UI*/
- (instancetype)initWithReuseIdentifier:(NSString *)reuseIdentifier{
    if (self = [super initWithReuseIdentifier:reuseIdentifier]) {
        CGFloat w = [UIScreen mainScreen].bounds.size.width;
        self.arrowImage = [[UIImageView alloc]initWithFrame:CGRectMake(10, (44 - 8) / 2, 15, 8)];
        self.arrowImage.image = [UIImage imageNamed:@"right.png"];
        [self.contentView addSubview:self.arrowImage];
        
        UIButton *button = [[UIButton alloc]initWithFrame:CGRectMake(0, 0, w, 44)];
        [button addTarget:self action:@selector(btnClick:) forControlEvents:UIControlEventTouchUpInside];
        [self.contentView addSubview:button];
        
        self.titleLabel = [[UILabel alloc]initWithFrame:CGRectMake(30, (44 - 20) / 2, w-20, 20)];
        self.titleLabel.font = [UIFont systemFontOfSize:17];
        self.titleLabel.textColor = [UIColor blackColor];

        UIView *line = [[UIView alloc]initWithFrame:CGRectMake(0, 43, w, 1)];
        line.backgroundColor = [UIColor darkGrayColor];
        [self.contentView addSubview:line];
        
        [self.contentView addSubview:self.titleLabel];
        
        self.contentView.backgroundColor = [UIColor yellowColor];
    }
    return self;
}
/*
  1刁赖、通過懶加載,設(shè)置“箭頭”的方向
  2长搀、通過頭視圖SectionView的點(diǎn)擊宇弛,改變“箭頭”的方向
  3、通過點(diǎn)擊SectionView源请,回調(diào)block進(jìn)行section刷新
*/
- (void)setModel:(SectionModel *)model{
    if (_model != model) {
        _model = model;
    }
    self.titleLabel.text = model.title;
    if (model.isExpand) {       //展開
        self.arrowImage.transform = CGAffineTransformIdentity;
    }else{
        self.arrowImage.transform = CGAffineTransformMakeRotation(M_PI);
    }
}

- (void)btnClick:(UIButton *)sender{
    self.model.isExpand = ! self.model.isExpand;
    if (self.model.isExpand) {
        self.arrowImage.transform = CGAffineTransformIdentity;
    }else{
        self.arrowImage.transform = CGAffineTransformMakeRotation(M_PI);
    }
    if (self.block) {
        self.block(self.model.isExpand);
    }
}
tableView 的配置
@interface ViewController ()<UITableViewDelegate,UITableViewDataSource>
@property (nonatomic,strong) UITableView *tableView;
@property (nonatomic,strong) NSMutableArray *sectionData;
@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    self.tableView = [[UITableView alloc]initWithFrame:self.view.frame style:UITableViewStylePlain];
    self.tableView.delegate = self;
    self.tableView.dataSource = self;
    [self.view addSubview:self.tableView];
    
    [self.tableView registerClass:[UITableViewCell class] forCellReuseIdentifier:@"cellid"];
    [self.tableView registerClass:[SectionView class] forHeaderFooterViewReuseIdentifier:@"header"];
}
//懶加載
- (NSMutableArray *)sectionData{
    if (_sectionData == nil) {
        _sectionData = [[NSMutableArray alloc]init];
        for (int i=0; i<20; i++) {
            SectionModel *model = [[SectionModel alloc]init];
            model.title = [NSString stringWithFormat:@"%d",i];
            model.isExpand = NO;
            NSMutableArray *array = [[NSMutableArray alloc]init];
            for (int j=0; j<10; j++) {
                CellModel *cell = [[CellModel alloc]init];
                cell.title = [NSString stringWithFormat:@"LivenCell==Section:%d,Row:%d",i,j];
                [array addObject:cell];
            }
            model.cellArray = array;
            [_sectionData addObject:model];
        }
    }
    return _sectionData;

}
#pragma mark - tableView delegate
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView{
    return self.sectionData.count;
}

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{
    SectionModel *model = _sectionData[section];
    return model.isExpand?model.cellArray.count:0;
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"cellid"];
    SectionModel *section = _sectionData[indexPath.section];
    CellModel *model = section.cellArray[indexPath.row];
    cell.textLabel.text = model.title;
    return cell;
}

- (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section{
    SectionView *view = [tableView dequeueReusableHeaderFooterViewWithIdentifier:@"header"];
    SectionModel *model = _sectionData[section];
    view.model = model;
    //更變了section的cell數(shù)量枪芒,所以要刷新
    view.block = ^(BOOL isExpanded){
        [tableView reloadSections:[NSIndexSet indexSetWithIndex:section] withRowAnimation:UITableViewRowAnimationFade];
    };
    return view;
}

- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath{
    return 44;
}
- (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section{
    return 44;
}

整體的內(nèi)容就這么多彻况,這個(gè)Demo真的不錯(cuò),覺得好的自己多敲幾遍舅踪,最后必須感謝“標(biāo)哥”對(duì)我的啟發(fā)

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末纽甘,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子抽碌,更是在濱河造成了極大的恐慌悍赢,老刑警劉巖,帶你破解...
    沈念sama閱讀 216,651評(píng)論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件货徙,死亡現(xiàn)場(chǎng)離奇詭異左权,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)破婆,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,468評(píng)論 3 392
  • 文/潘曉璐 我一進(jìn)店門涮总,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人祷舀,你說我怎么就攤上這事瀑梗。” “怎么了裳扯?”我有些...
    開封第一講書人閱讀 162,931評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵抛丽,是天一觀的道長(zhǎng)。 經(jīng)常有香客問我饰豺,道長(zhǎng)亿鲜,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,218評(píng)論 1 292
  • 正文 為了忘掉前任冤吨,我火速辦了婚禮蒿柳,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘漩蟆。我一直安慰自己垒探,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,234評(píng)論 6 388
  • 文/花漫 我一把揭開白布怠李。 她就那樣靜靜地躺著圾叼,像睡著了一般。 火紅的嫁衣襯著肌膚如雪捺癞。 梳的紋絲不亂的頭發(fā)上夷蚊,一...
    開封第一講書人閱讀 51,198評(píng)論 1 299
  • 那天,我揣著相機(jī)與錄音髓介,去河邊找鬼惕鼓。 笑死,一個(gè)胖子當(dāng)著我的面吹牛唐础,可吹牛的內(nèi)容都是我干的呜笑。 我是一名探鬼主播夫否,決...
    沈念sama閱讀 40,084評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼叫胁!你這毒婦竟也來了凰慈?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 38,926評(píng)論 0 274
  • 序言:老撾萬榮一對(duì)情侶失蹤驼鹅,失蹤者是張志新(化名)和其女友劉穎微谓,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體输钩,經(jīng)...
    沈念sama閱讀 45,341評(píng)論 1 311
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡豺型,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,563評(píng)論 2 333
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了买乃。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片姻氨。...
    茶點(diǎn)故事閱讀 39,731評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖剪验,靈堂內(nèi)的尸體忽然破棺而出肴焊,到底是詐尸還是另有隱情,我是刑警寧澤功戚,帶...
    沈念sama閱讀 35,430評(píng)論 5 343
  • 正文 年R本政府宣布娶眷,位于F島的核電站,受9級(jí)特大地震影響啸臀,放射性物質(zhì)發(fā)生泄漏届宠。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,036評(píng)論 3 326
  • 文/蒙蒙 一乘粒、第九天 我趴在偏房一處隱蔽的房頂上張望豌注。 院中可真熱鬧,春花似錦灯萍、人聲如沸轧铁。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,676評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽属桦。三九已至熊痴,卻和暖如春他爸,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背果善。 一陣腳步聲響...
    開封第一講書人閱讀 32,829評(píng)論 1 269
  • 我被黑心中介騙來泰國(guó)打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人檬寂。 一個(gè)月前我還...
    沈念sama閱讀 47,743評(píng)論 2 368
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像纪他,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子晾匠,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,629評(píng)論 2 354

推薦閱讀更多精彩內(nèi)容

  • 概述在iOS開發(fā)中UITableView可以說是使用最廣泛的控件茶袒,我們平時(shí)使用的軟件中到處都可以看到它的影子,類似...
    liudhkk閱讀 9,037評(píng)論 3 38
  • 原創(chuàng) 2017-07-26 王曉先 先姐筆耕為衛(wèi)知產(chǎn)并護(hù)青春 驚險(xiǎn)的實(shí)彈訓(xùn)練 王曉先 我插隊(duì)當(dāng)知青的那個(gè)年代凉馆,每年...
    先姐筆耕閱讀 358評(píng)論 1 0
  • 嗨薪寓,大家好,我是麗妃娘娘澜共,周末快樂向叉! 今天是跑休時(shí)間,所以起床后沒有跑步嗦董,看了一篇TED母谎。 講述的是一位英國(guó)姑娘,...
    麗妃娘娘閱讀 3,284評(píng)論 2 2
  • 定義:對(duì)自己的思考過程的認(rèn)知與理解京革。 對(duì)自己的思考過程奇唤,思考原理和思考結(jié)果,往往需要去思考一下為什么我會(huì)這么想存崖,這...
    Sucler閱讀 158評(píng)論 0 0
  • 對(duì)于性愛的渴望来惧,被寫進(jìn)兩性動(dòng)物的基因里冗栗,人類的基因包含對(duì)性愛的渴望。 如果人類的基因中沒有對(duì)性愛的渴望供搀,那么隅居,人類...
    小星Stack閱讀 376評(píng)論 0 0