猫猫学IOS(十七)UI之纯代码自定义Cell实现新浪微博UI

猫猫分享,必须精品

素材代码地址:http://blog.csdn.net/u013357243/article/details/44976175

原文地址:http://blog.csdn.net/u013357243?viewmode=contents

先看效果图


编程思路

代码创建Cell的步骤

1> 创建自定义Cell,继承自UITableViewCell

2> 根据需求,确定控件,并定义属性

3> 用getter方法完成控件的实例化,只创建并添加到contentView,不处理位置

4> 定义一个模型属性,通过setter方法,设置cell的显示

昵称正文字符串的位置算法

设置大小由文字的长度决定
用字符串方法:[@"" boundingRectWithSize:(CGSize) options:(NSStringDrawingOptions) attributes:(NSDictionary *) context:(NSStringDrawingContext *)]

//boundingRectWithSize计算给定文字字符串所占的区域,返回是一个x,y为0的CGRect
//    如果要计算多行的准确高度需要传入
//        options:NSStringDrawingUsesLineFragmentOrigin

//attribbutes:dict 用于指定字体的相关属性的字典。UIKit框架的第一个头文件ps 这个头文件不记很难找
//    context :nil
#define kNameFont [UIFont systemFontOfSize:14]

    NSDictionary *nameDict = @{NSFontAttributeName:kNameFont};
    CGRect nameFrame = [self.status.name boundingRectWithSize:CGSizeMake(MAXFLOAT, MAXFLOAT) options:NSStringDrawingUsesLineFragmentOrigin attributes:nameDict context:nil];

计算行高的方法

要用到代理方法的:

-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath

计算行高的方法,会在加载表格数据时,有多少行计算多少次 contentSize

 问题:此方法执行的时候,cell还没有被实例化!
 但是:行高计算是在实例化cell时,通过设置status属性,计算=》有了status模型,就可以知道行高  !

 问题:如何在cell实例化之前,获得行高?
 解决方法:通过status可以计算得到行高! = 》再建立一个模型,专门计算所有控件的位置

警告:原形单元格必须又一个可重用标示符的解决

警告:file:///Users/apple/Desktop/%E5%AD%A6%E4%B9%A0/%E4%BA%8C%E6%9C%9F%E5%AD%A6%E4%B9%A0/Day07/%E6%96%B0%E6%B5%AA%E5%BE%AE%E5%8D%9AUI/%E6%96%B0%E6%B5%AA%E5%BE%AE%E5%8D%9AUI/Base.lproj/Main.storyboard: warning: Unsupported Configuration: Prototype table cells must have reuse identifiers

警告:原形单元格必须又一个可重用标示符

解决办法是在Cell中的Identfier加入可重用标示符

然后一定要关联cell的class

——这两部可以用一行代码来代替

//为tableView注册可重用单元格
    [self.tableView registerClass:[NYStatusCell class] forCellReuseIdentifier:ID];

这时候我们注释

//    if (cell == nil) {
//        cell = [[NYStatusCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:ID];
//    }

也可以运行了

    在Storyboard中指定了可重用标示符,同时指定了Cell的类是NYStatusCell,系统会为tableView注册一个原形cell,专门用来做可重用单元格,一旦缓冲区不存在可重用单元格,系统会使用原形Cell新实例化一个Cell供程序使用!
因此如果在Storyb中,注册了原形Cell,就不需要做 cell == nil 的判断了

注意:这些在iOS6之后才有的。

代码学习

类结构

这个小项目主要由这些类组成

MVC各自负责各自的东西

Model有两个模型,一个是Status主要负责所有数据

Status中有

@property (nonatomic, copy)NSString *text;
@property (nonatomic, copy)NSString *icon;
@property (nonatomic, copy)NSString *name;
@property (nonatomic, assign)BOOL vip;
@property (nonatomic, copy) NSString *picture;

这些属性主要包括头像,昵称,vip图标,正文,图片

StatusFrame模型主要负责存放每一个组件在cell所要存放的位置

//提高安全性能:+readonly
@property (nonatomic, assign, readonly)CGRect textF;
@property (nonatomic, assign, readonly)CGRect iconF;
@property (nonatomic, assign, readonly)CGRect nameF;
@property (nonatomic, assign, readonly)CGRect vipF;
@property (nonatomic, assign, readonly)CGRect pictureF;

/**行高*/
@property (nonatomic, assign)CGFloat cellHeight;

/**所有控件的尺寸都可以通过Status来计算得出*/
@property (nonatomic, strong)NYStatus *status;

NYViewController中的代码

//ps:新建iOS交流学习群:304570962
可以加猫猫QQ:1764541256 或则微信znycat
让我们一起努力学习吧。
原文:http://blog.csdn.net/u013357243?viewmode=contents
//  NYViewController.m
//  新浪微博UI
//
//  Created by apple on 15-4-8.
//  Copyright (c) 2015年 znycat. All rights reserved.
//

#import "NYViewController.h"
#import "NYStatus.h"
#import "NYStatusCell.h"
#import "NYStatusFrame.h"

@interface NYViewController ()

@property (nonatomic, strong) NSArray *statusFrames;

@end

@implementation NYViewController
static NSString *ID = @"Cell";

/**懒加载数据*/
-(NSArray *)statusFrames
{
    if (_statusFrames == nil) {
        _statusFrames = [NYStatusFrame statusFrames];
    }
    return _statusFrames;
}

-(void)viewDidLoad
{
    [super viewDidLoad];
    self.tableView.contentInset = UIEdgeInsetsMake(20, 0, 0, 0);
    //为tableView注册可重用单元格
    [self.tableView registerClass:[NYStatusCell class] forCellReuseIdentifier:ID];
}

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

#pragma mark - 数据源方法

-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
    return self.statusFrames.count;
}

-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{

        /**
     在Storyboard中指定了可重用标示符,同时指定了Cell的类是HMStatusCell

     系统会为tableView注册一个原形Cell,专门用来做可重用单元格的,一旦缓冲区中不存在
     可重用单元格,系统会使用原形Cell新实例化一个Cell用程序使用!

     因此如果在,Storyboard中,注册了原形Cell,就不再需要 cell == nil的判断了
     */
//    NYStatusCell *cell = [tableView dequeueReusableCellWithIdentifier:ID];

    // unable to dequeue a cell with identifier Cell - must register a nib or a class for the identifier or connect a prototype cell in a storyboard
    // 使用这个方法,要求一定注册可重用单元格,否则就会崩溃!
    // 官方建议使用以下方法,利用程序的崩溃,及时发现问题
    NYStatusCell *cell = [tableView dequeueReusableCellWithIdentifier:ID forIndexPath:indexPath];

//    if (cell == nil) {
//        cell = [[NYStatusCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:ID];
//    }

    NYStatusFrame *statusFrame = self.statusFrames[indexPath.row];
    cell.statusFrame = statusFrame;
    return cell;
}

#pragma mark - 代理方法
/**计算单元格行高*/
-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
    /**
     计算行高的方法,会在加载表格数据时,有多少行计算多少次 contentSize

     问题:此方法执行的时候,cell还没有被实例化!
     但是:行高计算是在实例化cell时,通过设置status属性,计算=》有了status模型,就可以知道行高  !

     问题:如何在cell实例化之前,获得行高?
     解决方法:通过status可以计算得到行高! = 》再建立一个模型,专门计算所有控件的位置
     */
    NYStatusFrame *statusFrame = self.statusFrames[indexPath.row];
    return statusFrame.cellHeight;
}

@end

自定义cell纯代码写NYStatusCell

//
//  NYStatusCell.m
//  新浪微博UI
//
//  Created by apple on 15-4-9.
//  Copyright (c) 2015年 znycat. All rights reserved.
//

#import "NYStatusCell.h"
#import "NYStatus.h"
#import "NYStatusFrame.h"

/**姓名字体*/
#define kNameFont [UIFont systemFontOfSize:14]
/**正文字体*/
#define kTextFont [UIFont systemFontOfSize:16]
@interface NYStatusCell()
//1>创建自定iyiCell,继承自UITableViewCell
//2>根据需求,确定控件,并定义属性。
@property (nonatomic, strong) UIImageView *iconView;
@property (nonatomic, strong) UILabel *nameView;
@property (nonatomic, strong) UIImageView *vipView;
@property (nonatomic, strong) UILabel *textView;
@property (nonatomic, strong) UIImageView *pictureView;

@end

@implementation NYStatusCell

//3>用get方法完成控件的实例化,只创建并添加到contentView,不处理位置。
-(UIImageView *)iconView
{
    if (_iconView == nil) {
        _iconView = [[UIImageView alloc] init];
        [self.contentView addSubview:_iconView];
    }
    return _iconView;
}

-(UILabel *)nameView
{
    if (_nameView == nil) {
        _nameView = [[UILabel alloc] init];
        //默认字体是17号,改成kNameFont
        _nameView.font = kNameFont;
        [self.contentView addSubview:_nameView];
    }
    return _nameView;
}

-(UIImageView *)vipView
{
    if (_vipView == nil) {
        _vipView = [[UIImageView alloc] init];
        [self.contentView addSubview:_vipView];
    }
    return _vipView;
}

-(UILabel *)textView
{
    if (_textView == nil) {
        _textView = [[UILabel alloc] init];

        _textView.font = kTextFont;
        _textView.numberOfLines = 0;//让他可以换行
        [self.contentView addSubview:_textView];
    }
    return _textView;
}

-(UIImageView *)pictureView
{
    if (_pictureView == nil) {
        _pictureView = [[UIImageView alloc] init];
        [self.contentView addSubview:_pictureView];
    }
    return _pictureView;
}

-(void)setStatusFrame:(NYStatusFrame *)statusFrame
{
    _statusFrame = statusFrame;
    //1>设置数据
    [self settingData];

    //2>设置位置
    [self settingFrame];

}

/**设置数据*/
-(void)settingData
{
    NYStatus *status = self.statusFrame.status;
    //头像
    self.iconView.image = [UIImage imageNamed:status.icon];
    //姓名
    self.nameView.text = status.name;
    //vip
    if (status.vip) {
        self.vipView.image = [UIImage imageNamed:@"vip"];
    }
    //内容正文
    self.textView.text = status.text;
    //图片可选参数:
    if (status.picture.length > 0) {
        self.pictureView.hidden = YES;
        self.pictureView.image = [UIImage imageNamed:status.picture];
    }
    self.pictureView.hidden = NO;
}

/**设置位置*/
-(void)settingFrame
{

    //1.头像
    self.iconView.frame = self.statusFrame.iconF;

    //2,姓名大小由文字的长度决定
//boundingRectWithSize计算给定文字字符串所占的区域,返回是一个x,y为0的CGRect;w,h是计算好的宽高
//    如果要计算多行的准确高度需要传入
//        options:NSStringDrawingUsesLineFragmentOrigin

//attribbutes:dict 用于指定字体的相关属性的字典。UIKit框架的第一个头文件ps 这个头文件不记很难找
//    context :nil

    self.nameView.frame = self.statusFrame.nameF;

    //3,vip图片
    self.vipView.frame = self.statusFrame.vipF;

    //4,正文
    self.textView.frame = self.statusFrame.textF;

    //5,图片
    self.pictureView.frame = self.statusFrame.pictureF;

}

@end

模型实现方法

NYStatus

//
//  NYStatus.m
//  新浪微博UI
//
//  Created by apple on 15-4-8.
//  Copyright (c) 2015年 znycat. All rights reserved.
//

#import "NYStatus.h"

@implementation NYStatus

-(instancetype)initWithDict:(NSDictionary *)dict
{
    self = [super init];
    if (self) {
        [self setValuesForKeysWithDictionary:dict];
    }
    return self;
}

+(instancetype)statusWithDict:(NSDictionary *)dict
{
    return [[self alloc] initWithDict:dict];

}

+(NSArray *)statuses
{
    NSArray *array = [NSArray arrayWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"statuses.plist" ofType:nil]];
    NSMutableArray *arrayM = [NSMutableArray array];
    for (NSDictionary *dict in array) {
        [arrayM addObject:[self statusWithDict:dict]];
    }
    return arrayM;
}
@end


NYStatusFrame

//
//  NYStatusFrame.m
//  新浪微博UI
//
//  Created by apple on 15-4-9.
//  Copyright (c) 2015年 znycat. All rights reserved.
//

#import "NYStatusFrame.h"
#import "NYStatus.h"
#import "NSString+Tools.h"

#define kNameFont [UIFont systemFontOfSize:14]
/**正文字体*/
#define kTextFont [UIFont systemFontOfSize:16]

@implementation NYStatusFrame

/**
 为了程序的安全(面向对象的思想,你给我你就相信我,让我来改,别人别随便动)
 为了让程序更安全,我们将类NYStatusFrame的有关位置的:(例如iconF)设置成readonly只读属性,这时候我们用self.iconF(_iconF的set方法)的时候就不能用了。
 此时要注意:
 一旦重写了readonly属性的getter方法,
        -(CGRect)iconF
        {
        }
        带_的成员变量就不存在了
        这时候如果还需要使用_成员变量,则必须用合成指令@synthesize
                @synthesize iconF = _iconF;
 */

-(void)setStatus:(NYStatus *)status
{
    _status = status;
    //0.定义间距
    CGFloat padding = 10;

    //1.头像
    CGFloat iconX = padding;
    CGFloat iconY = padding;
    CGFloat iconW = 30;
    CGFloat iconH = 30;
    _iconF = CGRectMake(iconX, iconY, iconW, iconH);

    //2,姓名大小由文字的长度决定
    //boundingRectWithSize计算给定文字字符串所占的区域,返回是一个x,y为0的CGRect;w,h是计算好的宽高
    //    如果要计算多行的准确高度需要传入
    //        options:NSStringDrawingUsesLineFragmentOrigin

    //attribbutes:dict 用于指定字体的相关属性的字典。UIKit框架的第一个头文件ps 这个头文件不记很难找
    //    context :nil

    NSDictionary *nameDict = @{NSFontAttributeName:kNameFont};
//    CGRect nameFrame = [self.status.name boundingRectWithSize:CGSizeMake(MAXFLOAT, MAXFLOAT) options:NSStringDrawingUsesLineFragmentOrigin attributes:nameDict context:nil];
    CGRect nameFrame = [self.status.name textRectWithSize:CGSizeMake(MAXFLOAT, MAXFLOAT) attributes:nameDict];

    nameFrame.origin.x = CGRectGetMaxX(self.iconF) +padding;
    nameFrame.origin.y = padding + (self.iconF.size.height - nameFrame.size.height)*0.5;
    _nameF = nameFrame;

    //3,vip图片
    CGFloat vipX = CGRectGetMaxX(self.nameF) + padding;
    CGFloat vipY = self.nameF.origin.y;
    CGFloat vipW = 14;
    CGFloat vipH = 14;
    _vipF = CGRectMake(vipX, vipY, vipW, vipH);

    //4,正文
    NSDictionary *textDict = @{NSFontAttributeName:kTextFont};
//    CGRect textFrame = [self.status.text boundingRectWithSize:CGSizeMake(300, MAXFLOAT) options:NSStringDrawingUsesLineFragmentOrigin attributes:textDict context:nil];
    CGRect textFrame = [self.status.text textRectWithSize:CGSizeMake(300, MAXFLOAT) attributes:textDict];

    textFrame.origin.x = padding;
    textFrame.origin.y = CGRectGetMaxY(self.iconF) + padding;
    _textF = textFrame;

    //5,配图
    if (self.status.picture.length>0) {
        CGFloat pictureX = padding;
        CGFloat pictureY = CGRectGetMaxY(self.iconF) + padding +self.textF.size.height +padding;
        CGFloat pictureW = 100;
        CGFloat pictureH = 100;
        _pictureF= CGRectMake(pictureX, pictureY, pictureW, pictureH);
        self.cellHeight = CGRectGetMaxY(self.pictureF) + padding;
    }else{
        self.cellHeight = CGRectGetMaxY(self.textF) + padding;
    }

}

+(NSArray *)statusFrames
{
    NSArray *array = [NSArray arrayWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"statuses.plist" ofType:nil]];
    NSMutableArray *arrayM = [NSMutableArray array];
    for (NSDictionary *dict in array) {
        //要添加statusesFrame对象
        NYStatusFrame *statusFrame = [[NYStatusFrame alloc]init];
        //调用statusFrame的setter方法,保存status模型,同时计算出控件的位置(setter方法中进行的)
        statusFrame.status = [NYStatus statusWithDict:dict];
        //将statusFrame添加到数组
        [arrayM addObject:statusFrame];
    }
    return arrayM;
}
@end


ps:新建iOS交流学习群:304570962

可以加猫猫QQ:1764541256 或则微信znycat

让我们一起努力学习吧。

原文:http://blog.csdn.net/u013357243?viewmode=contents

时间: 2024-10-25 15:24:20

猫猫学IOS(十七)UI之纯代码自定义Cell实现新浪微博UI的相关文章

(素材源码)猫猫学IOS(十七)UI之纯代码自定义Cell实现新浪微博UI

猫猫分享,必须精品 素材代码地址:http://download.csdn.net/detail/u013357243/8580249 原文地址:http://blog.csdn.net/u013357243?viewmode=contents 先看效果图 编程思路 代码创建Cell的步骤 1> 创建自定义Cell,继承自UITableViewCell 2> 根据需求,确定控件,并定义属性 3> 用getter方法完成控件的实例化,只创建并添加到contentView,不处理位置 4&g

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

iOS开发UI篇-以微博界面为例使用纯代码自定义cell程序编码全过程(一) 一.storyboard的处理 直接让控制器继承uitableview controller,然后在storyboard中把继承自uiviewcontroller的控制器干掉,重新拖一个tableview controller,和主控制器进行连线. 项目结构和plist文件 二.程序逻辑业务的处理 第一步,把配图和plist中拿到项目中,加载plist数据(非png的图片放到spooding files中) 第二步,字

猫猫学iOS 之微博项目实战(10)微博cell中图片的显示以及各种填充模式简介

猫猫分享,必须精品 原创文章,欢迎转载.转载请注明:翟乃玉的博客 地址:http://blog.csdn.net/u013357243 :一效果 如果直接设置会有拉伸等等的状况,这里主要介绍图片显示的一些细节 二:代码 代码实现其实很简单,微博当中用了一个photos来存放九宫格这些图片,然后用了一个photo类来做每个photo,并且在上面显示gif等的样式,很多很多小技巧,直接上代码 九宫格根据行列设置等算法,不难 #import "HWStatusPhotosView.h" #i

猫猫学IOS(四)UI之半小时搞定Tom猫

话不多说 先上效果 项目源码素材下载地址: Tom猫游戏代码iOS 素材http://blog.csdn.net/u013357243/article/details/44457357 效果图 曾经风靡一时的tom猫其实制作起来那是叫一个相当的easy啊 功能全部实现,(关键是素材,没有素材的可以加我微信) 新手也可以很快的完成tom这个很拉轰的ios应用哦 做过android的我表示,android党默哀下把,那个做起来真心痛苦.... 然后呢你需要准备这些素材... 拖拽控件吧,因为这一个项

(素材_源码) 猫猫学IOS(五)UI之360等下载管理器九宫格UI

猫猫分享,必须精品 先看效果 代码学习地址: 猫猫学IOS(五)UI之360等下载管理器九宫格UI 猫猫学IOS(五)UI之360等下载管理器九宫格UI http://blog.csdn.net/u013357243/article/details/44486609 下载地址:http://download.csdn.net/detail/u013357243/8516817 ps1:有想要源码的可以加猫猫微信znycat QQ也可以:1764541256 --视频学习资料素材免费分析,哎自己一

ios开发UI篇—使用纯代码自定义UItableviewcell实现一个简单的微博界面布局

本文转自 :http://www.cnblogs.com/wendingding/p/3761730.html ios开发UI篇—使用纯代码自定义UItableviewcell实现一个简单的微博界面布局 一.实现效果 二.使用纯代码自定义一个tableview的步骤 1.新建一个继承自UITableViewCell的类 2.重写initWithStyle:reuseIdentifier:方法 添加所有需要显示的子控件(不需要设置子控件的数据和frame,  子控件要添加到contentView中

iOS开发UI基础—使用纯代码自定义UItableviewcell实现一个简单的微博界面布局

ios开发UI基础-使用纯代码自定义UItableviewcell实现一个简单的微博界面布局 一.实现效果 二.使用纯代码自定义一个tableview的步骤 1.新建一个继承自UITableViewCell的类 2.重写initWithStyle:reuseIdentifier:方法 添加所有需要显示的子控件(不需要设置子控件的数据和frame,  子控件要添加到contentView中) 进行子控件一次性的属性设置(有些属性只需要设置一次, 比如字体\固定的图片) 3.提供2个模型 数据模型:

iOS界面布局之三——纯代码的autoLayout及布局动画

iOS界面布局之三--纯代码的autoLayout及布局动画 一.引言 关于界面布局,apple的策略已经趋于成熟,autolayout的优势在开发中也已经展现的淋漓尽致.除了使用storyBoard进行布局约束的拖拽,有时我们也需要在代码中进行autolayout的布局设置,Masonry库可以方便的创建约束属性,实际上,我们也没有必要再使用系统原生的代码来创建和设置约束,这篇博客只作为使用的方法备忘.前几篇布局介绍的链接如下: 使用autoresizing进行界面布局:http://my.o

swift 之 纯代码创建 cell

初学swift 但是网上只有很多swift用xib创建的cell,就算是有也不是我想要的.今天自己弄了一个不用xib纯代码写的,来上代码 自定义cell 下面是controller 例外说一点懒加载 OC的懒加载 @property (nonatomic, strong) NSMutableArray * dataSource; - (NSMutableArray *)dataSource { if (!_dataSource) { _dataSource = [NSMutableArray a