AJ学IOS(19)UI之QQ好友列表

AJ分享,必须精品

先看效果图

哈哈,这次猫猫给来个动态的图片,这个看起来带劲
这里写图片描述

实现思路

首先建立模型

这里用到的是一个双层的模型。

cell的实现

这里一看其实就知道是一个tableView,我们自定义cell实现细节

headerView的实现

每一组的标题头其实都是headerVIew这里都是按钮需要我们自己设计。

代码实现

双层模型的代码

FriendCell:

#import <Foundation/Foundation.h>
#import "NJGlobal.h"

@interface NJFriendModel : NSObject
// 头像
@property (nonatomic, copy) NSString *icon;
// 简介
@property (nonatomic, copy) NSString *intro;
// 昵称
@property (nonatomic, copy) NSString *name;
// 是否是vip
@property (nonatomic, assign, getter = isVip) BOOL vip;


NJInitH(friend)
@end

QQGroupModel:

#import <Foundation/Foundation.h>
#import "NJGlobal.h"

@interface NJQQGroupModel : NSObject
/// 存放当前组所有的好友信息(好友模型)
@property (nonatomic, strong) NSArray *friends;

// 分组名称
@property (nonatomic, copy) NSString *name;

// 在线人数
@property (nonatomic, copy) NSString *online;

// 记录当前组是否需要打开
@property (nonatomic, assign, getter = isOpen) BOOL open;

NJInitH(qqGroup)
@end

@implementation NJQQGroupModel

- (instancetype)initWithDict:(NSDictionary *)dict
{
    if (self = [super init]) {
        // 1.将字典转换成模型
        [self setValuesForKeysWithDictionary:dict];
        // 定义数组保存转换后的模型
        NSMutableArray *models = [NSMutableArray arrayWithCapacity:self.friends.count];
        // 2.特殊处理friends中的数据
        for (NSDictionary *dict in self.friends) {
            // 2.1转换为模型
            NJFriendModel *friend = [NJFriendModel friendWithDict:dict];
            [models addObject:friend];

        }
        self.friends = models;
    }
    return self;
}

+ (instancetype)qqGroupWithDict:(NSDictionary *)dict
{
    return [[self alloc] initWithDict:dict];

}
@end

cell 的自定义

#import <UIKit/UIKit.h>
@class NJFriendModel;

@interface NJFriendCell : UITableViewCell

+ (instancetype)cellWithTableView:(UITableView *)tableView;

@property (nonatomic, strong) NJFriendModel *friendData;

@end

@implementation NJFriendCell
+ (instancetype)cellWithTableView:(UITableView *)tableView
{
    static NSString *identifier = @"friend";
    NJFriendCell *cell = [tableView dequeueReusableCellWithIdentifier:identifier];
    if (cell == nil) {
        cell = [[NJFriendCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:identifier];
    }
    return cell;
}

- (void)setFriendData:(NJFriendModel *)friendData
{
    _friendData = friendData;

//    1.设置头像
    self.imageView.image = [UIImage imageNamed:_friendData.icon];
//    2.设置昵称
    self.textLabel.text = _friendData.name;
//    3.设置简介
    self.detailTextLabel.text = _friendData.intro;

//    4.判断是否是会员
    if (_friendData.isVip) {
        [self.textLabel setTextColor:[UIColor redColor]];
    }else
    {
        [self.textLabel setTextColor:[UIColor blackColor]];
    }
}
@end

header的自定义

#import "NJHeaderView.h"
#import "NJQQGroupModel.h"

#import <UIKit/UIKit.h>
@class NJFriendModel;

@interface NJFriendCell : UITableViewCell

+ (instancetype)cellWithTableView:(UITableView *)tableView;

@property (nonatomic, strong) NJFriendModel *friendData;

@end

@implementation NJFriendCell
+ (instancetype)cellWithTableView:(UITableView *)tableView
{
    static NSString *identifier = @"friend";
    NJFriendCell *cell = [tableView dequeueReusableCellWithIdentifier:identifier];
    if (cell == nil) {
        cell = [[NJFriendCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:identifier];
    }
    return cell;
}

- (void)setFriendData:(NJFriendModel *)friendData
{
    _friendData = friendData;

    //    1.设置头像
    self.imageView.image = [UIImage imageNamed:_friendData.icon];
    //    2.设置昵称
    self.textLabel.text = _friendData.name;
    //    3.设置简介
    self.detailTextLabel.text = _friendData.intro;

    //    4.判断是否是会员
    if (_friendData.isVip) {
        [self.textLabel setTextColor:[UIColor redColor]];
    }else
    {
        [self.textLabel setTextColor:[UIColor blackColor]];
    }
}
@end



@interface NJHeaderView ()
@property (nonatomic, weak) UIButton *btn;
@property (nonatomic, weak) UILabel *label;
@end

@implementation NJHeaderView

// 创建头部视图
+ (instancetype)headerViewWithTableView:(UITableView *)tableView
{
//    1.创建头部视图
    static NSString *identifier = @"header";
    NJHeaderView *headderView =  [tableView dequeueReusableHeaderFooterViewWithIdentifier:identifier];
    if (headderView == nil) {
        headderView = [[NJHeaderView alloc] initWithReuseIdentifier:identifier];
    }
    return headderView;
}

// 但凡在init方法中获取到的frame都是0
- (id)initWithReuseIdentifier:(NSString *)reuseIdentifier
{
    if (self = [super initWithReuseIdentifier:reuseIdentifier]) {
//        1.添加子控件
        // 1.1添加按钮
        UIButton *btn = [UIButton buttonWithType:UIButtonTypeCustom];
        // 监听按钮的点击事件
        [btn addTarget:self action:@selector(btnOnClick:) forControlEvents:UIControlEventTouchUpInside];
        // 设置按钮的背景图片
        [btn setBackgroundImage:[UIImage imageNamed:@"buddy_header_bg"] forState:UIControlStateNormal];
        [btn setBackgroundImage:[UIImage imageNamed:@"buddy_header_bg_highlighted"] forState:UIControlStateHighlighted];

        // 设置按钮上的尖尖图片
        [btn setImage:[UIImage imageNamed:@"buddy_header_arrow"] forState:UIControlStateNormal];
        // 1.设置按钮的内容左对齐
        btn.contentHorizontalAlignment = UIControlContentHorizontalAlignmentLeft;
        // 2.设置按钮的内边距,然按钮的内容距离左边有一定的距离
        btn.contentEdgeInsets = UIEdgeInsetsMake(0, 20, 0, 0);
        // 3.设置按钮的标题和图片之间的距离
        btn.titleEdgeInsets = UIEdgeInsetsMake(0, 20, 0, 0);
//        btn.imageEdgeInsets
        // 设置按钮标题颜色
        [btn setTitleColor:[UIColor blackColor] forState:UIControlStateNormal];

        // 设置btn中的图片不填充整个imageview
        btn.imageView.contentMode = UIViewContentModeCenter;
        // 超出范围的图片不要剪切
//        btn.imageView.clipsToBounds = NO;
        btn.imageView.layer.masksToBounds = NO;

        [self addSubview:btn];
        self.btn = btn;

        // 1.2添加label
        UILabel *label = [[UILabel alloc] init];
        // label.backgroundColor = [UIColor greenColor];
        // 设置文本右对齐
        label.textAlignment = NSTextAlignmentRight;
        label.textColor = [UIColor grayColor];

        [self addSubview:label];
        self.label = label;
    }

    //  NSLog(@"initWithReuseIdentifier = %@", NSStringFromCGRect(self.frame));
    return  self;
}
// 该方法在控件的frame被改变的时候就会调用
// 该方法一般用于调整子控件的位置
- (void)layoutSubviews
{
#warning 切记重写layoutSubviews方法一定要调用父类的layoutSubviews
    [super layoutSubviews];
//    1.设置按钮的frame
    self.btn.frame = self.bounds;
//    2.设置label的frame
    CGFloat padding = 20;// 间隙
    CGFloat labelY = 0;
    CGFloat labelH = self.bounds.size.height;
    CGFloat labelW = 150;
    CGFloat labelX = self.bounds.size.width - padding - labelW;
    self.label.frame = CGRectMake(labelX, labelY, labelW, labelH);
}

- (void)btnOnClick:(UIButton *)btn
{
    NSLog(@"按钮被点击了");
//     1.修改组模型的isOpen属性
//    修改模型数据数据
    self.qqGroup.open = !self.qqGroup.isOpen;
//    2. 刷新表格(通知代理)
    if ([self.delegate respondsToSelector:@selector(headerViewDidClickHeaderView:)]) {
        [self.delegate headerViewDidClickHeaderView:self];
    }

//    3.修改btn上图片,让图片旋转
    // self.btn.imageView.transform = CGAffineTransformMakeRotation(M_PI_2);

//    NSLog(@"%p %@", self, self.qqGroup.name);
}

#pragma mark - 当一个控件被添加到其它视图上的时候会调用以下方法
// 已经被添加到父视图上的时候会调用
- (void)didMoveToSuperview
{
    // 在这个方法中就快要拿到最新的被添加到tableview上的头部视图修改它的图片
    if (self.qqGroup.isOpen) {
        self.btn.imageView.transform = CGAffineTransformMakeRotation(M_PI_2);
    }
}
// 即将被添加到父视图上的时候会调用
- (void)willMoveToSuperview:(UIView *)newSuperview
{
    // NSLog(@"willMoveToSuperview");
}

- (void)setQqGroup:(NJQQGroupModel *)qqGroup
{
    _qqGroup = qqGroup;

//    1.设置按钮上的文字
    [self.btn setTitle:_qqGroup.name forState:UIControlStateNormal];
//    2.设置在线人数
    self.label.text = [NSString stringWithFormat:@"%@/%d",  _qqGroup.online, _qqGroup.friends.count];
}
@end

控制器代码

#import "NJViewController.h"
#import "NJQQGroupModel.h"
#import "NJFriendModel.h"
#import "NJFriendCell.h"
#import "NJHeaderView.h"

@interface NJViewController ()<NJHeaderViewDelegate>
// 保存所有的分组数据
@property (nonatomic, strong) NSArray *qqGroups;

@end

@implementation NJViewController



#pragma mark - 懒加载
- (NSArray *)qqGroups
{
    if (_qqGroups == nil) {
        NSString *fullPath = [[NSBundle mainBundle] pathForResource:@"friends.plist" ofType:nil];
        NSArray *dictArray = [NSArray arrayWithContentsOfFile:fullPath];
        NSMutableArray *models = [NSMutableArray arrayWithCapacity:dictArray.count];
        for (NSDictionary *dict in dictArray) {
            NJQQGroupModel *qqGroip = [NJQQGroupModel qqGroupWithDict:dict];
            [models addObject:qqGroip];
        }
        self.qqGroups = [models copy];
    }
    return _qqGroups;
}

- (void)viewDidLoad
{
    [super viewDidLoad];
}

#pragma mark - 数据源方法
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
    return self.qqGroups.count;
}

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
    // 1.取出对应的组模型
    NJQQGroupModel *qqGroup = self.qqGroups[section];
    // 2.返回对应组中的好友数
//    return qqGroup.friends.count;
//    return 0;
    if (qqGroup.isOpen) {
        // 代表要展开
        return qqGroup.friends.count;
    }else
    {
        // 代表要合拢
        return 0;
    }
}

- (UITableViewCell *) tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    // 1.创建cell
    NJFriendCell *cell = [NJFriendCell cellWithTableView:tableView];
    // 2.传递模型
    // 2.1.取出对应的组模型
    NJQQGroupModel *qqGroup = self.qqGroups[indexPath.section];
    NJFriendModel *friend = qqGroup.friends[indexPath.row];
    cell.friendData = friend;

    // 3.返回cell
    return cell;
}

#pragma mark - NJHeaderViewDelegate
- (void)headerViewDidClickHeaderView:(NJHeaderView *)headerView
{
    // 重新调用数据源的方法加载数据
    [self.tableView reloadData];
}

#pragma mark - 代理方法
// 当一个分组标题进入视野的时候就会调用该方法
- (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section
{
//    1.创建头部视图, 头部视图有默认的宽高,是系统自动设置
    NJHeaderView *headerView = [NJHeaderView headerViewWithTableView:tableView];
    // 设置当前控制器为代理
    headerView.delegate = self;

//    2.传递模型
    NJQQGroupModel *qqGroup =  self.qqGroups[section];
//    0 - 0x8fa7ef0
    headerView.qqGroup = qqGroup;
    NSLog(@"%d - %p", section, headerView);
//    3.返回头部视图
    return headerView;

}
// 设置分组头部标题的高度
- (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section
{
    return 44;
}

- (BOOL)prefersStatusBarHidden
{
    return YES;
}
@end
原文地址:https://www.cnblogs.com/luolianxi/p/4990359.html