首页 > 代码库 > day01好友列表折叠效果实现
day01好友列表折叠效果实现
1.实现效果
2.关键点:每个分组的展开和折叠,主要是对每组的行数进行设置,展开为count,折叠为0
3.思想思路:先实现数据模型逻辑-->展示基本数据-->自定义cell-->自定义cellHeaderView视图-->在cellHeaderView中设置协议,controller中遵守协议,实现cellHeaderView点击事件的传递(即好友列表折叠点击事件的实现)
4.主要代码
1)friend ,group数据模型的定义
1 // 2 // FriendModel.h 3 // 1.自定义cell(纯代码) 4 // 5 // Created by 许霞 on 16/9/7. 6 // Copyright © 2016年 jmchat. All rights reserved. 7 // 8 9 #import <Foundation/Foundation.h>10 11 @interface FriendModel : NSObject12 /**13 * 图片14 */15 @property (nonatomic,copy) NSString *icon;16 /**17 * 介绍18 */19 @property (nonatomic,copy) NSString *intro;20 /**21 * 姓名22 */23 @property (nonatomic,copy) NSString *name;24 /**25 * 是否是vip26 */27 @property (nonatomic,assign,getter=isVip) BOOL vip;28 29 - (instancetype)initWithDict:(NSDictionary *)dict;30 + (instancetype)friendModelWithDict:(NSDictionary *)dict;31 @end
//// FriendModel.m// 1.自定义cell(纯代码)//// Created by 许霞 on 16/9/7.// Copyright © 2016年 jmchat. All rights reserved.//#import "FriendModel.h"@implementation FriendModel- (instancetype)initWithDict:(NSDictionary *)dict{ if (self =[super init]) { [self setValuesForKeysWithDictionary:dict]; } return self;}+ (instancetype)friendModelWithDict:(NSDictionary *)dict{ return [[self alloc] initWithDict:dict];}@end
//// GroupModel.h// 1.自定义cell(纯代码)//// Created by 许霞 on 16/9/7.// Copyright © 2016年 jmchat. All rights reserved.//#import <Foundation/Foundation.h>@interface GroupModel : NSObject/** * 姓名 */@property (nonatomic,copy) NSString *name;/** * 在线数 */@property (nonatomic,assign) int online;/** * 朋友 */@property (nonatomic,strong) NSArray *friends;/** * 是否展开 */@property (nonatomic,assign,getter=isOpened) BOOL opened;+ (instancetype)groupModelWithDict:(NSDictionary *)dict;- (instancetype)initWithDict:(NSDictionary *)dict;@end
//// GroupModel.m// 1.自定义cell(纯代码)//// Created by 许霞 on 16/9/7.// Copyright © 2016年 jmchat. All rights reserved.//#import "GroupModel.h"#import "FriendModel.h"@implementation GroupModel+ (instancetype)groupModelWithDict:(NSDictionary *)dict{ return [[self alloc] initWithDict:dict];}- (instancetype)initWithDict:(NSDictionary *)dict{ if (self =[super init]) { [self setValuesForKeysWithDictionary:dict]; } NSMutableArray * friendArray =[NSMutableArray array]; for (NSDictionary * friendDict in _friends) { FriendModel * friend =[FriendModel friendModelWithDict:friendDict]; [friendArray addObject:friend]; } _friends = friendArray; return self;}@end
2)cell,headerView的定义
//// FriendTableViewCell.h// 1.自定义cell(纯代码)//// Created by 许霞 on 16/9/7.// Copyright © 2016年 jmchat. All rights reserved.//#import <UIKit/UIKit.h>@class FriendModel;@interface FriendTableViewCell : UITableViewCell@property (nonatomic,strong) FriendModel * friendData;+(instancetype) cellWithTableView:(UITableView *)tableView;@end
//// FriendTableViewCell.m// 1.自定义cell(纯代码)//// Created by 许霞 on 16/9/7.// Copyright © 2016年 jmchat. All rights reserved.//#import "FriendTableViewCell.h"#import "FriendModel.h"@implementation FriendTableViewCell+(instancetype)cellWithTableView:(UITableView *)tableView{ static NSString *ID = @"friend"; FriendTableViewCell * cell =[tableView dequeueReusableCellWithIdentifier:ID]; if (cell == nil) { cell = [[FriendTableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:ID]; } return cell;}- (void)setFriendData:(FriendModel *)friendData{ _friendData = friendData; self.textLabel.text =_friendData.name; self.detailTextLabel.text = _friendData.intro; self.imageView.image =[UIImage imageNamed:_friendData.icon]; self.textLabel.textColor = _friendData.isVip?[UIColor redColor]:[UIColor blackColor];}@end
//// GroupHeaderView.h// 1.自定义cell(纯代码)//// Created by 许霞 on 16/9/7.// Copyright © 2016年 jmchat. All rights reserved.//#import <UIKit/UIKit.h>@class GroupModel,GroupHeaderView;@protocol GroupHeaderViewDelegate <NSObject>@optional- (void)headerViewDidClickedNameView:(GroupHeaderView *)headerView;@end@interface GroupHeaderView : UITableViewHeaderFooterView@property (nonatomic, strong) GroupModel * group;@property (nonatomic, weak) id <GroupHeaderViewDelegate> delegate;+(instancetype)headerViewWithTableView:(UITableView *)tableView;- (void)updateHeaderView;@end
//// GroupHeaderView.m// 1.自定义cell(纯代码)//// Created by 许霞 on 16/9/7.// Copyright © 2016年 jmchat. All rights reserved.//#import "GroupHeaderView.h"#import "GroupModel.h"@interface GroupHeaderView ()@property (nonatomic,weak) UILabel * countView;@property (nonatomic,weak) UIButton *nameView;@end@implementation GroupHeaderView+(instancetype)headerViewWithTableView:(UITableView *)tableView;{ static NSString *ID =@"groupHeader"; GroupHeaderView * header =[tableView dequeueReusableHeaderFooterViewWithIdentifier:ID]; if (header == nil) { header =[[GroupHeaderView alloc] initWithReuseIdentifier:ID]; } return header;}- (id) initWithReuseIdentifier:(NSString *)reuseIdentifier{ if (self =[super initWithReuseIdentifier:reuseIdentifier]) { //1.添加子控件 UIButton * nameView =[UIButton buttonWithType:UIButtonTypeCustom]; [nameView setBackgroundImage:[UIImage imageNamed:@"buddy_header_bg"] forState:UIControlStateNormal]; [nameView setBackgroundImage:[UIImage imageNamed:@"buddy_header_bg_highlighted"] forState:UIControlStateHighlighted]; [nameView setImage:[UIImage imageNamed:@"buddy_header_arrow"] forState:UIControlStateNormal]; [nameView setTitleColor:[UIColor blackColor] forState:UIControlStateNormal]; nameView.contentHorizontalAlignment = UIControlContentHorizontalAlignmentLeft; nameView.titleEdgeInsets =UIEdgeInsetsMake(0, 10, 0, 0); nameView.contentEdgeInsets = UIEdgeInsetsMake(0, 10, 0, 0); nameView.imageView.contentMode = UIViewContentModeCenter; nameView.imageView.clipsToBounds = NO; [nameView addTarget:self action:@selector(nameViewClick) forControlEvents:UIControlEventTouchUpInside]; [self.contentView addSubview:nameView]; self.nameView = nameView; UILabel *countView =[[UILabel alloc] init]; countView.textAlignment = NSTextAlignmentRight; countView.textColor = [UIColor grayColor]; [self.contentView addSubview:countView]; self.countView = countView; } return self;}- (void)layoutSubviews{ [super layoutSubviews]; self.nameView.frame = self.bounds; CGFloat countY = 0; CGFloat countH =self.nameView.frame.size.height; CGFloat countW = 150; CGFloat countX = self.frame.size.width-10-countW; self.countView.frame = CGRectMake(countX, countY, countW, countH); }-(void)setGroup:(GroupModel *)group{ _group = group; [self.nameView setTitle:group.name forState:UIControlStateNormal]; self.countView.text =[NSString stringWithFormat:@"%d/%u",group.online,group.friends.count];}- (void)nameViewClick{ self.group.opened = !self.group.opened; if ([self.delegate respondsToSelector:@selector(headerViewDidClickedNameView:)]) { [self.delegate headerViewDidClickedNameView:self]; }}- (void)updateHeaderView{ if (self.group.opened) { self.nameView.imageView.transform = CGAffineTransformMakeRotation(M_PI_2); }else{ self.nameView.imageView.transform = CGAffineTransformMakeRotation(0); } }//- (void)willMoveToSuperview:(UIView *)newSuperview//{// if (self.group.opened) {// self.nameView.imageView.transform = CGAffineTransformMakeRotation(M_PI_2);// }else{// self.nameView.imageView.transform = CGAffineTransformMakeRotation(0);// }//}@end
3)controller的实现
1 // 2 // ViewController.m 4 // 5 // Created by 许霞 on 16/9/7. 6 // Copyright © 2016年 jmchat. All rights reserved. 7 // 8 9 #import "ViewController.h" 10 #import "GroupModel.h" 11 #import "FriendModel.h" 12 #import "FriendTableViewCell.h" 13 #import "GroupHeaderView.h" 14 15 @interface ViewController ()<UITableViewDataSource,UITableViewDelegate,GroupHeaderViewDelegate> 16 @property (nonatomic,strong) UITableView * tableView; 17 @property (nonatomic,strong) NSArray * dataArray; 18 @end 19 20 @implementation ViewController 21 22 - (void)viewDidLoad { 23 [super viewDidLoad]; 24 [self initUI]; 25 } 26 /** 27 * 懒加载实现数据的加载 28 */ 29 30 - (NSArray *)dataArray 31 { 32 if (_dataArray ==nil) { 33 NSArray * dictArray =[[NSArray alloc] initWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"friends.plist" ofType:nil] ]; 34 NSMutableArray *groups =[NSMutableArray array]; 35 for (NSDictionary * groupDict in dictArray) { 36 GroupModel * group =[GroupModel groupModelWithDict:groupDict]; 37 [groups addObject:group]; 38 } 39 _dataArray = groups; 40 } 41 return _dataArray; 42 } 43 44 - (void) initUI 45 { 46 self.tableView.autoresizesSubviews = NO; 47 self.tableView =[[UITableView alloc] initWithFrame:CGRectMake(0, 20, [UIScreen mainScreen].bounds.size.width, [UIScreen mainScreen].bounds.size.height) style:UITableViewStylePlain]; 48 _tableView.delegate =self; 49 _tableView.dataSource =self; 50 _tableView.rowHeight = 50.0f; 51 _tableView.sectionHeaderHeight = 44.0f; 52 [self.view addSubview:_tableView]; 53 } 54 #pragma mark- 55 #pragma mark-UITableViewDataSource 56 - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView 57 { 58 return self.dataArray.count; 59 } 60 - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section 61 { 62 GroupModel * group = self.dataArray[section]; 63 return group.opened? group.friends.count:0; 64 } 65 66 - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath 67 { 68 //1.创建cell 69 FriendTableViewCell * cell =[FriendTableViewCell cellWithTableView:tableView]; 70 //2.设置cell数据 71 GroupModel * group =self.dataArray[indexPath.section]; 72 FriendModel * friendData =http://www.mamicode.com/ group.friends[indexPath.row]; 73 cell.friendData =http://www.mamicode.com/ friendData; 74 75 76 return cell; 77 } 78 79 - (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section 80 { 81 return 30.0f; 82 } 83 84 - (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section 85 { 86 //1.创建头部控件 87 GroupHeaderView * headerView =[GroupHeaderView headerViewWithTableView:tableView]; 88 headerView.delegate =self; 89 //2.给Header设置数据(传递模型给header) 90 headerView.group =self.dataArray[section]; 91 [headerView updateHeaderView]; 92 93 return headerView; 94 } 95 96 #pragma mark- 97 #pragma mark --GroupHeaderViewDelegate 98 - (void)headerViewDidClickedNameView:(GroupHeaderView *)headerView 99 {100 [self.tableView reloadData];101 }102 103 104 @end
5.经验总结
1)隐藏显示状态栏方法
-(BOOL)prefersStatusBarHidden
{
return YES;
}
2)friend 是c++关键字,不能用friend作为属性名
3)当一个控件被添加到父控件的中就会调用
- (void)didMoveToSuperView
{
}
4)headerView和cell一样,都有一个复用机制,但是当刷新tableVIew的时候,是不会从缓存池中取的,而是重新创建
5)layoutSubviews (一般在这里布局内部的子控件,设置子控件的frame,当一个控件的frame发生改变的时候就会调用)
6)tableView 的类型如果是plain可以实现组头固定显示;如果是group则无此效果,且如果为plain类型, 设置其组头,组为的高度为0有效,而group类型则无效,但可以设置为0.000001等极小数,可以实现组头,组尾视图的高度设置;
7)将数据源数组设置为不可变,是保证数据安全,不会被合作程序员不小心修改,也是让合作者透露,此数据源数组,不能更改
8)懒加载是写在get方法,如果你需要的时候,才会创建,而if(_group==nil),这里一定不能使用self.group,这样会导致循环调用
9)当模型中又包含有其他模型时,我们需要对其模型部分进行处理,大致思路仍是:用kvc实现复制,但是包含模型部分的数据,被kvc设置为了普通数据,我们单独对此部分进行重新设置即可,关键代码如下:
-(instancetype)initWithDict:(NSDictionary *)dict{ if (self =[super init]){//1.注入所有属性[self setValuesForKeysWithDictionary:dict];//2.特殊处理friends属性NSMutabelArray *friendArray =[NSMutableArray array];for (NSDictionary *dict in self.friends){ Friend * friend =[Friend friendWithDict:dict]; [friendArray addObject:friend];}self.friends = friendArray;}return self;}
10)代码仓库不确定的<#type#>进行设置
11)BOOL值属性,我们一般通过,getter关键字对其重命名
@property (nonatomic,assign,getter = isVip) BOOL vip
12)如果某个控件不出来,可以考虑的原因如下:
1.frame的尺寸和位置对不对; 2.hidden是否为YES; 3.有没有添加到父控件中; 4.alpha 是否 < 0.01; 5.被其他控件挡住了 ;6.父控件的前面5个情况.
13)按钮的一些属性:
1.设置按钮的内容的对齐方式:(垂直方向上:上下对齐;水平方向上:左右对齐)
nameView.contentHorizontalAlignment = UIControlContentHorizontalAlignmentLeft;
2.设置按钮的图片,文字,整体内容的内边距(这里内边距对象格式为:上左下右,逆时针方向设置)
nameView.titleEdgeInsets = UIEdgeInsetsMake(0, 10, 0, 0);
nameView.contentEdgeInsets = UIEdgeInsetsMake(0, 10, 0, 0);
3.设置按钮的内容,文字,图片的显示模式
nameView.imageView.contentMode = UIViewContentModeCenter;
4.设置按钮图片超过边框的内容是否裁剪
nameView.imageView.clipsToBounds = NO;
day01好友列表折叠效果实现