当前位置: 移动技术网 > 移动技术>移动开发>IOS > IOS开发教程第一季之UI基础day9合并IOS学习009仿QQ界面(UITableView静态单元格)、仿QQ好友列表

IOS开发教程第一季之UI基础day9合并IOS学习009仿QQ界面(UITableView静态单元格)、仿QQ好友列表

2020年07月09日  | 移动技术网移动技术  | 我要评论
1.仿QQ界面UITableView静态单元格

使用静态单元格,必须使用UITableViewController控制器

  • 静态单元格使用建议:
    1> 先保留1个Section, 1个Cell。
    2> 设置好这个Cell以后, 在设置section的个数以及每个section中行的个数。

    • 静态单元格设置大致步骤:
      1> 选中TableView设置Content为static cell(静态单元格)

    2> 删除静态单元格, 只保留一个。

    3> 选中TableView设置style为grouped

    4> 选中单元格, 设置设置style为basic、设置Accessory为Disclosure Indicator。

    5> 双击"Title"设置文字.

    6> 选中单元格设置Image属性为: found_icons_qzone
    6.1> 选中 UITableView设置 style 为 Grouped

    7> 选中tableView设置Section为 3。

    8> 选中第二个Section设置Rows为 2

    9> 选中第三个Section设置Rows为 3

    ** 注意: 当设置了数据源对象, 并且实现了数据源方法的时候, 即便有静态单元格也优先调用数据源方法来生成数据。

效果如下:
在这里插入图片描述

在这里插入图片描述

2.仿QQ好友列表分组显示完整版本

plist文件
在这里插入图片描述
1、创建FRFriend模型
FRFriend.h

#import <Foundation/Foundation.h>

NS_ASSUME_NONNULL_BEGIN
//创建数据模型
@interface FRFriend : NSObject
@property(nonatomic,copy)NSString* icon;//头像
@property(nonatomic,copy)NSString* intro;//签名
@property(nonatomic,copy)NSString* name;//昵称
@property(nonatomic,assign,getter=isVip)BOOL vip;//是否vip

-(instancetype)initWithDictionary:(NSDictionary*)dict;
+(instancetype)friendWithDictionary:(NSDictionary*)dict;
@end

NS_ASSUME_NONNULL_END

FRFriend.m

#import "FRFriend.h"

@implementation FRFriend
-(instancetype)initWithDictionary:(NSDictionary*)dict{
  if (self= [super init]) {
    [self setValuesForKeysWithDictionary:dict];
  }
  return self;
}
+(instancetype)friendWithDictionary:(NSDictionary*)dict{
  return [[self alloc]initWithDictionary:dict];
}
@end

2、创建FRFriendGroup模型
FRFriendGroup.h

#import <Foundation/Foundation.h>

NS_ASSUME_NONNULL_BEGIN

@interface FRFriendGroup : NSObject
@property(nonatomic,strong)NSArray* friends;//所有好友
@property(nonatomic,copy)NSString* name;//组名
@property(nonatomic,assign)NSNumber* online;//在线人数
@property(nonatomic,assign,getter=isVisible)BOOL visible;//表示该组是否可见(展开)


-(instancetype)initWithDictionary:(NSDictionary*)dict;
+(instancetype)groupWithDictionary:(NSDictionary*)dict;


@end

NS_ASSUME_NONNULL_END

FRFriendGroup.m

#import "FRFriendGroup.h"
#import "FRFriend.h"
@implementation FRFriendGroup
-(instancetype)initWithDictionary:(NSDictionary*)dict{
  if (self=[super init]) {
    [self setValuesForKeysWithDictionary:dict];
    //把字典里的friends数组再转一次模型
    NSMutableArray* arrayModelM=[NSMutableArray array];
    for (NSDictionary* subdict in self.friends) {
      //创建FRiend模型
      FRFriend* friendModel=[FRFriend friendWithDictionary:subdict];
      [arrayModelM addObject:friendModel];
    }
    self.friends=arrayModelM;
  }
  return self;
}
+(instancetype)groupWithDictionary:(NSDictionary*)dict{
  return [[self alloc]initWithDictionary:dict];
}
@end

3、创建FRFriendCell单元格类
FRFriendCell.h

#import <UIKit/UIKit.h>
@class FRFriend;
NS_ASSUME_NONNULL_BEGIN

@interface FRFriendCell : UITableViewCell
//friend模型属性
@property(nonatomic,strong)FRFriend* friendModel;

//创建单元格的类方法
+(instancetype)friendCellWithTableView:(UITableView*)tableView;

@end

NS_ASSUME_NONNULL_END

FRFriendCell.m

#import "FRFriendCell.h"
#import "FRFriend.h"
@implementation FRFriendCell
+(instancetype)friendCellWithTableView:(UITableView*)tableView{
  //创建单元格(视图)
  NSString* strId=@"friend_cell";
  FRFriendCell *cell = [tableView dequeueReusableCellWithIdentifier:strId];
  if (cell==nil) {
    cell = [[FRFriendCell alloc]initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:strId];
  }
  return cell;
}


//重写friendModel属性的set方法
-(void)setFriendModel:(FRFriend *)friendModel{
  _friendModel=friendModel;
  //设置各个控件的值,把模型数据的各个值设置给单元的子控件
  self.imageView.image=[UIImage imageNamed:friendModel.icon];
  self.textLabel.text=friendModel.name;
  self.detailTextLabel.text=friendModel.intro;
  
  //根据当前的好友是不是vip设置好友不同的名字显示颜色
  self.textLabel.textColor=friendModel.isVip?[UIColor redColor]:[UIColor blackColor];
  
}
- (void)awakeFromNib {
    [super awakeFromNib];
    // Initialization code
}

- (void)setSelected:(BOOL)selected animated:(BOOL)animated {
    [super setSelected:selected animated:animated];

    // Configure the view for the selected state
}

@end

4、创建FRGroupHeadView标题类
FRGroupHeadView.h

#import <UIKit/UIKit.h>
#import "FRFriendGroup.h"
@class FRGroupHeadView;
NS_ASSUME_NONNULL_BEGIN
//创建一个协议
@protocol FRGroupHeadViewDelegate <NSObject>

-(void)groupHeaderViewDidClickTitleButton:(FRGroupHeadView*) groupHeaderView;

@end


@interface FRGroupHeadView : UITableViewHeaderFooterView
@property(nonatomic,strong) FRFriendGroup* group;
//添加一个代理属性
@property(nonatomic,weak)id<FRGroupHeadViewDelegate> delegate;
-(void)didMoveToSuperview;

+(instancetype)groupHeaderViewWithTableView:(UITableView*)tableView;
@end

NS_ASSUME_NONNULL_END

FRGroupHeadView.m

#import "FRGroupHeadView.h"
#import "FRFriendGroup.h"
@interface FRGroupHeadView()
@property(nonatomic,weak)UIButton* btnGroupTitle;
@property(nonatomic,weak)UILabel* lblCount;

@end

@implementation FRGroupHeadView
//封装一个类方法来创建一个headerView
+(instancetype)groupHeaderViewWithTableView:(UITableView*)tableView{
  //2、创建UITableViewHeaderFooterView,这里和创建单元格很像
  static NSString* strId=@"group_header_view";
  FRGroupHeadView* headerView=[tableView dequeueReusableHeaderFooterViewWithIdentifier:strId];
  if (headerView==nil) {
    //创建一个新的UITableViewHeaderFooterView
    headerView=[[FRGroupHeadView alloc]initWithReuseIdentifier:strId];
  }
  //headerView.contentView.backgroundColor=[UIColor greenColor];
  return headerView;
}

//重写initWithReuseIdentifier方法
-(instancetype)initWithReuseIdentifier:(NSString*)reuseIdentifier{
  if (self=[super initWithReuseIdentifier:reuseIdentifier]) {
   //创建按钮
    UIButton *btnGroupTitle=[[UIButton alloc]init];
    //设置按钮的图片
    [btnGroupTitle setImage:[UIImage imageNamed:@"buddy_header_arrow"] forState:UIControlStateNormal];
    //设置按钮的文字演示
    [btnGroupTitle setTitleColor:[UIColor blackColor] forState:UIControlStateNormal];
    //设置按钮的背景图
    [btnGroupTitle setBackgroundImage:[UIImage imageNamed:@"buddy_header_bg"] forState:UIControlStateNormal];
    [btnGroupTitle setBackgroundImage:[UIImage imageNamed:@"buddy_header_bg_highlighted"] forState:UIControlStateHighlighted];

    //设置按钮内容左对齐
    btnGroupTitle.contentHorizontalAlignment=UIControlContentHorizontalAlignmentLeft;
    //设置按钮的左边距
    btnGroupTitle.contentEdgeInsets=UIEdgeInsetsMake(0, 10, 0, 0);
    //设置按钮标题距离左边的边距
    btnGroupTitle.titleEdgeInsets=UIEdgeInsetsMake(0, 5, 0, 0);
    
    //设置按钮的点击事件
    [btnGroupTitle addTarget:self action:@selector(btnGroupTitleClicked) forControlEvents:UIControlEventTouchUpInside];
    
    //设置按钮中图片的显示模式
    btnGroupTitle.imageView.contentMode=UIViewContentModeCenter;
    //设置图片框超出的部分不要截取
    btnGroupTitle.imageView.clipsToBounds=NO;
    
    //将按钮添加到contentview上
    [self.contentView addSubview:btnGroupTitle];
    self.btnGroupTitle=btnGroupTitle;
    
   //创建lable
    UILabel* lblCount=[[UILabel alloc]init];
    [self.contentView addSubview:lblCount];
    self.lblCount=lblCount;

  }
  return self;
}

//创建一个主标题按钮点击事件
-(void)btnGroupTitleClicked{
  //1.设置组状态
  self.group.visible = !self.group.isVisible;
  
  //2.刷新tableview,通过代理来实现
  if ([self.delegate respondsToSelector:@selector(groupHeaderViewDidClickTitleButton:)]) {
    //调用代理方法
    [self.delegate groupHeaderViewDidClickTitleButton:self];
  }
}


//当一个新的headerview已经加载到某个父控件中的时候执行这个方法
-(void)didMoveToSuperview{
  if (self.group.isVisible) {
    //3、让按钮中的图片实现旋转
    self.btnGroupTitle.imageView.transform=CGAffineTransformMakeRotation(M_PI_2);
  }else{
    //让按钮中的图片实现旋转回到原来的位置
    self.btnGroupTitle.imageView.transform=CGAffineTransformMakeRotation(0);

  }
  
  
  
}
//重写group的set方法
-(void)setGroup:(FRFriendGroup *)group{
  _group=group;
  //设置数据
  [self.btnGroupTitle setTitle:group.name forState:UIControlStateNormal];
  self.lblCount.text=[NSString stringWithFormat:@"%@ / %ld",group.online,group.friends.count];
  
  //设置按钮中图片的旋转问题
  if (self.group.isVisible) {
    //3、让按钮中的图片实现旋转
    self.btnGroupTitle.imageView.transform=CGAffineTransformMakeRotation(M_PI_2);
  }else{
    //让按钮中的图片实现旋转回到原来的位置
    self.btnGroupTitle.imageView.transform=CGAffineTransformMakeRotation(0);

  }
  
  //设置frame不要写在这里

}
//重写重新布局子控件
//当年控件的frame发生改变的时候会调用这个方法
-(void)layoutSubviews{
  [super layoutSubviews];
  //设置frame
  self.btnGroupTitle.frame=self.bounds;
  CGFloat lblW=100;
  CGFloat lblH=self.bounds.size.height;
  CGFloat lblX=self.bounds.size.width-10-lblW;
  CGFloat lblY=0;
  
  self.lblCount.frame=CGRectMake(lblX, lblY, lblW, lblH);
  
}
@end

4、自定义FRQQFriendsTableViewController控制器类
FRQQFriendsTableViewController.m

#import "FRQQFriendsTableViewController.h"
#import "FRFriendGroup.h"
#import "FRFriend.h"
#import "FRFriendCell.h"
#import "FRGroupHeadView.h"
@interface FRQQFriendsTableViewController ()<FRGroupHeadViewDelegate>
//保存所有的分组信息
@property(nonatomic,strong)NSArray* groups;
@end

@implementation FRQQFriendsTableViewController
//实现FRGroupHeadViewDelegate代理方法
-(void)groupHeaderViewDidClickTitleButton:(FRGroupHeadView *)groupHeaderView{
  //全局刷新tableview
  //[self.tableView reloadData];
  //局部刷新(只刷新某个组)
  //创建一个用来表示某个组的对象
  NSIndexSet* indexSet=[NSIndexSet indexSetWithIndex:groupHeaderView.tag];
  [self.tableView reloadSections:indexSet withRowAnimation:UITableViewRowAnimationFade];
}


//懒加载数据
//重写group的get方法
-(NSArray*)groups{
  if (_groups==nil) {
    //获取plist文件路径
    NSString* path=[[NSBundle mainBundle]pathForResource:@"friends.plist" ofType:nil];
    
    //通过path路径获得plist文件中字典的集合
    NSArray* arrayDict=[NSArray arrayWithContentsOfFile:path];
    //创建group模型可变数组
    NSMutableArray* arrayModelM=[NSMutableArray array];
    //遍历字典数组
    for (NSDictionary* dict in arrayDict) {
      FRFriendGroup* groupModel=[FRFriendGroup groupWithDictionary:dict];
      [arrayModelM addObject:groupModel];
    }
    //创建模型并将其加入模型数组中
    _groups=arrayModelM;
   
  }
  //返回goups属性
  return _groups;
  
}

- (void)viewDidLoad {
    [super viewDidLoad];
    //统一设置每组组标题的高度
  self.tableView.sectionHeaderHeight=44;
  
}

#pragma mark - Table view data source
//返回数据源方法
//返回分组数量
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
  return self.groups.count;
}
//返回每组的行数
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
  
  //因为要根据当前组的状态(是否展开),来设置不同的返回值,所以要为FRFriendGroup模型
  //增加一个用来保存”是否展开“状态的属性
  
  FRFriendGroup* group=self.groups[section];
  if (group.isVisible) {//如果可见
    return group.friends.count;//返回实际条数,即展开
  }else{
    return 0;//如果不可见,返回0条记录,即收拢
  }
}

//返回每行的单元格
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
  //获取模型(数据)
  //先获取组模型,在获取friend模型
  FRFriendGroup* group=self.groups[indexPath.section];
  FRFriend* friend=group.friends[indexPath.row];
  
  //创建单元格(视图)
  
  FRFriendCell *cell =[FRFriendCell friendCellWithTableView:tableView];
  //给单元格赋值(把模型设置给单元格)
  cell.friendModel=friend;
  //返回单元格
  return cell;
}

//设置每一组的组标题(该方法仅能设置组标题字符串,但我们需要更多的内容,该方法不太够用了)
/*
-(NSString*)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section{
  //创建组模型
  FRFriendGroup* group=self.groups[section];
  //总组模型中取name属性
  return group.name;
}
 */

//设置组标题返回一个view
-(UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section{
  //创建一个UITableViewHeaderFooterView,实现重用,千万不要创建UIView
  //1、获取模型数据(分组模型就可以了)
  FRFriendGroup* group=self.groups[section];
  //2、创建UITableViewHeaderFooterView,这里和创建单元格很像
  FRGroupHeadView* headerView=[FRGroupHeadView groupHeaderViewWithTableView:tableView];
  headerView.tag=section;
  //3、设置数据
  headerView.group=group;
  
  //设置headerView的代理为当前控制器
  headerView.delegate=self;
  
  //在刚刚创建好的headerView中获取的Frame都是0,因为我们没有为其frame赋值,因此其frame都是0,
  //但程序运行时能看到起frame,是因为,当前方法中,将headerview返回以后,UITableView在执行时,会用到headerView,
  //UITableView既然要用HeaderView,那么必须将headview添加到UITableView,UITableView内部会根据 一些设置来动态地为headerview的frame赋值,
  //也就是,UITableView在即将用headerv的时候才会为headerview来设置值
  //4、返回view
  return headerView;
}

@end

效果:
在这里插入图片描述
源码下载

本文地址:https://blog.csdn.net/weixin_43745804/article/details/107178684

如对本文有疑问, 点击进行留言回复!!

相关文章:

验证码:
移动技术网