UI基础之UITableView案例QQ好友列表
一:模型数据
LLFriend
#import <Foundation/Foundation.h> @interface LLFriend : NSObject /** * icon */ @property (nonatomic, copy) NSString *icon; /** * intro */ @property (nonatomic, copy) NSString *intro; /** * name */ @property (nonatomic, copy) NSString *name; /** * vip */ @property (nonatomic, assign, getter=isVip) BOOL vip; - (instancetype)initWithDic:(NSDictionary *)dic; + (instancetype)friendWithDic:(NSDictionary *)dic; @end
#import "LLFriend.h" @implementation LLFriend - (instancetype)initWithDic:(NSDictionary *)dic { if (self = [super init]) { [self setValuesForKeysWithDictionary:dic]; } return self; } + (instancetype)friendWithDic:(NSDictionary *)dic { return [[self alloc] initWithDic:dic]; } @end
LLFriendGroup
#import <Foundation/Foundation.h> @interface LLFriendGroup : NSObject /** * friends模型 */ @property (nonatomic, strong) NSArray *friends; /** * name */ @property (nonatomic, copy) NSString *name; /** * online */ @property (nonatomic, assign) int online; /** * 是否合闭 */ @property (nonatomic, assign, getter=isOpened) BOOL opened; - (instancetype)initWithDic:(NSDictionary *)dic; + (instancetype)friendGroupWithDic:(NSDictionary *)dic; + (NSArray *)friendGroupList; @end
#import "LLFriendGroup.h" #import "LLFriend.h" @implementation LLFriendGroup - (instancetype)initWithDic:(NSDictionary *)dic { if (self = [super init]) { [self setValuesForKeysWithDictionary:dic]; NSMutableArray *tmpArray = [[NSMutableArray alloc] initWithCapacity:self.friends.count]; for (NSDictionary *dic in self.friends) { LLFriend *friend = [LLFriend friendWithDic:dic]; [tmpArray addObject:friend]; } self.friends = tmpArray; } return self; } + (instancetype)friendGroupWithDic:(NSDictionary *)dic { return [[self alloc] initWithDic:dic]; } + (NSArray *)friendGroupList { NSString *path = [[NSBundle mainBundle] pathForResource:@"friends" ofType:@"plist"]; NSArray *dicArr = [NSArray arrayWithContentsOfFile:path]; NSMutableArray *tmpArr = [[NSMutableArray alloc] initWithCapacity:dicArr.count]; for (NSDictionary *dic in dicArr) { LLFriendGroup *friendGroup = [LLFriendGroup friendGroupWithDic:dic]; [tmpArr addObject:friendGroup]; } return tmpArr; } @end
二:View
LLHeaderView
#import <UIKit/UIKit.h> @class LLFriendGroup; @class LLHeaderView; @protocol LLFriendGroupDelegate <NSObject> @optional - (void)friendGroupDidClickNameView:(LLHeaderView *)friendGroup; @end @interface LLHeaderView : UITableViewHeaderFooterView @property (nonatomic, weak) id<LLFriendGroupDelegate> delegate; @property (nonatomic, strong) LLFriendGroup *group; + (instancetype)headerViewWith:(UITableView *)tableView; @end
#import "LLHeaderView.h" #import "LLFriendGroup.h" @interface LLHeaderView () @property (nonatomic, weak) UIButton *nameView; @property (nonatomic, weak) UILabel *onlineView; @end @implementation LLHeaderView + (instancetype)headerViewWith:(UITableView *)tableView { static NSString *ID = @"headerView"; LLHeaderView *headerView = [tableView dequeueReusableHeaderFooterViewWithIdentifier:ID]; if (!headerView) { headerView = [[LLHeaderView alloc] initWithReuseIdentifier:ID]; } return headerView; } - (instancetype)initWithReuseIdentifier:(NSString *)reuseIdentifier { if (self = [super initWithReuseIdentifier:reuseIdentifier]) { // 按钮 UIButton *nameView = [UIButton buttonWithType:UIButtonTypeCustom]; [self.contentView addSubview:nameView]; self.nameView = nameView; [nameView setTitleColor:[UIColor blackColor] forState:UIControlStateNormal]; nameView.titleLabel.font = [UIFont systemFontOfSize:16]; [nameView setImage:[UIImage imageNamed:@"buddy_header_arrow"] forState:UIControlStateNormal]; [self.nameView setBackgroundImage:[UIImage imageNamed:@"buddy_header_bg"] forState:UIControlStateNormal]; [self.nameView setBackgroundImage:[UIImage imageNamed:@"buddy_header_bg_highlighted"] forState:UIControlStateHighlighted]; // 设置按钮中内容 nameView.contentHorizontalAlignment = UIControlContentHorizontalAlignmentLeft; nameView.contentEdgeInsets = UIEdgeInsetsMake(0, 10, 0, 0); nameView.titleEdgeInsets = UIEdgeInsetsMake(0, 10, 0, 0); // 设置按钮图片旋转变形的状态 #warning 设置按钮图片旋转变形的状态 nameView.imageView.contentMode = UIViewContentModeCenter; nameView.imageView.clipsToBounds = NO; // 按钮注册事件 [self.nameView addTarget:self action:@selector(clickNameView:) forControlEvents:UIControlEventTouchUpInside]; // label UILabel *onlineView = [[UILabel alloc] init]; [self.contentView addSubview:onlineView]; self.onlineView = onlineView; onlineView.textAlignment = NSTextAlignmentRight; onlineView.font = [UIFont systemFontOfSize:14]; onlineView.textColor = [UIColor grayColor]; } return self; } - (void)clickNameView:(UIButton *)sender { self.group.opened = !self.group.isOpened; if (self.group.isOpened) { sender.imageView.transform = CGAffineTransformMakeRotation(M_PI_2); } else { sender.imageView.transform = CGAffineTransformMakeRotation(0); } if ([self.delegate respondsToSelector:@selector(friendGroupDidClickNameView:)]) { [self.delegate friendGroupDidClickNameView:self]; } } // 布局子控件 - (void)layoutSubviews { #warning 必须调用父类的方法,否则按钮不能点击 [super layoutSubviews]; self.nameView.frame = self.bounds; CGFloat onlineY = 0; CGFloat onlineW = 150; CGFloat onlineH = self.bounds.size.height; CGFloat onlineX = self.bounds.size.width - onlineW - 10; self.onlineView.frame = CGRectMake(onlineX, onlineY, onlineW, onlineH); } - (void)setGroup:(LLFriendGroup *)group { _group = group; [self.nameView setTitle:group.name forState:UIControlStateNormal]; self.onlineView.text = [NSString stringWithFormat:@"%d/%ld",group.online, group.friends.count]; // set方法中一定要给子控件重新都赋值,否则可能因为cell重用引起的问题 if (self.group.isOpened) { self.nameView.imageView.transform = CGAffineTransformMakeRotation(M_PI_2); } else { self.nameView.imageView.transform = CGAffineTransformMakeRotation(0); } } @end
LLFriendCell
#import <UIKit/UIKit.h> @class LLFriend; @interface LLFriendCell : UITableViewCell @property (nonatomic, strong) LLFriend *friendData; + (instancetype)friendCellWith:(UITableView *)tableView; @end
#import "LLFriendCell.h" #import "LLFriend.h" @implementation LLFriendCell + (instancetype)friendCellWith:(UITableView *)tableView { static NSString *ID = @"friendCell"; LLFriendCell *cell = [tableView dequeueReusableCellWithIdentifier:ID]; if (!cell) { cell = [[LLFriendCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:ID]; } return cell; } - (void)setFriendData:(LLFriend *)friendData { _friendData = friendData; self.imageView.image = [UIImage imageNamed:friendData.icon]; self.textLabel.text = friendData.name; self.detailTextLabel.text = friendData.intro; if (friendData.isVip) { self.textLabel.textColor = [UIColor redColor]; } else { self.textLabel.textColor = [UIColor blackColor]; } } @end
三:
controller
#import "ViewController.h" #import "LLFriend.h" #import "LLFriendGroup.h" #import "LLHeaderView.h" #import "LLFriendCell.h" @interface ViewController ()<LLFriendGroupDelegate> @property (nonatomic, strong) NSArray *friendGroups; @end @implementation ViewController - (void)viewDidLoad { [super viewDidLoad]; // Do any additional setup after loading the view, typically from a nib. self.tableView.sectionHeaderHeight = 44; } #pragma mark - 懒加载数据 - (NSArray *)friendGroups { if (!_friendGroups) { _friendGroups = [LLFriendGroup friendGroupList]; } return _friendGroups; } #pragma mark - 数据源方法 - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView { return self.friendGroups.count; } - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { LLFriendGroup *group = self.friendGroups[section]; return group.isOpened ? group.friends.count : 0; // return 0; } - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { LLFriendCell *cell = [LLFriendCell friendCellWith:tableView]; cell.friendData = [self.friendGroups[indexPath.section] friends][indexPath.row]; return cell; } #pragma mark - tableView的代理方法 - (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section { LLHeaderView *headerView = [LLHeaderView headerViewWith:tableView]; headerView.group = self.friendGroups[section]; headerView.delegate = self; return headerView; } #pragma mark - LLFriendGroup代理方法 - (void)friendGroupDidClickNameView:(LLHeaderView *)friendGroup { // NSIndexSet *indexSet = [NSIndexSet indexSetWithIndex:<#(NSUInteger)#>] // self.tableView reloadSections:<#(NSIndexSet *)#> withRowAnimation:<#(UITableViewRowAnimation)#> [self.tableView reloadData]; } - (BOOL)prefersStatusBarHidden { return YES; } @end
效果:
补充:
背景图片设置 btn setBackgroudImage: state:
2,按钮上默认文字跟图片都是居中对齐的
所以如果想设置其他对齐方式,可以调用按钮的对齐属性
1,contentHorizontalAlignment 水平对齐
2,contentVerticalAlignment 垂直对齐
3,按钮的内边距设置
默认按钮上的文字或图片都是填充整个按钮的宽度跟高度,如果我们想要设置按钮中的内容有跟边框有距离可以设置的属性
1,contentEdgeInsets 按钮上整个内容内边距
2,titleEdgeInsets 文字边距设置
4,按钮上的图片旋转后被拉伸的处理
设置按钮内部的imageView的内容模式为居中,因为默认会填充整个imageView
btn.imageView.contentMode = UIViewContentModeCenter
btn.imageView.clipsToBounds = NO; 默认为yes表示超出的部分减掉
5:
- (instancetype)initWithReuseIdentifier:(NSString *)reuseIdentifier
{
if (self = [super initWithReuseIdentifier:reuseIdentifier]) {
NSLog(@"%f", self.frame.size.height); // height为0;
}
init方法中,self对象和它父类的frame初始化过程中都为0;
所以没法确定子类的frame,在layoutSubview方法中父类的frame已经确定了