AJ分享,必须精品

先看效果图


编程思路

代码创建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中的代码


// 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

AJ学IOS(17)UI之纯代码自定义Cell实现新浪微博UI的更多相关文章

  1. iOS开发小技巧--纯代码自定义cell

    纯代码自定义cell 自定义cell的步骤(每个cell的高度不一样,每个cell里面显示的内容也不一样) 1.新建一个继承自UITableViewCell的子类 2.在initWithStyle:方 ...

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

    AJ分享,必须精品 :一效果 如果直接设置会有拉伸等等的状况,这里主要介绍图片显示的一些细节 二:代码 代码实现其实很简单,微博当中用了一个photos来存放九宫格这些图片,然后用了一个photo类来 ...

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

    本文转自 :http://www.cnblogs.com/wendingding/p/3761730.html ios开发UI篇—使用纯代码自定义UItableviewcell实现一个简单的微博界面布 ...

  4. AJ学IOS(16)UI之XIB自定义Cell实现团购UI

    AJ分享,必须精品 先看效果图 自定义Cell 本次主要是自定义Cell的学习 实现自定义Cell主要有三种方法:按照使用的频繁度排序: XIB > 纯代码 > StoryBoard XI ...

  5. 李洪强iOS开发之后使用纯代码实现横向滚动的UIScrollView

    李洪强iOS开发之后使用纯代码实现横向滚动的UIScrollView (VTmagic是一个实现左右滚动的控制器的框架,也可以实现此功能) 实现的效果:  01 - 创建四个控制器 02 - 定义需要 ...

  6. iOS回顾笔记(08) -- 自定义Cell的类型和创建步骤总结

    iOS回顾笔记(08) -- 自定义Cell的类型和创建步骤总结 项目中我们常见的自定义cell主要分为两种 等高cell:如应用列表.功能列表 非等高cell:如微博列表.QQ聊天页面 下面对这 ...

  7. 通过代码自定义cell 新浪微博页面显示

    通过代码自定义cell(cell的高度不一致)(如果高度一致的cell 用xib实现) 1.新建一个集成自UItableVIewCell的类 2.重写initWithStle :方法 - (insta ...

  8. AJ学IOS(03)UI之纯代码实现UI——图片查看器

    AJ分享,必须精品 先看效果 主要实现类似看新闻的一个界面,不用拖拽,纯代码手工写. 首先分析app可以很容易知道他这里有两个UILabel一个UIImageView还有两个UIButton 定义UI ...

  9. AJ学IOS(41)UI之核心动画 两行代码搞定3D转场

    AJ分享,必须精品 效果: 代码: 其实代码很少,苹果都给封装好了 // 1.创建核心动画 CATransition *ca = [CATransition animation]; // 1.1动画过 ...

随机推荐

  1. 妈妈再也不担心我面试被Redis问得脸都绿了

    长文前排提醒,收藏向前排提醒,素质三连 (转发 + 在看 + 留言) 前排提醒! 前言 Redis 作为一个开源的,高级的键值存储和一个适用的解决方案,已经越来越在构建 「高性能」.「可扩展」 的 W ...

  2. Spring Data JPA 自定义对象接收查询结果集

    Spring Data JPA 简介 Spring Data JPA 是 Spring 基于 ORM 框架.JPA 规范的基础上封装的一套JPA应用框架,可使开发者用极简的代码即可实现对数据库的访问和 ...

  3. ECCV 2018 目标检测 | IoU-Net:将IoU的作用发挥到极致

    常见的目标检测算法缺少了定位效果的学习,IoU-Net提出IoU predictor.IoU-guided NMS和Optimization-based bounding box refinement ...

  4. [Docker02]Docker_registry

    部署Docker仓库 Docker registry #检查端口5000是否被占用 netstat -tunlp | grep 5000 # the local host ip is 172.17.0 ...

  5. Hive常用的10个系统函数及作用

    聚合函数 函数处理的数据粒度为多条记录. sum()—求和 count()—求数据量 avg()—求平均直 distinct—求不同值数 min—求最小值 max—求最人值 分析函数 Analytic ...

  6. 《JavaScript 模式》读书笔记(5)— 对象创建模式1

    这又是一个新的开始,对象的重要性不言而喻.在JavaScript中创建对象是十分容易的,之前聊过的对象字面量和构造函数都可以达到目的.但是本篇中,我们越过那些方法,以寻求一些额外的对象创建模式. 本篇 ...

  7. go:数据类型

    Go语言中有丰富的数据类型,除了基本的整型.浮点型.布尔型.字符串外,还有数组.切片.结构体.函数.map.通道(channel)等.Go 语言的基本类型和其他语言大同小异. 1.基本数据类型 整型 ...

  8. OpenCV-Python 轨迹栏作为调色板 | 九

    目标 了解将轨迹栏固定到OpenCV窗口 您将学习以下功能:cv.getTrackbarPos,cv.createTrackbar等. 代码演示 在这里,我们将创建一个简单的应用程序,以显示您指定的颜 ...

  9. 来讨论一下这些常见的 Redis 面试题

    Redis应该算面试中必问的一个知识点,但是发现很多童鞋并不熟悉这块,这篇就常见的一些问题做一些整理,有不对的地方欢迎留言指正! 1.Redis支持的数据类型? String(字符串) 格式: set ...

  10. [HDU1029]Ignatius and the Princess IV<桶 水题>

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1029 题目大意: 多组数据,每组数据先给一个n,然后给n各数字,找出n各数字中出现了至少(n+1)/2 ...