zoukankan      html  css  js  c++  java
  • 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
  • 相关阅读:
    Leetcode: Insert Delete GetRandom O(1)
    Leetcode: Kth Smallest Element in a Sorted Matrix
    Leetcode: Combination Sum IV && Summary: The Key to Solve DP
    Leetcode: Wiggle Subsequence
    Leetcode: Guess Number Higher or Lower II
    Leetcode: Guess Number Higher or Lower
    Leetcode: Find K Pairs with Smallest Sums
    Leetcode: Super Pow
    Leetcode: Largest Divisible Subset
    Leetcode: Water and Jug Problem && Summary: GCD求法(辗转相除法 or Euclidean algorithm)
  • 原文地址:https://www.cnblogs.com/luolianxi/p/4990359.html
Copyright © 2011-2022 走看看