zoukankan      html  css  js  c++  java
  • iOS开发UI篇—以微博界面为例使用纯代码自定义cell程序编码全过程(二)

    iOS开发UI篇—以微博界面为例使用纯代码自定义cell程序编码全过程(二)

    一、需要改进的地方

    还需改进的地方:cell的高度需要根据每条微博的数据进行动态设置。
    设置cell的高度可以有两种方式,一种是通过rowheight属性来进行设置,一种是通过代理来进行设置。通过属性设置适用于每行的高度一致,使用代理适用于每行的高度不一致的情况。
    二、实现思路
    在这个应用中,每个cell的高度是根据内容来确定的,所以在这里我们通过代理来设置cell的高度。
    获取到图片最大的Y值或者是文字最大的Y值,在cell中设置一个新的变量。
    判断一下,如果有配图,则高度等于配图的高度+间隙的高度,如果没有配图那么高度等于文字的高度+间隙的高度。
    在自定义cell的setting frame方法中计算出行高,而要在主控制器中进行使用,怎么办才能拿到数据?
     
    计算行高的方法最终是由cellforrow(setweibo->settingframe->计算行高)调用的,如果要拿到行高的话,需要先调用cellforrow这个方法。
    查看cellforrow和heughtforrow这两个方法是谁先调用,结果显示是heiforrow先调用。
    拿不到计算的行高?怎么办?
     
    让它在计算heightforrow之前就计算出行高。计算行高,依赖于其他控件中的位置,位置依赖于模型中的数据。
    拿到模型数据,就可以计算出高度。
    那么在哪里可以拿到数据模型呢?
     
    在懒加载中创建模型,就可以拿到模型,计算所有控件的frame,在懒加载中就可以获得行高。
    拿到模型后可以计算出5个frame,那么就使用一个模型,把着5个frame保存起来,将来一个自定义的cell就对应一个frame模型。
    新建一个类,继承自nsobject,这个类专门用来保存每一行数据的frame。在类中创建5个对应的frame属性,(CGRECT)以及一个行高。添加一个模型数据,当别人给我一个模型数据的时候,我就可以通过重写set方法,设置模型数据的frame.
    把之前的frame计算方法拷贝过去。(为什么?)
    在懒加载方法中,根据模型数据创建frame模型,往数组里面添加的时候添加frame模型,此时该数组中既有所有的数据模型,又拥有对应的frame。
    在代理方法中,获取到当前索引对应的frame。
    三、实现代码
    1.项目文件结构
    2.代码
    模型部分
    TXStatus.h文件
     1 //  Created by 鑫 on 14-10-12.
     2 //  Copyright (c) 2014年 梁镋鑫. All rights reserved.
     3 //
     4 
     5 #import <Foundation/Foundation.h>
     6 
     7 @interface TXStatus : NSObject
     8 @property (nonatomic, copy) NSString *text; // 内容
     9 @property (nonatomic, copy) NSString *icon; // 头像
    10 @property (nonatomic, copy) NSString *name; // 昵称
    11 @property (nonatomic, copy) NSString *picture; // 配图
    12 @property (nonatomic, assign) BOOL vip;
    13 
    14 - (instancetype)initWithDict:(NSDictionary *)dict;
    15 + (instancetype)statusWithDict:(NSDictionary *)dict;
    16 
    17 @end
    TXStatus.m文件
     1 #import "TXStatus.h"
     2 #import "TXStatus.h"
     3 @implementation TXStatus
     4 - (instancetype)initWithDict:(NSDictionary *)dict
     5 {
     6     if (self = [super init]) {
     7         [self setValuesForKeysWithDictionary:dict];
     8     }
     9     return self;
    10 }
    11 
    12 + (instancetype)statusWithDict:(NSDictionary *)dict
    13 {
    14     return [[self alloc] initWithDict:dict];
    15 }
    16 
    17 @end
    视图部分
    TXStatusCell.h文件
    1 #import <UIKit/UIKit.h>
    2 @class TXStatusFrame;
    3 @interface TXStatusCell : UITableViewCell
    4 @property (nonatomic, strong) TXStatusFrame *statusFrame;
    5 + (instancetype)cellWithTableView:(UITableView *)tableView;
    6 @end
    TXStatusCell.m文件
      1 //
      2 // 昵称的字体
      3 #define TXNameFont [UIFont systemFontOfSize:14]
      4 // 正文的字体
      5 #define TXTextFont [UIFont systemFontOfSize:15]
      6 #import "TXStatusCell.h"
      7 #import "TXStatus.h"
      8 #import "TXStatusFrame.h"
      9 @interface TXStatusCell()
     10 
     11 /**
     12  *  头像
     13  */
     14 @property (nonatomic, weak) UIImageView *iconView;
     15 /**
     16  *  昵称
     17  */
     18 @property (nonatomic, weak) UILabel *nameView;
     19 /**
     20  *  会员图标
     21  */
     22 @property (nonatomic, weak) UIImageView *vipView;
     23 /**
     24  *  正文
     25  */
     26 @property (nonatomic, weak) UILabel *textView;
     27 /**
     28  *  配图
     29  */
     30 @property (nonatomic, weak) UIImageView *pictureView;
     31 
     32 
     33 @end
     34 @implementation TXStatusCell
     35 /**
     36  *  构造方法(在初始化对象的时候会调用)
     37  *  一般在这个方法中添加需要显示的子控件
     38  */
     39 - (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier
     40 {
     41     self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
     42     if (self) {
     43         // 1.头像
     44         UIImageView *iconView = [[UIImageView alloc] init];
     45         [self.contentView addSubview:iconView];
     46         self.iconView = iconView;
     47         
     48         // 2.昵称
     49         UILabel *nameView = [[UILabel alloc] init];
     50         //        nameView.backgroundColor = [UIColor redColor];
     51         nameView.font = TXNameFont;
     52         [self.contentView addSubview:nameView];
     53         self.nameView = nameView;
     54         
     55         // 3.会员图标
     56         UIImageView *vipView = [[UIImageView alloc] init];
     57         vipView.image = [UIImage imageNamed:@"vip"];
     58         [self.contentView addSubview:vipView];
     59         self.vipView = vipView;
     60         
     61         // 4.正文
     62         UILabel *textView = [[UILabel alloc] init];
     63         //        textView.backgroundColor = [UIColor blueColor];
     64         textView.numberOfLines = 0;
     65         textView.font = TXTextFont;
     66         [self.contentView addSubview:textView];
     67         self.textView = textView;
     68         
     69         // 5.配图
     70         UIImageView *pictureView = [[UIImageView alloc] init];
     71         [self.contentView addSubview:pictureView];
     72         self.pictureView = pictureView;
     73     }
     74     return self;
     75 }
     76 /**
     77  *  在这个方法中设置子控件的frame和显示数据
     78  */
     79 - (void)setStatusFrame:(TXStatusFrame *)statusFrame
     80 {
     81     _statusFrame = statusFrame;
     82     
     83     // 1.设置数据
     84     [self settingData];
     85     
     86     // 2.设置frame
     87     [self settingFrame];
     88 }
     89 /**
     90  *  设置数据
     91  */
     92 - (void)settingData
     93 {
     94     // 微博数据
     95     TXStatus *status = self.statusFrame.status;
     96     
     97     // 1.头像
     98     self.iconView.image = [UIImage imageNamed:status.icon];
     99     
    100     // 2.昵称
    101     self.nameView.text = status.name;
    102     
    103     // 3.会员图标
    104     if (status.vip) {
    105         self.vipView.hidden = NO;
    106         
    107         self.nameView.textColor = [UIColor redColor];
    108     } else {
    109         self.vipView.hidden = YES;
    110         
    111         self.nameView.textColor = [UIColor blackColor];
    112     }
    113     
    114     // 4.正文
    115     self.textView.text = status.text;
    116     
    117     // 5.配图
    118     if (status.picture) { // 有配图
    119         self.pictureView.hidden = NO;
    120         self.pictureView.image = [UIImage imageNamed:status.picture];
    121     } else { // 没有配图
    122         self.pictureView.hidden = YES;
    123     }
    124 }
    125 
    126 /**
    127  *  计算文字尺寸
    128  *
    129  *  @param text    需要计算尺寸的文字
    130  *  @param font    文字的字体
    131  *  @param maxSize 文字的最大尺寸
    132  */
    133 - (CGSize)sizeWithText:(NSString *)text font:(UIFont *)font maxSize:(CGSize)maxSize
    134 {
    135     NSDictionary *attrs = @{NSFontAttributeName : font};
    136     return [text boundingRectWithSize:maxSize options:NSStringDrawingUsesLineFragmentOrigin attributes:attrs context:nil].size;
    137 }
    138 
    139 /**
    140  *  设置frame
    141  */
    142 /**
    143  *  设置frame
    144  */
    145 - (void)settingFrame
    146 {
    147     // 1.头像
    148     self.iconView.frame = self.statusFrame.iconF;
    149     
    150     // 2.昵称
    151     self.nameView.frame = self.statusFrame.nameF;
    152     
    153     // 3.会员图标
    154     self.vipView.frame = self.statusFrame.vipF;
    155     
    156     // 4.正文
    157     self.textView.frame = self.statusFrame.textF;
    158     
    159     // 5.配图
    160     if (self.statusFrame.status.picture) {// 有配图
    161         self.pictureView.frame = self.statusFrame.pictureF;
    162     }
    163 }
    164 + (instancetype)cellWithTableView:(UITableView *)tableView
    165 {
    166     
    167     static NSString *ID = @"status";
    168     TXStatusCell *cell = [tableView dequeueReusableCellWithIdentifier:ID];
    169     if (cell == nil) {
    170         cell = [[TXStatusCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:ID];
    171     }
    172     return cell;
    173 
    174 }
    175 
    176 - (void)awakeFromNib
    177 {
    178     // Initialization code
    179 }
    180 
    181 - (void)setSelected:(BOOL)selected animated:(BOOL)animated
    182 {
    183     [super setSelected:selected animated:animated];
    184 
    185     // Configure the view for the selected state
    186 }
    187 
    188 @end
    TXStatusFrame.h文件
     1 //  Created by 鑫 on 14-10-12.
     2 //  Copyright (c) 2014年 梁镋鑫. All rights reserved.
     3 //
     4 
     5 #import <Foundation/Foundation.h>
     6 @class TXStatus;
     7 @interface TXStatusFrame : NSObject
     8 /**
     9  *  头像的frame
    10  */
    11 @property (nonatomic, assign, readonly) CGRect iconF;
    12 /**
    13  *  昵称的frame
    14  */
    15 @property (nonatomic, assign, readonly) CGRect nameF;
    16 /**
    17  *  会员图标的frame
    18  */
    19 @property (nonatomic, assign, readonly) CGRect vipF;
    20 /**
    21  *  正文的frame
    22  */
    23 @property (nonatomic, assign, readonly) CGRect textF;
    24 /**
    25  *  配图的frame
    26  */
    27 @property (nonatomic, assign, readonly) CGRect pictureF;
    28 
    29 /**
    30  *  cell的高度
    31  */
    32 @property (nonatomic, assign, readonly) CGFloat cellHeight;
    33 @property (nonatomic, strong) TXStatus *status;
    34 @end
    TXStatusFrame.m文件
     1 //  Created by 鑫 on 14-10-12.
     2 //  Copyright (c) 2014年 梁镋鑫. All rights reserved.
     3 //
     4 // 昵称的字体
     5 #define TXNameFont [UIFont systemFontOfSize:14]
     6 // 正文的字体
     7 #define TXTextFont [UIFont systemFontOfSize:15]
     8 
     9 #import "TXStatusFrame.h"
    10 #import "TXStatus.h"
    11 @implementation TXStatusFrame
    12 /**
    13  *  计算文字尺寸
    14  *
    15  *  @param text    需要计算尺寸的文字
    16  *  @param font    文字的字体
    17  *  @param maxSize 文字的最大尺寸
    18  */
    19 - (CGSize)sizeWithText:(NSString *)text font:(UIFont *)font maxSize:(CGSize)maxSize
    20 {
    21     NSDictionary *attrs = @{NSFontAttributeName : font};
    22     return [text boundingRectWithSize:maxSize options:NSStringDrawingUsesLineFragmentOrigin attributes:attrs context:nil].size;
    23 }
    24 -(void)setStatus:(TXStatus *)status
    25 { _status = status;
    26     
    27     // 子控件之间的间距
    28     CGFloat padding = 10;
    29     
    30     // 1.头像
    31     CGFloat iconX = padding;
    32     CGFloat iconY = padding;
    33     CGFloat iconW = 30;
    34     CGFloat iconH = 30;
    35     _iconF = CGRectMake(iconX, iconY, iconW, iconH);
    36     
    37     // 2.昵称
    38     // 文字的字体
    39     CGSize nameSize = [self sizeWithText:self.status.name font:TXNameFont maxSize:CGSizeMake(MAXFLOAT, MAXFLOAT)];
    40     CGFloat nameX = CGRectGetMaxX(_iconF) + padding;
    41     CGFloat nameY = iconY + (iconH - nameSize.height) * 0.5;
    42     _nameF = CGRectMake(nameX, nameY, nameSize.width, nameSize.height);
    43     
    44     // 3.会员图标
    45     CGFloat vipX = CGRectGetMaxX(_nameF) + padding;
    46     CGFloat vipY = nameY;
    47     CGFloat vipW = 14;
    48     CGFloat vipH = 14;
    49     _vipF = CGRectMake(vipX, vipY, vipW, vipH);
    50     
    51     // 4.正文
    52     CGFloat textX = iconX;
    53     CGFloat textY = CGRectGetMaxY(_iconF) + padding;
    54     CGSize textSize = [self sizeWithText:self.status.text font:TXTextFont maxSize:CGSizeMake(300, MAXFLOAT)];
    55     _textF = CGRectMake(textX, textY, textSize.width, textSize.height);
    56     
    57     // 5.配图
    58     if (self.status.picture) {// 有配图
    59         CGFloat pictureX = textX;
    60         CGFloat pictureY = CGRectGetMaxY(_textF) + padding;
    61         CGFloat pictureW = 100;
    62         CGFloat pictureH = 100;
    63         _pictureF = CGRectMake(pictureX, pictureY, pictureW, pictureH);
    64         
    65         _cellHeight = CGRectGetMaxY(_pictureF) + padding;
    66     } else {
    67         _cellHeight = CGRectGetMaxY(_textF) + padding;
    68     }
    69 
    70     
    71 }
    72 @end
    控制器部分
    TXViewController.h文件
    1 #import <UIKit/UIKit.h>
    2 
    3 @interface TXViewController : UITableViewController
    4 
    5 @end
    TXViewController.m文件
     1 //  Created by 鑫 on 14-10-12.
     2 //  Copyright (c) 2014年 梁镋鑫. All rights reserved.
     3 //
     4 
     5 #import "TXViewController.h"
     6 #import "TXStatus.h"
     7 #import "TXStatusCell.h"
     8 #import "TXStatusFrame.h"
     9 @interface TXViewController ()
    10 @property (nonatomic, strong) NSArray *statusFrames;
    11 
    12 @end
    13 
    14 @implementation TXViewController
    15 - (void)viewDidLoad
    16 {
    17     [super viewDidLoad];
    18     // Do any additional setup after loading the view, typically from a nib.
    19     //行高
    20     self.tableView.rowHeight = 400;
    21 }
    22 
    23 - (NSArray *)statusFrames
    24 {
    25     if (_statusFrames == nil) {
    26         // 初始化
    27         // 1.获得plist的全路径
    28         NSString *path = [[NSBundle mainBundle] pathForResource:@"statuses.plist" ofType:nil];
    29         
    30         // 2.加载数组
    31         NSArray *dictArray = [NSArray arrayWithContentsOfFile:path];
    32         
    33         // 3.将dictArray里面的所有字典转成模型对象,放到新的数组中
    34         NSMutableArray *statusFrameArray = [NSMutableArray array];
    35         for (NSDictionary *dict in dictArray) {
    36             // 3.1.创建TXStatus模型对象
    37             TXStatus *status = [TXStatus statusWithDict:dict];
    38             
    39             // 3.2.创建TXStatusFrame模型对象
    40             TXStatusFrame *statusFrame = [[TXStatusFrame alloc] init];
    41             statusFrame.status = status;
    42             
    43             // 3.2.添加模型对象到数组中
    44             [statusFrameArray addObject:statusFrame];
    45         }
    46         
    47         // 4.赋值
    48         _statusFrames = statusFrameArray;
    49     }
    50     return _statusFrames;
    51 }
    52 #pragma mark - 实现数据源方法
    53 - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
    54 {
    55     return self.statusFrames.count;
    56 }
    57 
    58 - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
    59 {
    60     // 1.创建cell
    61     TXStatusCell *cell = [TXStatusCell cellWithTableView:tableView];
    62     
    63     // 2.在这个方法算好了cell的高度
    64     cell.statusFrame = self.statusFrames[indexPath.row];
    65     
    66     // 3.返回cell
    67     return cell;
    68 }
    69 #pragma mark - 实现代理方法
    70 - (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
    71 {
    72     
    73     // 取出这行对应的frame模型
    74     TXStatusFrame *statusFrame = self.statusFrames[indexPath.row];
    75     return statusFrame.cellHeight;}
    76 
    77 
    78 - (BOOL)prefersStatusBarHidden
    79 {
    80     return YES;
    81 }
    82 
    83 
    84 
    85 @end

    3.实现效果

           

    四、优化

    在给自定义cell中重写set方法时,设置了微博的数据,还同时设置了frame,那么既然已经在frame模型中计算出了frame,这里就不需要再进行一次多余的计算了。修改代码,在cell里拿到weiboframe模型,就能拿到所有的frame。在自定义的cell里边,不再保存weibo而是保存weiboframe的属性。

    说明:只对项目的三个文件进行了修改。

     示意图:

  • 相关阅读:
    java.util.ConcurrentModificationException故障分析
    Eclipse常见问题总结-持续更新
    MySQL学习—简单存储过程
    Mysql学习——触发器
    MySQL学习—多表查询(内连接,外链接,全连接)
    JDK环境变量配置
    Spring学习总结(二)——容器对Bean的管理
    Spring学习总结(一)——Spring容器的实例化
    类加载机制
    手写数据库连接池
  • 原文地址:https://www.cnblogs.com/asd5551680/p/4069367.html
Copyright © 2011-2022 走看看