欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  移动技术

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

程序员文章站 2022-09-14 14:33:19
1.仿QQ界面UITableView静态单元格使用静态单元格,必须使用UITableViewController控制器静态单元格使用建议:1> 先保留1个Section, 1个Cell。2> 设置好这个Cell以后, 在设置section的个数以及每个section中行的个数。静态单元格设置大致步骤:1> 选中TableView设置Content为static cell(静态单元格)2> 删除静态单元格, 只保留一个。3> 选中TableView设置st...
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

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

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

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

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

plist文件
IOS开发教程第一季之UI基础day9合并IOS学习009仿QQ界面(UITableView静态单元格)、仿QQ好友列表
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

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

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