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

效果:

补充:

1, 设置按钮的背景图片和按钮上的图片
    字体设置: [self.textView setTitle:message.text             
             forState:UIControlStateNormal];
     字体颜色: self.textView setTitleColor:[UIColor blueColor]
           forState:UIControlStateNormal];

    背景图片设置   btn setBackgroudImage: state:

    图片设置:    btn setImage:  state:
   特别注意:    设置按钮上图片的方法,不能用btn.imageView.image属性 这样图片不显示

 2,按钮上默认文字跟图片都是居中对齐的

     所以如果想设置其他对齐方式,可以调用按钮的对齐属性

     1,contentHorizontalAlignment 水平对齐

     2,contentVerticalAlignment 垂直对齐

 3,按钮的内边距设置

   默认按钮上的文字或图片都是填充整个按钮的宽度跟高度,如果我们想要设置按钮中的内容有跟边框有距离可以设置的属性

      1,contentEdgeInsets 按钮上整个内容内边距

      2,titleEdgeInsets 文字边距设置

      3,imageEdgeInsets  图片边距设置。

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已经确定了

 
 
原文地址:https://www.cnblogs.com/-boy/p/4136213.html