• 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 *)dict
    14 {
    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 *)dict
    10 {
    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 : UITableViewCell
    4 + (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 *)friendData
    16 {
    17     _friendData = 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 @optional
    14 - (void)headerViewDidClickedNameView:(TXHeaderView *)headerView;
    15 @end
    16 
    17 @interface TXHeaderView : UITableViewHeaderFooterView
    18 + (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的frameounds没有值
     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)nameViewClick
    113 {
    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)didMoveToSuperview
    127 {
    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 *)newSuperview
    139 //{
    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 : UITableViewController
    11 
    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 @end
    10 
    11 @implementation TXViewController
    12 
    13 - (void)viewDidLoad
    14 {
    15     [super viewDidLoad];
    16     
    17     // 每一行cell的高度
    18     self.tableView.rowHeight = 50;
    19     // 每一组头部控件的高度
    20     self.tableView.sectionHeaderHeight = 44;
    21 }
    22 
    23 - (NSArray *)groups
    24 {
    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)prefersStatusBarHidden
    40 {
    41     return YES;
    42 }
    43 
    44 #pragma mark - 数据源方法
    45 - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
    46 {
    47     return self.groups.count;
    48 }
    49 
    50 - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
    51 {
    52     TXFriendGroup *group = self.groups[section];
    53     
    54     return (group.isOpened ? group.friends.count : 0);
    55 }
    56 
    57 - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
    58 {
    59     // 1.创建cell
    60     TXFriendCell *cell = [TXFriendCell cellWithTableView:tableView];
    61     
    62     // 2.设置cell的数据
    63     TXFriendGroup *group = self.groups[indexPath.section];
    64     cell.friendData = group.friends[indexPath.row];
    65     
    66     return cell;
    67 }
    68 
    69 /**
    70  *  返回每一组需要显示的头部标题(字符出纳)
    71  */
    72 - (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section
    73 {
    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 *)headerView
    89 {
    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;

  • 相关阅读:
    一个别人的心得(转发的)
    常见的游戏设计技术
    查看更新
    xml,json和各种序列化工具的对比
    python游戏环境搭建
    快速制作游戏
    子网和掩码
    nat
    pycharm使用技巧
    IP的面向无连接状态
  • 原文地址:https://www.cnblogs.com/asd5551680/p/4069485.html
Copyright © 2020-2023  润新知