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. 安装SQL Server 2008R2 报错“此计算机上安装了 Microsoft Visual Studio 2008 的早期版本”解决方法

    安装SQL Server 2008 R2报错“此计算机上安装了 Microsoft Visual Studio 2008 的早期版本,请在安装 SQL Server 2008 前将 VS2008 升级 ...

  2. mybatis3.2.7 原理和入门程序

    使用jdbc操作数据库有以下缺点   |--数据库连接,使用时就创建,不使用立即释放,对数据库进行频繁开启和关闭,造成数据源资源浪费,影响数据库性能.    设想:使用数据库连接池管理数据库连接.   ...

  3. 洛谷 P3808 【模板】AC自动机(简单版) 题解

    原题链接 前置知识: 字典树.(会 \(\texttt{KMP}\) 就更好) 显然呢,本题用 字典树 和 \(\texttt{KMP}\) 无法解决问题. 所以我们发明了一个东西: \(\textt ...

  4. 【Code Force】Round #589 (Div. 2) D、Complete Tripartite

    题目链接 大致题意 把一个图分成三块,要求任意两块之间是完全图,块内部没有连线 分析 首先根据块内没有连线可以直接分成两块 假定点1是属于块1的,那么所有与点1连接的点,都不属于块1:反之则是块1的 ...

  5. 【狂神说】JAVA Mybatis 笔记+源码

    简介 自学的[狂神JAVA]MyBatis GitHub源码: https://github.com/Donkequan/Mybatis-Study 分享自写源码和笔记 配置用的 jdk13.0.2 ...

  6. TensorFlow系列专题(八):七步带你实现RNN循环神经网络小示例

    欢迎大家关注我们的网站和系列教程:http://panchuang.net/ ,学习更多的机器学习.深度学习的知识! [前言]:在前面的内容里,我们已经学习了循环神经网络的基本结构和运算过程,这一小节 ...

  7. 工作日志,Excel导入树结构数据

    目录 1. 前言 2. 需求分析 2.1 需求难点 2.2 解决难点 2.3 表格设计 3. 功能实现 3.1 一个分枝 3.2 一个分枝多个树叶 3.3 多个分枝多个树叶 4. 代码事例 4.1 目 ...

  8. Dome_iptest_server

    一个简单的ip测试服务器 打印返回 请求头request import socket def send_data(conn, data=None, status=200): if status != ...

  9. Unity引擎入门——制作第一个2D游戏(2)角色移动与动画

    在上一节的内容里,我们已经创建出了一个主角,也搭建了一个简单的场景. 传送门:https://www.cnblogs.com/zny0222/p/12653088.html 既然有了主角,要怎样才能让 ...

  10. ajax使用POST提交报错400

    并非BadRequest!! 在用ajax访问登录接口的时候出现了这个错误,查阅得到使用Ajax的Post需要添加 contentType: "application/x-www-form- ...