iOS 新浪微博-5.1 首页微博列表_时间/配图
在上一篇中,我们已经把首页微博显示出来了,但还有很多细节,需要我们去调整的。这一章中,我们将处理好时间,配图,工具框及转发微博等小细节的功能。
时间处理
第一步:定义一个时间的类别,用于判断是昨天、今天等。
NSDate+Time.h
#import <Foundation/Foundation.h> @interface NSDate (Time)
/**
* 判断某个时间是否为今年
*/
- (BOOL)isThisYear;
/**
* 判断某个时间是否为昨天
*/
- (BOOL)isYesterday;
/**
* 判断某个时间是否为今天
*/
- (BOOL)isToday;
@end
NSDate+Time.m
//
// NSDate+Time.m
//
// Created by jiangys on 15/10/25.
// Copyright © 2015年 Jiangys. All rights reserved.
// #import "NSDate+Time.h" @implementation NSDate (Time) /**
* 判断某个时间是否为今年
*/
- (BOOL)isThisYear
{
NSCalendar *calendar = [NSCalendar currentCalendar];
// 获得某个时间的年月日时分秒
NSDateComponents *dateCmps = [calendar components:NSCalendarUnitYear fromDate:self];
NSDateComponents *nowCmps = [calendar components:NSCalendarUnitYear fromDate:[NSDate date]];
return dateCmps.year == nowCmps.year;
} /**
* 判断某个时间是否为昨天
*/
- (BOOL)isYesterday
{
NSDate *now = [NSDate date]; // date == 2014-04-30 10:05:28 --> 2014-04-30 00:00:00
// now == 2014-05-01 09:22:10 --> 2014-05-01 00:00:00
NSDateFormatter *fmt = [[NSDateFormatter alloc] init];
fmt.dateFormat = @"yyyy-MM-dd"; // 2014-04-30
NSString *dateStr = [fmt stringFromDate:self];
// 2014-10-18
NSString *nowStr = [fmt stringFromDate:now]; // 2014-10-30 00:00:00
NSDate *date = [fmt dateFromString:dateStr];
// 2014-10-18 00:00:00
now = [fmt dateFromString:nowStr]; NSCalendar *calendar = [NSCalendar currentCalendar]; NSCalendarUnit unit = NSCalendarUnitYear | NSCalendarUnitMonth | NSCalendarUnitDay;
NSDateComponents *cmps = [calendar components:unit fromDate:date toDate:now options:]; return cmps.year == && cmps.month == && cmps.day == ;
} /**
* 判断某个时间是否为今天
*/
- (BOOL)isToday
{
NSDate *now = [NSDate date];
NSDateFormatter *fmt = [[NSDateFormatter alloc] init];
fmt.dateFormat = @"yyyy-MM-dd"; NSString *dateStr = [fmt stringFromDate:self];
NSString *nowStr = [fmt stringFromDate:now]; return [dateStr isEqualToString:nowStr];
} @end
第二步:在Status.m中重写时间的属性
/**
* 时间处理,重写 1.今年
1> 今天
* 1分内: 刚刚
* 1分~59分内:xx分钟前
* 大于60分钟:xx小时前 2> 昨天
* 昨天 xx:xx 3> 其他
* xx-xx xx:xx 2.非今年
1> xxxx-xx-xx xx:xx
*/
- (NSString *)created_at
{ NSDateFormatter *fmt = [[NSDateFormatter alloc] init];
// 如果是真机调试,转换这种欧美时间,需要设置locale
fmt.locale = [[NSLocale alloc] initWithLocaleIdentifier:@"en_US"]; // 设置日期格式(声明字符串里面每个数字和单词的含义)
// E:星期几
// M:月份
// d:几号(这个月的第几天)
// H:24小时制的小时
// m:分钟
// s:秒
// y:年
fmt.dateFormat = @"EEE MMM dd HH:mm:ss Z yyyy";
// _created_at = @"Tue Sep 30 17:06:25 +0600 2014"; // 微博的创建日期
NSDate *createDate = [fmt dateFromString:_created_at];
// 当前时间
NSDate *now = [NSDate date]; // 日历对象(方便比较两个日期之间的差距)
NSCalendar *calendar = [NSCalendar currentCalendar];
// NSCalendarUnit枚举代表想获得哪些差值
NSCalendarUnit unit = NSCalendarUnitYear | NSCalendarUnitMonth | NSCalendarUnitDay | NSCalendarUnitHour | NSCalendarUnitMinute | NSCalendarUnitSecond;
// 计算两个日期之间的差值
NSDateComponents *cmps = [calendar components:unit fromDate:createDate toDate:now options:]; if ([createDate isThisYear]) { // 今年
if ([createDate isYesterday]) { // 昨天
fmt.dateFormat = @"昨天 HH:mm";
return [fmt stringFromDate:createDate];
} else if ([createDate isToday]) { // 今天
if (cmps.hour >= ) {
return [NSString stringWithFormat:@"%d小时前", (int)cmps.hour];
} else if (cmps.minute >= ) {
return [NSString stringWithFormat:@"%d分钟前", (int)cmps.minute];
} else {
return @"刚刚";
}
} else { // 今年的其他日子
fmt.dateFormat = @"MM-dd HH:mm";
return [fmt stringFromDate:createDate];
}
} else { // 非今年
fmt.dateFormat = @"yyyy-MM-dd HH:mm";
return [fmt stringFromDate:createDate];
}
}
这样,就可以显示出来了,但会有问题,就是不断的下拉刷新时,本来显示“刚刚”字样的,刷新后,可能变为“1分钟前”。由于“刚刚”的字体size不变化,因而显示“1分钟前”会导致显示不全。改进方法
/** 时间 */
// self.timeLabel.text = status.created_at;
// self.timeLabel.frame = statusFrame.timeLabelF; /** 来源 */
// self.sourceLabel.text = status.source;
// self.sourceLabel.frame = statusFrame.sourceLabelF; /** 时间 */
NSString *time = status.created_at;
CGFloat timeX = statusFrame.nameLabelF.origin.x;
CGFloat timeY = CGRectGetMaxY(statusFrame.nameLabelF) + StatusCellBorderW;
CGSize timeSize = [time sizeWithFont:StatusCellTimeFont];
self.timeLabel.frame = (CGRect){{timeX, timeY}, timeSize};
self.timeLabel.text = time; /** 来源 */
CGFloat sourceX = CGRectGetMaxX(self.timeLabel.frame) + StatusCellBorderW;
CGFloat sourceY = timeY;
CGSize sourceSize = [status.source sizeWithFont:StatusCellSourceFont];
self.sourceLabel.frame = (CGRect){{sourceX, sourceY}, sourceSize};
self.sourceLabel.text = status.source;
这样,每重新加载cell时,都重新计算一遍时间和来源的size。
效果:

配图
第一步:通过查看新浪微博的API,我们可以看到,返回的配图是一个集合。先定义好集合里的模型
Photo.h
#import <Foundation/Foundation.h> @interface Photo : NSObject
/** 缩略图地址 */
@property (nonatomic, copy) NSString *thumbnail_pic;
@end
第二步:在Status模型了,添加配图的集合属性,并指定,里面的集合是由Photo这个模型来构成的。
Status.h
/** 微博配图地址。多图时返回多图链接。无配图返回“[]” */
@property (nonatomic, strong) NSArray *pic_urls;
Status.m ,需要引用 #import "MJExtension.h"
+ (NSDictionary *)objectClassInArray
{
return @{@"pic_urls" : [Photo class]};
}
第三步:拿到数据之后,接下来要做的事情
- 定义一个配图的View
- 定义一个装了该微博所有的配图View的容器
- 往容器里填充配图
- 计算这个容器的宽高
1.定义一个配图的View
StatusPhotoView.h
#import <UIKit/UIKit.h>
@class Photo; @interface StatusPhotoView : UIImageView /** 图片模型 */
@property (nonatomic, strong) Photo *photo; @end
StatusPhotoView.m
//
// StatusPhotoView.m
//
// Created by jiangys on 15/10/25.
// Copyright © 2015年 Jiangys. All rights reserved.
// #import "StatusPhotoView.h"
#import "Photo.h"
#import "UIImageView+WebCache.h" @interface StatusPhotoView()
@property (nonatomic, weak) UIImageView *gifView;
@end @implementation StatusPhotoView - (UIImageView *)gifView
{
if (!_gifView) {
UIImage *image = [UIImage imageNamed:@"timeline_image_gif"];
UIImageView *gifView = [[UIImageView alloc] initWithImage:image];
[self addSubview:gifView];
self.gifView = gifView;
}
return _gifView;
} - (instancetype)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
// 内容模式
self.contentMode = UIViewContentModeScaleAspectFill;
// 超出边框的内容都剪掉
self.clipsToBounds = YES;
}
return self;
} - (void)setPhoto:(Photo *)photo
{
_photo = photo; // 设置图片
[self sd_setImageWithURL:[NSURL URLWithString:photo.thumbnail_pic] placeholderImage:[UIImage imageNamed:@"timeline_image_placeholder"]]; // 显示\隐藏gif控件
// 判断是够以gif或者GIF结尾
self.gifView.hidden = ![photo.thumbnail_pic.lowercaseString hasSuffix:@"gif"];
} - (void)layoutSubviews
{
[super layoutSubviews]; self.gifView.x = self.width - self.gifView.width;
self.gifView.y = self.height - self.gifView.height;
}
@end
2.定义一个装了该微博所有的配图View的容器
StatusPhotosView.h
#import <UIKit/UIKit.h> @interface StatusPhotosView : UIView /** 图片模型 */
@property (nonatomic, strong) NSArray *photos; /**
* 根据图片个数计算相册的尺寸
*/
+ (CGSize)sizeWithCount:(NSUInteger)count;
@end
StatusPhotosView.m
//
// StatusPhotosView.m
//
// Created by jiangys on 15/10/25.
// Copyright © 2015年 Jiangys. All rights reserved.
// #import "StatusPhotosView.h"
#import "StatusPhotoView.h"
#import "Photo.h" #define StatusPhotoWH 70
#define StatusPhotoMargin 10
#define StatusPhotoMaxCol(count) ((count==4)?2:3) @implementation StatusPhotosView - (void)setPhotos:(NSArray *)photos
{
_photos = photos; NSUInteger photosCount = photos.count; // 创建足够多的图片控制
while (self.subviews.count < photosCount) {
StatusPhotoView *photoView = [[StatusPhotoView alloc] init];
[self addSubview:photoView];
} // 遍历所有的图片控件,设置图片
for (int i = ; i < self.subviews.count; i++) {
StatusPhotoView *photoView = self.subviews[i]; if (i < photosCount) {
photoView.photo = photos[i];
photoView.hidden = NO;
} else{
photoView.hidden=YES;
}
} } - (void)layoutSubviews
{
[super layoutSubviews]; // 设置图片的尺寸和位置
NSUInteger photosCount = self.photos.count;
int maxCol = StatusPhotoMaxCol(photosCount);
for (int i = ; i<photosCount; i++) {
StatusPhotoView *photoView = self.subviews[i]; int col = i % maxCol;
photoView.x = col * (StatusPhotoWH + StatusPhotoMargin); int row = i / maxCol;
photoView.y = row * (StatusPhotoWH + StatusPhotoMargin);
photoView.width = StatusPhotoWH;
photoView.height = StatusPhotoWH;
}
} + (CGSize)sizeWithCount:(NSUInteger)count
{
// 最大列数(一行最多有多少列)
int maxCols = StatusPhotoMaxCol(count); NSUInteger cols = (count >= maxCols)? maxCols : count;
CGFloat photosW = cols * StatusPhotoWH + (cols - ) * StatusPhotoMargin; // 行数
NSUInteger rows = (count + maxCols - ) / maxCols;
CGFloat photosH = rows * StatusPhotoWH + (rows - ) * StatusPhotoMargin; return CGSizeMake(photosW, photosH);
}
@end
3.StatusFrame.m里计算配图的宽高
/** 配图 */
CGFloat originalH = ;
if (status.pic_urls.count) { // 有配图
CGFloat photosX = contentX;
CGFloat photosY = CGRectGetMaxY(self.contentLabelF) + StatusCellBorderW;
CGSize photosSize = [StatusPhotosView sizeWithCount:status.pic_urls.count];
_photosViewF = (CGRect){{photosX, photosY}, photosSize}; originalH = CGRectGetMaxY(self.photosViewF) + StatusCellBorderW;
} else { // 没配图
originalH = CGRectGetMaxY(self.contentLabelF) + StatusCellBorderW;
}
4.在StatusCell.m里创建定义容器,初始化容器并赋值
/** 配图 */
@property (nonatomic, weak) StatusPhotosView *photosView;
初始化容器initWithStyle
/** 配图 */
StatusPhotosView *photosView = [[StatusPhotosView alloc] init];
[originalView addSubview:photosView];
self.photosView = photosView;
赋值setStatusFrame
/** 配图 */
if (status.pic_urls.count) {
self.photosView.frame = statusFrame.photosViewF;
self.photosView.photos = status.pic_urls;
self.photosView.hidden = NO;
} else {
self.photosView.hidden = YES;
}
效果如下图:

iOS 新浪微博-5.1 首页微博列表_时间/配图的更多相关文章
- iOS 新浪微博-5.2 首页微博列表_转发微博/工具栏
继续于上一篇,还是做首页的功能,这一篇把剩下的首页继续完善. 看看上面的图片,分析: 1.转发微博里面的内容,和原创微博是一样的,由文字+配图组成.这应该放在一个UIView里处理. 2.工具栏也当成 ...
- iOS 新浪微博-5.3 首页微博列表_集成图片浏览器
实际上,我们可以使用李明杰在教程里集成的MJPhotoBrowser,地址: http://code4app.com/ios/快速集成图片浏览器/525e06116803fa7b0a000001 使用 ...
- iOS 新浪微博-5.0 首页微博列表
首页显示微博列表,是微博的核心部分,这一章节,我们主要是显示出微博的列表. 导入第三方类库 pod 'SDWebImage', '~> 3.7.3' pod 'MJRefresh', '~> ...
- IOS SWIFT UITableView 实现简单微博列表
// // Weibo.swift // UITableViewCellExample // // Created by XUYAN on 15/8/15. // Copyright (c) 2015 ...
- Day8-微信小程序实战-交友小程序-首页用户列表渲染及多账号调试及其点赞功能的实现
在这之前已经把编辑个人的所有信息的功能已经完成了 之后先对首页的列表搞动态的,之前都是写死的静态 1.之前都是把好友写死的,现在就在js里面定义一个数组,用循环来动态的绑定 在onReady中定义,取 ...
- 【Android 我的博客APP】1.抓取博客首页文章列表内容——网页数据抓取
打算做个自己在博客园的博客APP,首先要能访问首页获取数据获取首页的文章列表,第一步抓取博客首页文章列表内容的功能已实现,在小米2S上的效果图如下: 思路是:通过编写的工具类访问网页,获取页面源代码, ...
- PHPCMS v9 实现首页,列表页,内容页调用点击量方法
大家好,今天有点闲,看很多朋友经常问PHPCMS v9 首页,列表页,内容页调用点击怎么弄,打算抽时间把代码全部归纳出来,以便大家日后使用,如下: 1,首页调用点击量 {pc:content acti ...
- 织梦首页、列表页调用文章body内容的两种方法
http://blog.csdn.net/langyu1021/article/details/52261411 关于首页.列表页调用文章body内容的两种方法,具体方法如下: 第一种方法: {ded ...
- iOS 新浪微博-1.1框架升级
在iOS 新浪微博-1.0框架搭建 中,使用的是xcode5.1.1开发.现在把重整了一下框架 改为xcode7.0开发 使用cocoaPad管理第三方库 程序将托管到github上 在改为xcode ...
随机推荐
- Windows的文件类型关联
在用脚本语言开发时尤其是在windows环境下发现想自动在命令行环境下运行脚本必须要带着相应的解释器的路径才行,不然就会提示无法找到对应的命令,于是乎在<学习Ruby>这本书中对于文件类型 ...
- 洛谷P1162 填涂颜色【bfs】
题目链接:https://www.luogu.org/problemnew/show/P1162 题意: 有一个0和1组成的矩阵,一些1组成一个闭合圈,圈住一些0,现在要把被圈住的这些0变成2输出. ...
- Away3D引擎学习入门笔记
(1). 准备工作,一些必须知道的东西 (创建时间:2014-06-05) A.必要的开发语言基础.至少要懂点ActionScript 3.0语法(ActionScript 3.0语法及API参考), ...
- linux 之awk
简介 awk是一个强大的文本分析工具,相对grep的查找,sed的编辑,awk在其对数据分析并生成报告时,显得尤为强大.简单来说awk就是把文件逐行的读入,以空格 为默认分隔符将每行切片,切开的部分再 ...
- [administrator][netctl] 给未插线未UP端口设置IP
以下内容均为使用netctl配置工具前提下: 需求: Tstation管理口做日常使用.没有千兆交换.所以加一个一块千兆的卡.这块卡是为了做数据传输专用的. 目前主要就是每周给T7备份使用.但是由于是 ...
- VPS常用操作(自用)
1.screen 用来开启进程,关闭ssh或命令行后扔可以继续运行 screen screen -list screen -r xx screen -S PID -X quit 2.mono asf ...
- 【PyQt5-Qt Designer】文本框读写操作
主要内容: 1.读.写 输入控件(Input Widgets)中的内容(str) 2.保存数据到txt文件 3.从txt文件中读内容,与输入控件中内容比较 将上述各种输入控件(Input Widget ...
- 让对象支持with语句
一.with语句的好处 with语句的好处在于,它可以自动帮我们释放上下文,就比如文件句柄的操作, 如果你不使用with语句操作,你要先open一个文件句柄,使用完毕后要close这个文件句柄, 而使 ...
- es6 学习二 Generator
安装babel的拓展包(Polyfill) ,对Generator的转义 这是一个补完babel支持es6的拓展包,配置步骤为3个: 打开命令行键入 npm install --save-dev ba ...
- 递归、嵌套for循环、map集合方式实现树形结构菜单列表查询
有时候, 我们需要用到菜单列表,但是怎么样去实现一个菜单列表的编写呢,这是一重要的问题. 比如我们需要编写一个树形结构的菜单,那么我们可以使用JQuery的zTree插件:http://www.tre ...