首页 > 代码库 > iOS开发UI篇—使用UItableview完成一个简单的QQ好友列表(二)

iOS开发UI篇—使用UItableview完成一个简单的QQ好友列表(二)

一、实现效果

           

二、实现代码

1.数据模型部分

TXFriendGroup.h文件

 1 #import <Foundation/Foundation.h> 2  3 @interface TXFriendGroup : NSObject 4 @property (nonatomic, copy) NSString *name; 5 /** 6  *  数组中装的都是TXriend模型 7  */ 8 @property (nonatomic, strong) NSArray *friends; 9 @property (nonatomic, assign) int online;10 11 + (instancetype)groupWithDict:(NSDictionary *)dict;12 - (instancetype)initWithDict:(NSDictionary *)dict;13 @property (nonatomic, assign, getter = isOpened) BOOL opened;14 15 16 @end

 

 TXFriendGroup.m文件

 1 //  Created by 鑫 on 14-10-13. 2 //  Copyright (c) 2014年 梁镋鑫. All rights reserved. 3 // 4  5 #import "TXFriendGroup.h" 6 #import "TXFriend.h" 7 @implementation TXFriendGroup 8 + (instancetype)groupWithDict:(NSDictionary *)dict 9 {10     return [[self alloc] initWithDict:dict];11 }12 13 - (instancetype)initWithDict:(NSDictionary *)dict14 {15     if (self = [super init]) {16         // 1.注入所有属性17         [self setValuesForKeysWithDictionary:dict];18         19         // 2.特殊处理friends属性20         NSMutableArray *friendArray = [NSMutableArray array];21         for (NSDictionary *dict in self.friends) {22             TXFriend *friend = [TXFriend friendWithDict:dict];23             [friendArray addObject:friend];24         }25         self.friends = friendArray;26     }27     return self;28 }29 30 @end

 

TXFriend.h文件

 1 #import <Foundation/Foundation.h> 2  3 @interface TXFriend : NSObject 4 @property (nonatomic, copy) NSString *name; 5 @property (nonatomic, copy) NSString *icon; 6 @property (nonatomic, copy) NSString *intro; 7 @property (nonatomic, assign, getter = isVip) BOOL vip; 8  9 + (instancetype)friendWithDict:(NSDictionary *)dict;10 - (instancetype)initWithDict:(NSDictionary *)dict;11 12 @end

 

TXFriend.m文件

 1 #import "TXFriend.h" 2  3 @implementation TXFriend 4 + (instancetype)friendWithDict:(NSDictionary *)dict 5 { 6     return [[self alloc] initWithDict:dict]; 7 } 8  9 - (instancetype)initWithDict:(NSDictionary *)dict10 {11     if (self = [super init]) {12         [self setValuesForKeysWithDictionary:dict];13     }14     return self;15 }16 17 @end

 

2.视图部分

TXFriendCell.h文件

1 #import <UIKit/UIKit.h>2 @class TXFriend;3 @interface TXFriendCell : UITableViewCell4 + (instancetype)cellWithTableView:(UITableView *)tableView;5 // friend是C++的关键字,不能用friend作为属性名6 @property (nonatomic, strong) TXFriend *friendData;7 @end

 

TXFriendCell.m文件

 1 #import "TXFriendCell.h" 2 #import "TXFriend.h" 3 @implementation TXFriendCell 4  5 + (instancetype)cellWithTableView:(UITableView *)tableView 6 { 7     static NSString *ID = @"friend"; 8     TXFriendCell *cell = [tableView dequeueReusableCellWithIdentifier:ID]; 9     if (cell == nil) {10         cell = [[TXFriendCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:ID];11     }12     return cell;13 }14 15 - (void)setFriendData:(TXFriend *)friendData16 {17     _friendData =http://www.mamicode.com/ friendData;18     19     self.imageView.image = [UIImage imageNamed:friendData.icon];20     self.textLabel.text = friendData.name;21     self.detailTextLabel.text = friendData.intro;22 }23 24 @end

 

TXHeaderView.h文件

 1 //  TXHeaderView.h 2 //  04-QQ好友列表 3 // 4 //  Created by 鑫 on 14-10-14. 5 //  Copyright (c) 2014年 梁镋鑫. All rights reserved. 6 // 7  8 #import <UIKit/UIKit.h> 9 @class TXFriendGroup, TXHeaderView;10 //把自己的名字全进去TXHeaderView,告诉他那个家伙身上的按钮备点11 12 @protocol TXHeaderViewDelegate <NSObject>13 @optional14 - (void)headerViewDidClickedNameView:(TXHeaderView *)headerView;15 @end16 17 @interface TXHeaderView : UITableViewHeaderFooterView18 + (instancetype)headerViewWithTableView:(UITableView *)tableView;19 20 @property (nonatomic, strong) TXFriendGroup *group;21 22 @property (nonatomic, weak) id<TXHeaderViewDelegate> delegate;23 @end

 

TXHeaderView.m文件

  1 #import "TXHeaderView.h"  2 #import "TXFriendGroup.h"  3   4 /**  5  某个控件出不来:  6  1.frame的尺寸和位置对不对  7    8  2.hidden是否为YES  9   10  3.有没有添加到父控件中 11   12  4.alpha 是否 < 0.01 13   14  5.被其他控件挡住了 15   16  6.父控件的前面5个情况 17  */ 18  19 @interface TXHeaderView() 20 @property (nonatomic, weak) UILabel *countView; 21 @property (nonatomic, weak) UIButton *nameView; 22 @end 23  24 @implementation TXHeaderView 25  26 + (instancetype)headerViewWithTableView:(UITableView *)tableView 27 { 28     static NSString *ID = @"header"; 29     TXHeaderView *header = [tableView dequeueReusableHeaderFooterViewWithIdentifier:ID]; 30     if (header == nil) { 31         header = [[TXHeaderView alloc] initWithReuseIdentifier:ID]; 32     } 33     return header; 34 } 35  36 /** 37  *  在这个初始化方法中,TXHeaderView的frame\bounds没有值 38  */ 39 - (id)initWithReuseIdentifier:(NSString *)reuseIdentifier 40 { 41     if (self = [super initWithReuseIdentifier:reuseIdentifier]) { 42         // 添加子控件 43         // 1.添加按钮 44         UIButton *nameView = [UIButton buttonWithType:UIButtonTypeCustom]; 45         // 背景图片 46         [nameView setBackgroundImage:[UIImage imageNamed:@"buddy_header_bg"] forState:UIControlStateNormal]; 47         [nameView setBackgroundImage:[UIImage imageNamed:@"buddy_header_bg_highlighted"] forState:UIControlStateHighlighted]; 48         // 设置按钮内部的左边箭头图片 49         [nameView setImage:[UIImage imageNamed:@"buddy_header_arrow"] forState:UIControlStateNormal]; 50         [nameView setTitleColor:[UIColor blackColor] forState:UIControlStateNormal]; 51         // 设置按钮的内容左对齐 52         nameView.contentHorizontalAlignment = UIControlContentHorizontalAlignmentLeft; 53         // 设置按钮的内边距 54         //        nameView.imageEdgeInsets 55         nameView.titleEdgeInsets = UIEdgeInsetsMake(0, 10, 0, 0); 56         nameView.contentEdgeInsets = UIEdgeInsetsMake(0, 10, 0, 0); 57         [nameView addTarget:self action:@selector(nameViewClick) forControlEvents:UIControlEventTouchUpInside]; 58          59         // 设置按钮内部的imageView的内容模式为居中 60         nameView.imageView.contentMode = UIViewContentModeCenter; 61         // 超出边框的内容不需要裁剪 62         nameView.imageView.clipsToBounds = NO; 63          64         [self.contentView addSubview:nameView]; 65         self.nameView = nameView; 66          67         // 2.添加好友数 68         UILabel *countView = [[UILabel alloc] init]; 69         countView.textAlignment = NSTextAlignmentRight; 70         countView.textColor = [UIColor grayColor]; 71         [self.contentView addSubview:countView]; 72         self.countView = countView; 73     } 74     return self; 75 } 76  77 /** 78  *  当一个控件的frame发生改变的时候就会调用 79  * 80  *  一般在这里布局内部的子控件(设置子控件的frame) 81  */ 82 - (void)layoutSubviews 83 { 84 #warning 一定要调用super的方法 85     [super layoutSubviews]; 86      87     // 1.设置按钮的frame 88     self.nameView.frame = self.bounds; 89      90     // 2.设置好友数的frame 91     CGFloat countY = 0; 92     CGFloat countH = self.frame.size.height; 93     CGFloat countW = 150; 94     CGFloat countX = self.frame.size.width - 10 - countW; 95     self.countView.frame = CGRectMake(countX, countY, countW, countH); 96 } 97  98 - (void)setGroup:(TXFriendGroup *)group 99 {100     _group = group;101     102     // 1.设置按钮文字(组名)103     [self.nameView setTitle:group.name forState:UIControlStateNormal];104     105     // 2.设置好友数(在线数/总数)106     self.countView.text = [NSString stringWithFormat:@"%d/%d", group.online, group.friends.count];107 }108 109 /**110  *  监听组名按钮的点击111  */112 - (void)nameViewClick113 {114     // 1.修改组模型的标记(状态取反)115     self.group.opened = !self.group.isOpened;116     117     // 2.刷新表格118     if ([self.delegate respondsToSelector:@selector(headerViewDidClickedNameView:)]) {119         [self.delegate headerViewDidClickedNameView:self];120     }121 }122 123 /**124  *  当一个控件被添加到父控件中就会调用125  */126 - (void)didMoveToSuperview127 {128     if (self.group.opened) {129         self.nameView.imageView.transform = CGAffineTransformMakeRotation(M_PI_2);130     } else {131         self.nameView.imageView.transform = CGAffineTransformMakeRotation(0);132     }133 }134 135 /**136  *  当一个控件即将被添加到父控件中会调用137  */138 //- (void)willMoveToSuperview:(UIView *)newSuperview139 //{140 //141 //}142 @end

 

3.控制器部分

TXViewController.h文件

 1 //  TXViewController.h 2 //  04-QQ好友列表 3 // 4 //  Created by 鑫 on 14-10-13. 5 //  Copyright (c) 2014年 梁镋鑫. All rights reserved. 6 // 7  8 #import <UIKit/UIKit.h> 9 10 @interface TXViewController : UITableViewController11 12 @end

 

TXViewController.m文件

 1 #import "TXViewController.h" 2 #import "TXFriendGroup.h" 3 #import "TXFriend.h" 4 #import "TXHeaderView.h" 5 #import "TXFriendCell.h" 6  7 @interface TXViewController () <TXHeaderViewDelegate> 8 @property (nonatomic, strong) NSArray *groups; 9 @end10 11 @implementation TXViewController12 13 - (void)viewDidLoad14 {15     [super viewDidLoad];16     17     // 每一行cell的高度18     self.tableView.rowHeight = 50;19     // 每一组头部控件的高度20     self.tableView.sectionHeaderHeight = 44;21 }22 23 - (NSArray *)groups24 {25     if (_groups == nil) {26         NSArray *dictArray = [NSArray arrayWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"friends.plist" ofType:nil]];27         28         NSMutableArray *groupArray = [NSMutableArray array];29         for (NSDictionary *dict in dictArray) {30             TXFriendGroup *group = [TXFriendGroup groupWithDict:dict];31             [groupArray addObject:group];32         }33         34         _groups = groupArray;35     }36     return _groups;37 }38 39 - (BOOL)prefersStatusBarHidden40 {41     return YES;42 }43 44 #pragma mark - 数据源方法45 - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView46 {47     return self.groups.count;48 }49 50 - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section51 {52     TXFriendGroup *group = self.groups[section];53     54     return (group.isOpened ? group.friends.count : 0);55 }56 57 - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath58 {59     // 1.创建cell60     TXFriendCell *cell = [TXFriendCell cellWithTableView:tableView];61     62     // 2.设置cell的数据63     TXFriendGroup *group = self.groups[indexPath.section];64     cell.friendData =http://www.mamicode.com/ group.friends[indexPath.row];65     66     return cell;67 }68 69 /**70  *  返回每一组需要显示的头部标题(字符出纳)71  */72 - (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section73 {74     // 1.创建头部控件75     TXHeaderView *header = [TXHeaderView headerViewWithTableView:tableView];76     header.delegate = self;77     78     // 2.给header设置数据(给header传递模型)79     header.group = self.groups[section];80     81     return header;82 }83 84 #pragma mark - headerView的代理方法85 /**86  *  点击了headerView上面的名字按钮时就会调用87  */88 - (void)headerViewDidClickedNameView:(TXHeaderView *)headerView89 {90     [self.tableView reloadData];91 }92 @end

 

三、代码说明

1.项目文件结构

2.注意点

(1)调整字体的大小:    self.textLabel.font=[UIFont systemFontOfSize:15.f];

(2)-(void)layoutSubviews方法。该方法在控件的frame被改变的时候就会调用,这个方法一般用于调整子控件的位置,注意一定要调用[super layoutSubviews];

(3)但凡在init方法中获取到的frame都是0;

(4)如果控件不显示,有以下一些排错方法

a.frame为空(没有设置frame)
b.hidden是否为YES
c.alpha<=0.1(透明度)
d.没有添加到父控件中
e.查看父控件以上几点

(5)请注意在设置按钮的文本时,一定要设置按钮的状态

正确:[self.btn setTitle:_group.name forState:UIControlStateNormal];
错误: self.btn.titleLabel.text=_group.name;

(6)调用构造方法时,一定要先初始化父类的方法,先判断,再进行自己属性的初始化

self=[super initWithReuseIdentifier:reuseIdentifier]
if(self)
{
……
}
(7)当一个控件被添加到其它视图上的时候会调用以下方法

1) 已经被添加到父视图上的时候会调用- (void)didMoveToSuperview

2) 即将被添加到父视图上的时候会调用- (void)willMoveToSuperview:(UIView *)newSuperview

(8)图片填充知识

   1)设置btn中的图片不填充整个imageview btn.imageView.contentMode = UIViewContentModeCenter;

   2)超出范围的图片不要剪切

  //btn.imageView.clipsToBounds = NO;

  btn.imageView.layer.masksToBounds = NO;

四、补充(代理)

设置代理的几个步骤
(1)如果一个视图中的某个按钮被点击了,这个时候需要去主控制器中刷新数据。有一种做法是,让这个视图拥有控制器这个属性,然后当按钮被点击的时候去利用该属性去做刷新数据的操作。另一种做法是把控制器设置为这个视图的代理,当视图中的某个按钮被点击的时候,通知它的代理(主控制器)去干刷新数据这件事。
(2)要成为代理是由条件的,有以下几个步骤
    1).双方约定一个协议(代理协议,注意命名规范),在视图中自定义一个协议,协议中提供一个方法。

      @protocol YYHeaderViewDelegate <NSObject>

      -(void)headerViewDidClickHeaderView:(YYHeaderView *)headerView;

      @end

    2).在视图中添加一个id类型的属性变量,任何人只要遵守了约定协议的都可以成为它的代理。

      //delegate遵守YYHeaderViewDelegate这个协议,可以使用协议中的方法

      @property(nonatomic,weak)id<YYHeaderViewDelegate> delegate;

    3).在控制器中,遵守自定义的代理协议,就可以使用代理提供的方法,在这个方法中对数据进行刷新。

      @interface YYViewController ()<YYHeaderViewDelegate>

      -(void)headerViewDidClickHeaderView:(YYHeaderView *)headerView

        {

              [self.tableView reloadData];

        }

    4).把控制器设置作为按钮点击事件的代理。

        headerview.delegate=self;

iOS开发UI篇—使用UItableview完成一个简单的QQ好友列表(二)