iOS开发UI篇—使用UItableview完成一个简单的QQ好友列表(二)
一、实现效果
二、实现代码
1.数据模型部分
TXFriendGroup.h文件
1 #import <Foundation/Foundation.h> 2 3 @interface TXFriendGroup : NSObject 4 @property (nonatomic, copy) NSString *name; 5 /** 6 * 数组中装的都是TXriend模型 7 */ 8 @property (nonatomic, strong) NSArray *friends; 9 @property (nonatomic, assign) int online; 10 11 + (instancetype)groupWithDict:(NSDictionary *)dict; 12 - (instancetype)initWithDict:(NSDictionary *)dict; 13 @property (nonatomic, assign, getter = isOpened) BOOL opened; 14 15 16 @end
TXFriendGroup.m文件
1 // Created by 鑫 on 14-10-13. 2 // Copyright (c) 2014年 梁镋鑫. All rights reserved. 3 // 4 5 #import "TXFriendGroup.h" 6 #import "TXFriend.h" 7 @implementation TXFriendGroup 8 + (instancetype)groupWithDict:(NSDictionary *)dict 9 { 10 return [[self alloc] initWithDict:dict]; 11 } 12 13 - (instancetype)initWithDict:(NSDictionary *)dict 14 { 15 if (self = [super init]) { 16 // 1.注入所有属性 17 [self setValuesForKeysWithDictionary:dict]; 18 19 // 2.特殊处理friends属性 20 NSMutableArray *friendArray = [NSMutableArray array]; 21 for (NSDictionary *dict in self.friends) { 22 TXFriend *friend = [TXFriend friendWithDict:dict]; 23 [friendArray addObject:friend]; 24 } 25 self.friends = friendArray; 26 } 27 return self; 28 } 29 30 @end
TXFriend.h文件
1 #import <Foundation/Foundation.h> 2 3 @interface TXFriend : NSObject 4 @property (nonatomic, copy) NSString *name; 5 @property (nonatomic, copy) NSString *icon; 6 @property (nonatomic, copy) NSString *intro; 7 @property (nonatomic, assign, getter = isVip) BOOL vip; 8 9 + (instancetype)friendWithDict:(NSDictionary *)dict; 10 - (instancetype)initWithDict:(NSDictionary *)dict; 11 12 @end
TXFriend.m文件
1 #import "TXFriend.h" 2 3 @implementation TXFriend 4 + (instancetype)friendWithDict:(NSDictionary *)dict 5 { 6 return [[self alloc] initWithDict:dict]; 7 } 8 9 - (instancetype)initWithDict:(NSDictionary *)dict 10 { 11 if (self = [super init]) { 12 [self setValuesForKeysWithDictionary:dict]; 13 } 14 return self; 15 } 16 17 @end
2.视图部分
TXFriendCell.h文件
1 #import <UIKit/UIKit.h> 2 @class TXFriend; 3 @interface TXFriendCell : UITableViewCell 4 + (instancetype)cellWithTableView:(UITableView *)tableView; 5 // friend是C++的关键字,不能用friend作为属性名 6 @property (nonatomic, strong) TXFriend *friendData; 7 @end
TXFriendCell.m文件
1 #import "TXFriendCell.h" 2 #import "TXFriend.h" 3 @implementation TXFriendCell 4 5 + (instancetype)cellWithTableView:(UITableView *)tableView 6 { 7 static NSString *ID = @"friend"; 8 TXFriendCell *cell = [tableView dequeueReusableCellWithIdentifier:ID]; 9 if (cell == nil) { 10 cell = [[TXFriendCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:ID]; 11 } 12 return cell; 13 } 14 15 - (void)setFriendData:(TXFriend *)friendData 16 { 17 _friendData = friendData; 18 19 self.imageView.image = [UIImage imageNamed:friendData.icon]; 20 self.textLabel.text = friendData.name; 21 self.detailTextLabel.text = friendData.intro; 22 } 23 24 @end
TXHeaderView.h文件
1 // TXHeaderView.h 2 // 04-QQ好友列表 3 // 4 // Created by 鑫 on 14-10-14. 5 // Copyright (c) 2014年 梁镋鑫. All rights reserved. 6 // 7 8 #import <UIKit/UIKit.h> 9 @class TXFriendGroup, TXHeaderView; 10 //把自己的名字全进去TXHeaderView,告诉他那个家伙身上的按钮备点 11 12 @protocol TXHeaderViewDelegate <NSObject> 13 @optional 14 - (void)headerViewDidClickedNameView:(TXHeaderView *)headerView; 15 @end 16 17 @interface TXHeaderView : UITableViewHeaderFooterView 18 + (instancetype)headerViewWithTableView:(UITableView *)tableView; 19 20 @property (nonatomic, strong) TXFriendGroup *group; 21 22 @property (nonatomic, weak) id<TXHeaderViewDelegate> delegate; 23 @end
TXHeaderView.m文件
1 #import "TXHeaderView.h" 2 #import "TXFriendGroup.h" 3 4 /** 5 某个控件出不来: 6 1.frame的尺寸和位置对不对 7 8 2.hidden是否为YES 9 10 3.有没有添加到父控件中 11 12 4.alpha 是否 < 0.01 13 14 5.被其他控件挡住了 15 16 6.父控件的前面5个情况 17 */ 18 19 @interface TXHeaderView() 20 @property (nonatomic, weak) UILabel *countView; 21 @property (nonatomic, weak) UIButton *nameView; 22 @end 23 24 @implementation TXHeaderView 25 26 + (instancetype)headerViewWithTableView:(UITableView *)tableView 27 { 28 static NSString *ID = @"header"; 29 TXHeaderView *header = [tableView dequeueReusableHeaderFooterViewWithIdentifier:ID]; 30 if (header == nil) { 31 header = [[TXHeaderView alloc] initWithReuseIdentifier:ID]; 32 } 33 return header; 34 } 35 36 /** 37 * 在这个初始化方法中,TXHeaderView的frame\bounds没有值 38 */ 39 - (id)initWithReuseIdentifier:(NSString *)reuseIdentifier 40 { 41 if (self = [super initWithReuseIdentifier:reuseIdentifier]) { 42 // 添加子控件 43 // 1.添加按钮 44 UIButton *nameView = [UIButton buttonWithType:UIButtonTypeCustom]; 45 // 背景图片 46 [nameView setBackgroundImage:[UIImage imageNamed:@"buddy_header_bg"] forState:UIControlStateNormal]; 47 [nameView setBackgroundImage:[UIImage imageNamed:@"buddy_header_bg_highlighted"] forState:UIControlStateHighlighted]; 48 // 设置按钮内部的左边箭头图片 49 [nameView setImage:[UIImage imageNamed:@"buddy_header_arrow"] forState:UIControlStateNormal]; 50 [nameView setTitleColor:[UIColor blackColor] forState:UIControlStateNormal]; 51 // 设置按钮的内容左对齐 52 nameView.contentHorizontalAlignment = UIControlContentHorizontalAlignmentLeft; 53 // 设置按钮的内边距 54 // nameView.imageEdgeInsets 55 nameView.titleEdgeInsets = UIEdgeInsetsMake(0, 10, 0, 0); 56 nameView.contentEdgeInsets = UIEdgeInsetsMake(0, 10, 0, 0); 57 [nameView addTarget:self action:@selector(nameViewClick) forControlEvents:UIControlEventTouchUpInside]; 58 59 // 设置按钮内部的imageView的内容模式为居中 60 nameView.imageView.contentMode = UIViewContentModeCenter; 61 // 超出边框的内容不需要裁剪 62 nameView.imageView.clipsToBounds = NO; 63 64 [self.contentView addSubview:nameView]; 65 self.nameView = nameView; 66 67 // 2.添加好友数 68 UILabel *countView = [[UILabel alloc] init]; 69 countView.textAlignment = NSTextAlignmentRight; 70 countView.textColor = [UIColor grayColor]; 71 [self.contentView addSubview:countView]; 72 self.countView = countView; 73 } 74 return self; 75 } 76 77 /** 78 * 当一个控件的frame发生改变的时候就会调用 79 * 80 * 一般在这里布局内部的子控件(设置子控件的frame) 81 */ 82 - (void)layoutSubviews 83 { 84 #warning 一定要调用super的方法 85 [super layoutSubviews]; 86 87 // 1.设置按钮的frame 88 self.nameView.frame = self.bounds; 89 90 // 2.设置好友数的frame 91 CGFloat countY = 0; 92 CGFloat countH = self.frame.size.height; 93 CGFloat countW = 150; 94 CGFloat countX = self.frame.size.width - 10 - countW; 95 self.countView.frame = CGRectMake(countX, countY, countW, countH); 96 } 97 98 - (void)setGroup:(TXFriendGroup *)group 99 { 100 _group = group; 101 102 // 1.设置按钮文字(组名) 103 [self.nameView setTitle:group.name forState:UIControlStateNormal]; 104 105 // 2.设置好友数(在线数/总数) 106 self.countView.text = [NSString stringWithFormat:@"%d/%d", group.online, group.friends.count]; 107 } 108 109 /** 110 * 监听组名按钮的点击 111 */ 112 - (void)nameViewClick 113 { 114 // 1.修改组模型的标记(状态取反) 115 self.group.opened = !self.group.isOpened; 116 117 // 2.刷新表格 118 if ([self.delegate respondsToSelector:@selector(headerViewDidClickedNameView:)]) { 119 [self.delegate headerViewDidClickedNameView:self]; 120 } 121 } 122 123 /** 124 * 当一个控件被添加到父控件中就会调用 125 */ 126 - (void)didMoveToSuperview 127 { 128 if (self.group.opened) { 129 self.nameView.imageView.transform = CGAffineTransformMakeRotation(M_PI_2); 130 } else { 131 self.nameView.imageView.transform = CGAffineTransformMakeRotation(0); 132 } 133 } 134 135 /** 136 * 当一个控件即将被添加到父控件中会调用 137 */ 138 //- (void)willMoveToSuperview:(UIView *)newSuperview 139 //{ 140 // 141 //} 142 @end
3.控制器部分
TXViewController.h文件
1 // TXViewController.h 2 // 04-QQ好友列表 3 // 4 // Created by 鑫 on 14-10-13. 5 // Copyright (c) 2014年 梁镋鑫. All rights reserved. 6 // 7 8 #import <UIKit/UIKit.h> 9 10 @interface TXViewController : UITableViewController 11 12 @end
TXViewController.m文件
1 #import "TXViewController.h" 2 #import "TXFriendGroup.h" 3 #import "TXFriend.h" 4 #import "TXHeaderView.h" 5 #import "TXFriendCell.h" 6 7 @interface TXViewController () <TXHeaderViewDelegate> 8 @property (nonatomic, strong) NSArray *groups; 9 @end 10 11 @implementation TXViewController 12 13 - (void)viewDidLoad 14 { 15 [super viewDidLoad]; 16 17 // 每一行cell的高度 18 self.tableView.rowHeight = 50; 19 // 每一组头部控件的高度 20 self.tableView.sectionHeaderHeight = 44; 21 } 22 23 - (NSArray *)groups 24 { 25 if (_groups == nil) { 26 NSArray *dictArray = [NSArray arrayWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"friends.plist" ofType:nil]]; 27 28 NSMutableArray *groupArray = [NSMutableArray array]; 29 for (NSDictionary *dict in dictArray) { 30 TXFriendGroup *group = [TXFriendGroup groupWithDict:dict]; 31 [groupArray addObject:group]; 32 } 33 34 _groups = groupArray; 35 } 36 return _groups; 37 } 38 39 - (BOOL)prefersStatusBarHidden 40 { 41 return YES; 42 } 43 44 #pragma mark - 数据源方法 45 - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView 46 { 47 return self.groups.count; 48 } 49 50 - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section 51 { 52 TXFriendGroup *group = self.groups[section]; 53 54 return (group.isOpened ? group.friends.count : 0); 55 } 56 57 - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath 58 { 59 // 1.创建cell 60 TXFriendCell *cell = [TXFriendCell cellWithTableView:tableView]; 61 62 // 2.设置cell的数据 63 TXFriendGroup *group = self.groups[indexPath.section]; 64 cell.friendData = group.friends[indexPath.row]; 65 66 return cell; 67 } 68 69 /** 70 * 返回每一组需要显示的头部标题(字符出纳) 71 */ 72 - (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section 73 { 74 // 1.创建头部控件 75 TXHeaderView *header = [TXHeaderView headerViewWithTableView:tableView]; 76 header.delegate = self; 77 78 // 2.给header设置数据(给header传递模型) 79 header.group = self.groups[section]; 80 81 return header; 82 } 83 84 #pragma mark - headerView的代理方法 85 /** 86 * 点击了headerView上面的名字按钮时就会调用 87 */ 88 - (void)headerViewDidClickedNameView:(TXHeaderView *)headerView 89 { 90 [self.tableView reloadData]; 91 } 92 @end
三、代码说明
1.项目文件结构
2.注意点
(1)调整字体的大小: self.textLabel.font=[UIFont systemFontOfSize:15.f];
(2)-(void)layoutSubviews方法。该方法在控件的frame被改变的时候就会调用,这个方法一般用于调整子控件的位置,注意一定要调用[super layoutSubviews];
(3)但凡在init方法中获取到的frame都是0;
(4)如果控件不显示,有以下一些排错方法
(5)请注意在设置按钮的文本时,一定要设置按钮的状态
(6)调用构造方法时,一定要先初始化父类的方法,先判断,再进行自己属性的初始化
1) 已经被添加到父视图上的时候会调用- (void)didMoveToSuperview
2) 即将被添加到父视图上的时候会调用- (void)willMoveToSuperview:(UIView *)newSuperview
(8)图片填充知识
1)设置btn中的图片不填充整个imageview btn.imageView.contentMode = UIViewContentModeCenter;
2)超出范围的图片不要剪切
//btn.imageView.clipsToBounds = NO;
btn.imageView.layer.masksToBounds = NO;
四、补充(代理)
@protocol YYHeaderViewDelegate <NSObject>
-(void)headerViewDidClickHeaderView:(YYHeaderView *)headerView;
@end
//delegate遵守YYHeaderViewDelegate这个协议,可以使用协议中的方法
@property(nonatomic,weak)id<YYHeaderViewDelegate> delegate;
@interface YYViewController ()<YYHeaderViewDelegate>
-(void)headerViewDidClickHeaderView:(YYHeaderView *)headerView
{
[self.tableView reloadData];
}
headerview.delegate=self;