05---MVC模式下动态调整Cell高度三部曲

动态调整Cell高度三部曲

  我们在做项目开发的过程中经常会遇到每一个cell的高度及cell的子控件的显示个数不同,以我最近开发的微格为例,讲解一下MVC模式动态的调整Cell宽高的三部曲

 

    1>.自定义Cell,重写- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier方法 在此方法中添加所有的可能显示的子控件

        子控件的frame通过构建的cellFrame模型进行设置 - (void)setCellFrame:(cellFrame *)cellFrame (顺便设置文字,图片等信息)

#import <UIKit/UIKit.h>
@class StatusCellFrame;

@interface StatusCell : UITableViewCell
{
        UIImageView *_icon; // 头像
        UILabel *_screenName; // 昵称
        UILabel *_time; // 时间
        UILabel *_source; // 来源
        UILabel *_text; // 内容
        UIImageView *_image; // 配图
        
        UIImageView *_retweeted; // 被转发微博的父控件
        UILabel *_retweetedScreenName; // 被转发微博作者的昵称
        UILabel *_retweetedText; // 被转发微博的内容
        UIImageView *_retweetedImage; // 被转发微博的配图
}
// 每一个微博Cell都含有statusCellFrame这个模型对象的属性
@property (nonatomic, strong) StatusCellFrame *statusCellFrame;
@end


//  MVC设计模式 : 一般都是设计一个模型Model 在视图View中拥有这个Model的实例 
StatusCell.h
//
//  StatusCell.m
//  新浪微博控
//
//  Created by WHB on 14-7-22.
//  Copyright (c) 2014年 whblap. All rights reserved.
//

#import "StatusCell.h"
#import "StatusCellFrame.h"
#import "Status.h"
#import "UIImageView+WebCache.h"  
#import "User.h"

@implementation StatusCell

- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier
{
    self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
    if (self) {
        // 1.添加微博本身的子控件
        [self addAllSubviews];
        
        // 2.添加被转发微博的子控件
        [self addReweetedAllSubviews];
    }
    return self;
}

#pragma mark 添加微博本身的子控件
- (void)addAllSubviews
{
    // 1.头像
    _icon = [[UIImageView alloc] init];
    [self.contentView addSubview:_icon];
    
    // 2.昵称
    _screenName = [[UILabel alloc] init];
    _screenName.font = kScreenNameFont;
    [self.contentView addSubview:_screenName];
    
    // 3.时间
    _time = [[UILabel alloc] init];
    _time.font = kTimeFont;
    [self.contentView addSubview:_time];
    
    // 4.来源
    _source = [[UILabel alloc] init];
    _source.font = kSourceFont;
    [self.contentView addSubview:_source];
    
    // 5.内容
    _text = [[UILabel alloc] init];
    _text.numberOfLines = 0;
    _text.font = kTextFont;
    [self.contentView addSubview:_text];
    
    // 6.配图
    _image = [[UIImageView alloc] init];
    [self.contentView addSubview:_image];
}

#pragma mark 被转发微博的子控件
- (void)addReweetedAllSubviews
{
    // 1.被转发微博的父控件
    _retweeted = [[UIImageView alloc] init];
    [self.contentView addSubview:_retweeted];
    
    // 2.被转发微博的昵称
    _retweetedScreenName = [[UILabel alloc] init];
    _retweetedScreenName.font = kRetweetedScreenNameFont;
    [_retweeted addSubview:_retweetedScreenName];
    
    // 3.被转发微博的内容
    _retweetedText = [[UILabel alloc] init];
    _retweetedText.numberOfLines = 0;
    _retweetedText.font = kRetweetedTextFont;
    [_retweeted addSubview:_retweetedText];
    
    // 4.被转发微博的配图
    _retweetedImage = [[UIImageView alloc] init];
    [_retweeted addSubview:_retweetedImage];
}

- (void)setStatusCellFrame:(StatusCellFrame *)statusCellFrame
{
    _statusCellFrame = statusCellFrame;
    
    Status *s = statusCellFrame.status;
    
    // 1.头像
    _icon.frame = statusCellFrame.iconFrame;
    [_icon setImageWithURL:[NSURL URLWithString:s.user.profileImageUrl] placeholderImage:[UIImage imageNamed:@"Icon.png"] options:SDWebImageRetryFailed | SDWebImageLowPriority];
    
    // 2.昵称
    _screenName.frame = statusCellFrame.screenNameFrame;
    _screenName.text = s.user.screenName;
    
    // 3.时间
    _time.frame = statusCellFrame.timeFrame;
    _time.text = s.createdAt;
    
    // 4.来源
    _source.frame = statusCellFrame.sourceFrame;
    _source.text = s.source;
    
    // 5.内容
    _text.frame = statusCellFrame.textFrame;
    _text.text = s.text;
    
    // 6.配图
    if (s.picUrls.count) {
        _image.hidden = NO;
        _image.frame = statusCellFrame.imageFrame;
        //        MyLog(@"pic---%@", s.picUrls);
        NSString *imageStr = s.picUrls[0][@"thumbnail_pic"];
        NSURL *imageURL = [NSURL URLWithString:imageStr];
        [_image setImageWithURL:imageURL placeholderImage:[UIImage imageNamed:@"Icon.png"] options:SDWebImageLowPriority | SDWebImageRetryFailed];
        //#warning 配图的图片
    } else {
        _image.hidden = YES;
    }
    
    // 7.被转发微博
    if (s.retweetedStatus) {
        _retweeted.hidden = NO;
        
        _retweeted.frame = statusCellFrame.retweetedFrame;
        
        // 8.昵称
        _retweetedScreenName.frame = statusCellFrame.retweetedScreenNameFrame;
        _retweetedScreenName.text = s.retweetedStatus.user.screenName;
        
        // 9.内容
        _retweetedText.frame = statusCellFrame.retweetedTextFrame;
        _retweetedText.text = s.retweetedStatus.text;
        
        // 10.配图
        if (s.retweetedStatus.picUrls.count) {
            _retweetedImage.hidden = NO;
            
            _retweetedImage.frame = statusCellFrame.retweetedImageFrame;
            
            [_retweetedImage setImageWithURL:[NSURL URLWithString:s.retweetedStatus.picUrls[0][@"thumbnail_pic"]] placeholderImage:[UIImage imageNamed:@"Icon.png"] options:SDWebImageRetryFailed | SDWebImageLowPriority];
            
        } else {
            _retweetedImage.hidden = YES;
        }
    } else {
        _retweeted.hidden = YES;
    }
    
}
@end
StatusCell.m

    2>.新建一个模型,作用是对cell里面的每一个控件设置frame 条件:

            1>>.需要提供好一系列的CGRect类型的数据进行访问

            2>>.提供一个接口来计算cell里面所有子控件的frame和cell的高度 如:- (void)setStatus:(Status *)status

//
//  StatusCellFrame.h
//  微格
//
//  Created by WHB on 14-7-22.
//  Copyright (c) 2014年 whblap. All rights reserved.
//

#define kCellBorderWidth 10
#define kScreenNameFont [UIFont systemFontOfSize:17]
#define kTimeFont [UIFont systemFontOfSize:13]
#define kSourceFont kTimeFont
#define kTextFont [UIFont systemFontOfSize:15]

#define kRetweetedTextFont [UIFont systemFontOfSize:16]
#define kRetweetedScreenNameFont [UIFont systemFontOfSize:16]

#import <Foundation/Foundation.h>
@class Status;

@interface StatusCellFrame : NSObject

//  一个StatusCellFrame对象 能 描述 一个StatusCell内部所有子控件的frame
@property (nonatomic, strong) Status *status;  // 根据status的内容来设置 各个属性的宽高  即提供的接口用来计算cell里面的所有控件的frame 和 cell

@property (nonatomic, readonly) CGFloat cellHeight; // Cell的高度

@property (nonatomic, readonly) CGRect iconFrame; // 头像的frame

@property (nonatomic, readonly) CGRect screenNameFrame; // 昵称
@property (nonatomic, readonly) CGRect timeFrame; // 时间
@property (nonatomic, readonly) CGRect sourceFrame; // 来源
@property (nonatomic, readonly) CGRect textFrame; // 内容
@property (nonatomic, readonly) CGRect imageFrame; // 配图

@property (nonatomic, readonly) CGRect retweetedFrame; // 被转发微博的父控件
@property (nonatomic, readonly) CGRect retweetedScreenNameFrame; // 被转发微博作者的昵称
@property (nonatomic, readonly) CGRect retweetedTextFrame; // 被转发微博的内容
@property (nonatomic, readonly) CGRect retweetedImageFrame; // 被转发微博的配图
@end
StatusCellFrame.h
//
//  StatusCellFrame.m
//  微格
//
//  Created by WHB on 14-7-22.
//  Copyright (c) 2014年 whblap. All rights reserved.
//

#import "StatusCellFrame.h"
#import "Status.h"
#import "User.h"

@implementation StatusCellFrame
- (void)setStatus:(Status *)status
{
    _status = status;
    // 利用微博数据,计算所有子控件的frame
    
    // 整个cell的宽度
    CGFloat cellWidth = [UIScreen mainScreen].bounds.size.width;
    
    // 1.头像
    CGFloat iconX = kCellBorderWidth;
    CGFloat iconY = kCellBorderWidth;
    _iconFrame = CGRectMake(iconX, iconY, 50, 50);
    
    // 2.昵称
    CGFloat screenNameX = CGRectGetMaxX(_iconFrame) + kCellBorderWidth;
    CGFloat screenNameY = iconY;
    CGSize screenNameSize = [status.user.screenName sizeWithFont:kScreenNameFont];
    _screenNameFrame = (CGRect){{screenNameX, screenNameY}, screenNameSize};
    
    // 3.时间
    CGFloat timeX = screenNameX;
    CGFloat timeY = CGRectGetMaxY(_screenNameFrame) + kCellBorderWidth;
    CGSize timeSize = [status.createdAt sizeWithFont:kTimeFont];
    _timeFrame = (CGRect){{timeX, timeY}, timeSize};
    
    // 4.来源
    CGFloat sourceX = CGRectGetMaxX(_timeFrame) + kCellBorderWidth;
    CGFloat sourceY = timeY;
    CGSize sourceSize = [status.source sizeWithFont:kSourceFont];
    _sourceFrame = (CGRect) {{sourceX, sourceY}, sourceSize};
    
    // 5.内容
    CGFloat textX = iconX;
    CGFloat textY = CGRectGetMaxY(_sourceFrame) + kCellBorderWidth;
    CGSize textSize = [status.text sizeWithFont:kTextFont constrainedToSize:CGSizeMake(cellWidth - 2 * kCellBorderWidth, MAXFLOAT)];
    _textFrame = (CGRect){{textX, textY}, textSize};
    
    if (status.picUrls.count) { // 6.有配图
        CGFloat imageX = textX;
        CGFloat imageY = CGRectGetMaxY(_textFrame) + kCellBorderWidth;
        _imageFrame = CGRectMake(imageX, imageY, 100, 100);
    } else if (status.retweetedStatus) { // 7.有转发的微博
        // 被转发微博整体
        CGFloat retweetX = textX;
        CGFloat retweetY = CGRectGetMaxY(_textFrame) + kCellBorderWidth;
        CGFloat retweetWidth = cellWidth - 2 * kCellBorderWidth;
        CGFloat retweetHeight = kCellBorderWidth;
        
        // 8.被转发微博的昵称
        CGFloat retweetedScreenNameX = kCellBorderWidth;
        CGFloat retweetedScreenNameY = kCellBorderWidth;
        CGSize retweetedScreenNameSize = [status.retweetedStatus.user.screenName sizeWithFont:kRetweetedScreenNameFont];
        _retweetedScreenNameFrame = (CGRect){{retweetedScreenNameX, retweetedScreenNameY}, retweetedScreenNameSize};
        
        // 9.被转发微博的内容
        CGFloat retweetedTextX = retweetedScreenNameX;
        CGFloat retweetedTextY = CGRectGetMaxY(_retweetedScreenNameFrame) + kCellBorderWidth;
        CGSize retweetedTextSize = [status.retweetedStatus.text sizeWithFont:kRetweetedTextFont constrainedToSize:CGSizeMake(retweetWidth - 2 * kCellBorderWidth, MAXFLOAT)];
        _retweetedTextFrame = (CGRect){{retweetedTextX, retweetedTextY}, retweetedTextSize};
        
        // 10.被转发微博的配图
        if (status.retweetedStatus.picUrls.count) {
            CGFloat retweetedImageX = retweetedTextX;
            CGFloat retweetedImageY = CGRectGetMaxY(_retweetedTextFrame) + kCellBorderWidth;
            _retweetedImageFrame = CGRectMake(retweetedImageX, retweetedImageY, 100, 100);  
            retweetHeight += CGRectGetMaxY(_retweetedImageFrame);
        } else {
            retweetHeight += CGRectGetMaxY(_retweetedTextFrame);
        }   
        _retweetedFrame = CGRectMake(retweetX, retweetY, retweetWidth, retweetHeight);
    }
    
    // 11.整个cell的高度
    _cellHeight = kCellBorderWidth;
    if (status.picUrls.count) {
        _cellHeight += CGRectGetMaxY(_imageFrame);
    } else if (status.retweetedStatus) {
        _cellHeight += CGRectGetMaxY(_retweetedFrame);
    } else {
        _cellHeight += CGRectGetMaxY(_textFrame);
    }
}
@end
StatusCellFrame.m

    3>.返回控制器,

    在- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath方法中

              1>>.创建一个自定义的Cell

              2>>.实例化一个cellFrame

              3>>.给Cell传递对应的cellframe;

    在- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath方法中利用cellFrame

    返回每一行cell的高度。

//
//  HomeViewController.m
//  新浪微博控
//
//  Created by whblap on 14-6-25.
//  Copyright (c) 2014年 whblap. All rights reserved.
//

#import "HomeViewController.h"
#import "UIBarButtonItem+WHBALP.h"
#import "HttpTool.h"
#import "Status.h"
#import "User.h"
#import "StatusManage.h"
#import "StatusCell.h"
#import "StatusCellFrame.h"

@interface HomeViewController ()
{
    NSMutableArray *_statuses; // 所有的微博数据
}
@end

@implementation HomeViewController

- (void)viewDidLoad
{
    [super viewDidLoad];
    
    [self buildNavigationBar];
    [self loadStatusData];
}

#pragma mark - build导航栏
- (void)buildNavigationBar
{
    self.title = @"首页";
    self.view.backgroundColor = [UIColor cyanColor];
    
    // 添加给导航栏左图片按钮
    self.navigationItem.leftBarButtonItem = [UIBarButtonItem barButtonItemWithImage:@"navigationbar_compose.png" highlightedImage:@"navigationbar_compose_highlighted.png" addTarget:self action:@selector(sendStatus)];
    
    // 给导航栏添加右图片按钮
    self.navigationItem.rightBarButtonItem = [UIBarButtonItem barButtonItemWithImage:@"navigationbar_pop.png" highlightedImage:@"navigationbar_pop_highlighted.png" addTarget:self action:@selector(popMenu)];
}
#pragma mark - 加载微博数据
- (void)loadStatusData
{
    _statuses = [NSMutableArray array];
//    [HttpTool getWithPath:@"2/statuses/home_timeline.json" params:nil success:^(id JSON) {
//        NSArray *statuses = JSON[@"statuses"]; // JSON返回的数据默认是20条 为数组类型的对象
//        // 将字典模型转化为模型对象(将模型对象添加到statuses微博数组中)
//        for (NSDictionary *dict  in statuses) {
//            //  
//            Status *status = [[Status alloc] initWithDict:dict];
//             [_statuses addObject:status];
//        }
//        NSLog(@"_____________%d",_statuses.count);
//         [self.tableView reloadData];
//    } failure:^(NSError *error) {
//        NSLog(@"%@",error);
//    }];
    // 微博管理 加载
    [StatusManage getStatusesWithSuccess:^(NSArray *statues) {
        [_statuses addObjectsFromArray:statues];
        [self.tableView reloadData];
    } failure:^(NSError *error) {
        NSLog(@"%@",error);
    }];
}

#pragma mark - 发送微博方法
- (void)sendStatus
{
    MyLog(@"调用了发送微博方法");
    
}

#pragma mark - 弹出菜单
- (void)popMenu
{
    MyLog(@"调用了弹出菜单方法");
}


- (void)didReceiveMemoryWarning
{
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}

#pragma mark - Table view data source
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
    // Return the number of rows in the section.
    NSLog(@"++++++++++++++++%d",_statuses.count);
    return _statuses.count;
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    static NSString *CellIdentifier = @"Cell";
    StatusCell *cell = [tableView dequeueReusableCellWithIdentifier:nil];
    
    if (cell == nil) {
        // 创建一个自定义的cell
        cell = [[StatusCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier];
    }
    // 实例化一个微博frame对象
    StatusCellFrame *sCellFrame = [[StatusCellFrame alloc] init];
    // 将访问服务器得到的微博数据赋值给微博frame对象的status模型 需要根据这个设置frame
    sCellFrame.status = _statuses[indexPath.row];
    [cell setStatusCellFrame:sCellFrame];

    return cell;
}

#pragma mark 返回每一行cell的高度
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
    StatusCellFrame *f = [[StatusCellFrame alloc] init];
    f.status = _statuses[indexPath.row];
    return f.cellHeight;
}
@end
ViewController.m

05---MVC模式下动态调整Cell高度三部曲,古老的榕树,5-wow.com

郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。