在上一篇中,我们已经把首页微博显示出来了,但还有很多细节,需要我们去调整的。这一章中,我们将处理好时间,配图,工具框及转发微博等小细节的功能。

时间处理

第一步:定义一个时间的类别,用于判断是昨天、今天等。

NSDate+Time.h

  1. #import <Foundation/Foundation.h>
  2.  
  3. @interface NSDate (Time)
  4. /**
  5. * 判断某个时间是否为今年
  6. */
  7. - (BOOL)isThisYear;
  8. /**
  9. * 判断某个时间是否为昨天
  10. */
  11. - (BOOL)isYesterday;
  12. /**
  13. * 判断某个时间是否为今天
  14. */
  15. - (BOOL)isToday;
  16. @end

NSDate+Time.m

  1. //
  2. // NSDate+Time.m
  3. // Weibo
  4. //
  5. // Created by jiangys on 15/10/25.
  6. // Copyright © 2015年 Jiangys. All rights reserved.
  7. //
  8.  
  9. #import "NSDate+Time.h"
  10.  
  11. @implementation NSDate (Time)
  12.  
  13. /**
  14. * 判断某个时间是否为今年
  15. */
  16. - (BOOL)isThisYear
  17. {
  18. NSCalendar *calendar = [NSCalendar currentCalendar];
  19. // 获得某个时间的年月日时分秒
  20. NSDateComponents *dateCmps = [calendar components:NSCalendarUnitYear fromDate:self];
  21. NSDateComponents *nowCmps = [calendar components:NSCalendarUnitYear fromDate:[NSDate date]];
  22. return dateCmps.year == nowCmps.year;
  23. }
  24.  
  25. /**
  26. * 判断某个时间是否为昨天
  27. */
  28. - (BOOL)isYesterday
  29. {
  30. NSDate *now = [NSDate date];
  31.  
  32. // date == 2014-04-30 10:05:28 --> 2014-04-30 00:00:00
  33. // now == 2014-05-01 09:22:10 --> 2014-05-01 00:00:00
  34. NSDateFormatter *fmt = [[NSDateFormatter alloc] init];
  35. fmt.dateFormat = @"yyyy-MM-dd";
  36.  
  37. // 2014-04-30
  38. NSString *dateStr = [fmt stringFromDate:self];
  39. // 2014-10-18
  40. NSString *nowStr = [fmt stringFromDate:now];
  41.  
  42. // 2014-10-30 00:00:00
  43. NSDate *date = [fmt dateFromString:dateStr];
  44. // 2014-10-18 00:00:00
  45. now = [fmt dateFromString:nowStr];
  46.  
  47. NSCalendar *calendar = [NSCalendar currentCalendar];
  48.  
  49. NSCalendarUnit unit = NSCalendarUnitYear | NSCalendarUnitMonth | NSCalendarUnitDay;
  50. NSDateComponents *cmps = [calendar components:unit fromDate:date toDate:now options:];
  51.  
  52. return cmps.year == && cmps.month == && cmps.day == ;
  53. }
  54.  
  55. /**
  56. * 判断某个时间是否为今天
  57. */
  58. - (BOOL)isToday
  59. {
  60. NSDate *now = [NSDate date];
  61. NSDateFormatter *fmt = [[NSDateFormatter alloc] init];
  62. fmt.dateFormat = @"yyyy-MM-dd";
  63.  
  64. NSString *dateStr = [fmt stringFromDate:self];
  65. NSString *nowStr = [fmt stringFromDate:now];
  66.  
  67. return [dateStr isEqualToString:nowStr];
  68. }
  69.  
  70. @end

第二步:在Status.m中重写时间的属性

  1. /**
  2. * 时间处理,重写
  3.  
  4. 1.今年
  5. 1> 今天
  6. * 1分内: 刚刚
  7. * 1分~59分内:xx分钟前
  8. * 大于60分钟:xx小时前
  9.  
  10. 2> 昨天
  11. * 昨天 xx:xx
  12.  
  13. 3> 其他
  14. * xx-xx xx:xx
  15.  
  16. 2.非今年
  17. 1> xxxx-xx-xx xx:xx
  18. */
  19. - (NSString *)created_at
  20. {
  21.  
  22. NSDateFormatter *fmt = [[NSDateFormatter alloc] init];
  23. // 如果是真机调试,转换这种欧美时间,需要设置locale
  24. fmt.locale = [[NSLocale alloc] initWithLocaleIdentifier:@"en_US"];
  25.  
  26. // 设置日期格式(声明字符串里面每个数字和单词的含义)
  27. // E:星期几
  28. // M:月份
  29. // d:几号(这个月的第几天)
  30. // H:24小时制的小时
  31. // m:分钟
  32. // s:秒
  33. // y:年
  34. fmt.dateFormat = @"EEE MMM dd HH:mm:ss Z yyyy";
  35. // _created_at = @"Tue Sep 30 17:06:25 +0600 2014";
  36.  
  37. // 微博的创建日期
  38. NSDate *createDate = [fmt dateFromString:_created_at];
  39. // 当前时间
  40. NSDate *now = [NSDate date];
  41.  
  42. // 日历对象(方便比较两个日期之间的差距)
  43. NSCalendar *calendar = [NSCalendar currentCalendar];
  44. // NSCalendarUnit枚举代表想获得哪些差值
  45. NSCalendarUnit unit = NSCalendarUnitYear | NSCalendarUnitMonth | NSCalendarUnitDay | NSCalendarUnitHour | NSCalendarUnitMinute | NSCalendarUnitSecond;
  46. // 计算两个日期之间的差值
  47. NSDateComponents *cmps = [calendar components:unit fromDate:createDate toDate:now options:];
  48.  
  49. if ([createDate isThisYear]) { // 今年
  50. if ([createDate isYesterday]) { // 昨天
  51. fmt.dateFormat = @"昨天 HH:mm";
  52. return [fmt stringFromDate:createDate];
  53. } else if ([createDate isToday]) { // 今天
  54. if (cmps.hour >= ) {
  55. return [NSString stringWithFormat:@"%d小时前", (int)cmps.hour];
  56. } else if (cmps.minute >= ) {
  57. return [NSString stringWithFormat:@"%d分钟前", (int)cmps.minute];
  58. } else {
  59. return @"刚刚";
  60. }
  61. } else { // 今年的其他日子
  62. fmt.dateFormat = @"MM-dd HH:mm";
  63. return [fmt stringFromDate:createDate];
  64. }
  65. } else { // 非今年
  66. fmt.dateFormat = @"yyyy-MM-dd HH:mm";
  67. return [fmt stringFromDate:createDate];
  68. }
  69. }

这样,就可以显示出来了,但会有问题,就是不断的下拉刷新时,本来显示“刚刚”字样的,刷新后,可能变为“1分钟前”。由于“刚刚”的字体size不变化,因而显示“1分钟前”会导致显示不全。改进方法

  1. /** 时间 */
  2. // self.timeLabel.text = status.created_at;
  3. // self.timeLabel.frame = statusFrame.timeLabelF;
  4.  
  5. /** 来源 */
  6. // self.sourceLabel.text = status.source;
  7. // self.sourceLabel.frame = statusFrame.sourceLabelF;
  8.  
  9. /** 时间 */
  10. NSString *time = status.created_at;
  11. CGFloat timeX = statusFrame.nameLabelF.origin.x;
  12. CGFloat timeY = CGRectGetMaxY(statusFrame.nameLabelF) + StatusCellBorderW;
  13. CGSize timeSize = [time sizeWithFont:StatusCellTimeFont];
  14. self.timeLabel.frame = (CGRect){{timeX, timeY}, timeSize};
  15. self.timeLabel.text = time;
  16.  
  17. /** 来源 */
  18. CGFloat sourceX = CGRectGetMaxX(self.timeLabel.frame) + StatusCellBorderW;
  19. CGFloat sourceY = timeY;
  20. CGSize sourceSize = [status.source sizeWithFont:StatusCellSourceFont];
  21. self.sourceLabel.frame = (CGRect){{sourceX, sourceY}, sourceSize};
  22. self.sourceLabel.text = status.source;

这样,每重新加载cell时,都重新计算一遍时间和来源的size。

效果:

配图

第一步:通过查看新浪微博的API,我们可以看到,返回的配图是一个集合。先定义好集合里的模型

Photo.h

  1. #import <Foundation/Foundation.h>
  2.  
  3. @interface Photo : NSObject
  4. /** 缩略图地址 */
  5. @property (nonatomic, copy) NSString *thumbnail_pic;
  6. @end

第二步:在Status模型了,添加配图的集合属性,并指定,里面的集合是由Photo这个模型来构成的。

Status.h

  1. /** 微博配图地址。多图时返回多图链接。无配图返回“[]” */
  2. @property (nonatomic, strong) NSArray *pic_urls;

Status.m ,需要引用 #import "MJExtension.h"

  1. + (NSDictionary *)objectClassInArray
  2. {
  3. return @{@"pic_urls" : [Photo class]};
  4. }

第三步:拿到数据之后,接下来要做的事情

  1. 定义一个配图的View
  2. 定义一个装了该微博所有的配图View的容器
  3. 往容器里填充配图
  4. 计算这个容器的宽高

1.定义一个配图的View

StatusPhotoView.h

  1. #import <UIKit/UIKit.h>
  2. @class Photo;
  3.  
  4. @interface StatusPhotoView : UIImageView
  5.  
  6. /** 图片模型 */
  7. @property (nonatomic, strong) Photo *photo;
  8.  
  9. @end

StatusPhotoView.m

  1. //
  2. // StatusPhotoView.m
  3. // Weibo
  4. //
  5. // Created by jiangys on 15/10/25.
  6. // Copyright © 2015年 Jiangys. All rights reserved.
  7. //
  8.  
  9. #import "StatusPhotoView.h"
  10. #import "Photo.h"
  11. #import "UIImageView+WebCache.h"
  12.  
  13. @interface StatusPhotoView()
  14. @property (nonatomic, weak) UIImageView *gifView;
  15. @end
  16.  
  17. @implementation StatusPhotoView
  18.  
  19. - (UIImageView *)gifView
  20. {
  21. if (!_gifView) {
  22. UIImage *image = [UIImage imageNamed:@"timeline_image_gif"];
  23. UIImageView *gifView = [[UIImageView alloc] initWithImage:image];
  24. [self addSubview:gifView];
  25. self.gifView = gifView;
  26. }
  27. return _gifView;
  28. }
  29.  
  30. - (instancetype)initWithFrame:(CGRect)frame
  31. {
  32. self = [super initWithFrame:frame];
  33. if (self) {
  34. // 内容模式
  35. self.contentMode = UIViewContentModeScaleAspectFill;
  36. // 超出边框的内容都剪掉
  37. self.clipsToBounds = YES;
  38. }
  39. return self;
  40. }
  41.  
  42. - (void)setPhoto:(Photo *)photo
  43. {
  44. _photo = photo;
  45.  
  46. // 设置图片
  47. [self sd_setImageWithURL:[NSURL URLWithString:photo.thumbnail_pic] placeholderImage:[UIImage imageNamed:@"timeline_image_placeholder"]];
  48.  
  49. // 显示\隐藏gif控件
  50. // 判断是够以gif或者GIF结尾
  51. self.gifView.hidden = ![photo.thumbnail_pic.lowercaseString hasSuffix:@"gif"];
  52. }
  53.  
  54. - (void)layoutSubviews
  55. {
  56. [super layoutSubviews];
  57.  
  58. self.gifView.x = self.width - self.gifView.width;
  59. self.gifView.y = self.height - self.gifView.height;
  60. }
  61. @end

2.定义一个装了该微博所有的配图View的容器

StatusPhotosView.h

  1. #import <UIKit/UIKit.h>
  2.  
  3. @interface StatusPhotosView : UIView
  4.  
  5. /** 图片模型 */
  6. @property (nonatomic, strong) NSArray *photos;
  7.  
  8. /**
  9. * 根据图片个数计算相册的尺寸
  10. */
  11. + (CGSize)sizeWithCount:(NSUInteger)count;
  12. @end

StatusPhotosView.m

  1. //
  2. // StatusPhotosView.m
  3. // Weibo
  4. //
  5. // Created by jiangys on 15/10/25.
  6. // Copyright © 2015年 Jiangys. All rights reserved.
  7. //
  8.  
  9. #import "StatusPhotosView.h"
  10. #import "StatusPhotoView.h"
  11. #import "Photo.h"
  12.  
  13. #define StatusPhotoWH 70
  14. #define StatusPhotoMargin 10
  15. #define StatusPhotoMaxCol(count) ((count==4)?2:3)
  16.  
  17. @implementation StatusPhotosView
  18.  
  19. - (void)setPhotos:(NSArray *)photos
  20. {
  21. _photos = photos;
  22.  
  23. NSUInteger photosCount = photos.count;
  24.  
  25. // 创建足够多的图片控制
  26. while (self.subviews.count < photosCount) {
  27. StatusPhotoView *photoView = [[StatusPhotoView alloc] init];
  28. [self addSubview:photoView];
  29. }
  30.  
  31. // 遍历所有的图片控件,设置图片
  32. for (int i = ; i < self.subviews.count; i++) {
  33. StatusPhotoView *photoView = self.subviews[i];
  34.  
  35. if (i < photosCount) {
  36. photoView.photo = photos[i];
  37. photoView.hidden = NO;
  38. } else{
  39. photoView.hidden=YES;
  40. }
  41. }
  42.  
  43. }
  44.  
  45. - (void)layoutSubviews
  46. {
  47. [super layoutSubviews];
  48.  
  49. // 设置图片的尺寸和位置
  50. NSUInteger photosCount = self.photos.count;
  51. int maxCol = StatusPhotoMaxCol(photosCount);
  52. for (int i = ; i<photosCount; i++) {
  53. StatusPhotoView *photoView = self.subviews[i];
  54.  
  55. int col = i % maxCol;
  56. photoView.x = col * (StatusPhotoWH + StatusPhotoMargin);
  57.  
  58. int row = i / maxCol;
  59. photoView.y = row * (StatusPhotoWH + StatusPhotoMargin);
  60. photoView.width = StatusPhotoWH;
  61. photoView.height = StatusPhotoWH;
  62. }
  63. }
  64.  
  65. + (CGSize)sizeWithCount:(NSUInteger)count
  66. {
  67. // 最大列数(一行最多有多少列)
  68. int maxCols = StatusPhotoMaxCol(count);
  69.  
  70. NSUInteger cols = (count >= maxCols)? maxCols : count;
  71. CGFloat photosW = cols * StatusPhotoWH + (cols - ) * StatusPhotoMargin;
  72.  
  73. // 行数
  74. NSUInteger rows = (count + maxCols - ) / maxCols;
  75. CGFloat photosH = rows * StatusPhotoWH + (rows - ) * StatusPhotoMargin;
  76.  
  77. return CGSizeMake(photosW, photosH);
  78. }
  79. @end

3.StatusFrame.m里计算配图的宽高

  1. /** 配图 */
  2. CGFloat originalH = ;
  3. if (status.pic_urls.count) { // 有配图
  4. CGFloat photosX = contentX;
  5. CGFloat photosY = CGRectGetMaxY(self.contentLabelF) + StatusCellBorderW;
  6. CGSize photosSize = [StatusPhotosView sizeWithCount:status.pic_urls.count];
  7. _photosViewF = (CGRect){{photosX, photosY}, photosSize};
  8.  
  9. originalH = CGRectGetMaxY(self.photosViewF) + StatusCellBorderW;
  10. } else { // 没配图
  11. originalH = CGRectGetMaxY(self.contentLabelF) + StatusCellBorderW;
  12. }

4.在StatusCell.m里创建定义容器,初始化容器并赋值

  1. /** 配图 */
  2. @property (nonatomic, weak) StatusPhotosView *photosView;

初始化容器initWithStyle

  1. /** 配图 */
  2. StatusPhotosView *photosView = [[StatusPhotosView alloc] init];
  3. [originalView addSubview:photosView];
  4. self.photosView = photosView;

赋值setStatusFrame

  1. /** 配图 */
  2. if (status.pic_urls.count) {
  3. self.photosView.frame = statusFrame.photosViewF;
  4. self.photosView.photos = status.pic_urls;
  5. self.photosView.hidden = NO;
  6. } else {
  7. self.photosView.hidden = YES;
  8. }

效果如下图:

iOS 新浪微博-5.1 首页微博列表_时间/配图的更多相关文章

  1. iOS 新浪微博-5.2 首页微博列表_转发微博/工具栏

    继续于上一篇,还是做首页的功能,这一篇把剩下的首页继续完善. 看看上面的图片,分析: 1.转发微博里面的内容,和原创微博是一样的,由文字+配图组成.这应该放在一个UIView里处理. 2.工具栏也当成 ...

  2. iOS 新浪微博-5.3 首页微博列表_集成图片浏览器

    实际上,我们可以使用李明杰在教程里集成的MJPhotoBrowser,地址: http://code4app.com/ios/快速集成图片浏览器/525e06116803fa7b0a000001 使用 ...

  3. iOS 新浪微博-5.0 首页微博列表

    首页显示微博列表,是微博的核心部分,这一章节,我们主要是显示出微博的列表. 导入第三方类库 pod 'SDWebImage', '~> 3.7.3' pod 'MJRefresh', '~> ...

  4. IOS SWIFT UITableView 实现简单微博列表

    // // Weibo.swift // UITableViewCellExample // // Created by XUYAN on 15/8/15. // Copyright (c) 2015 ...

  5. Day8-微信小程序实战-交友小程序-首页用户列表渲染及多账号调试及其点赞功能的实现

    在这之前已经把编辑个人的所有信息的功能已经完成了 之后先对首页的列表搞动态的,之前都是写死的静态 1.之前都是把好友写死的,现在就在js里面定义一个数组,用循环来动态的绑定 在onReady中定义,取 ...

  6. 【Android 我的博客APP】1.抓取博客首页文章列表内容——网页数据抓取

    打算做个自己在博客园的博客APP,首先要能访问首页获取数据获取首页的文章列表,第一步抓取博客首页文章列表内容的功能已实现,在小米2S上的效果图如下: 思路是:通过编写的工具类访问网页,获取页面源代码, ...

  7. PHPCMS v9 实现首页,列表页,内容页调用点击量方法

    大家好,今天有点闲,看很多朋友经常问PHPCMS v9 首页,列表页,内容页调用点击怎么弄,打算抽时间把代码全部归纳出来,以便大家日后使用,如下: 1,首页调用点击量 {pc:content acti ...

  8. 织梦首页、列表页调用文章body内容的两种方法

    http://blog.csdn.net/langyu1021/article/details/52261411 关于首页.列表页调用文章body内容的两种方法,具体方法如下: 第一种方法: {ded ...

  9. iOS 新浪微博-1.1框架升级

    在iOS 新浪微博-1.0框架搭建 中,使用的是xcode5.1.1开发.现在把重整了一下框架 改为xcode7.0开发 使用cocoaPad管理第三方库 程序将托管到github上 在改为xcode ...

随机推荐

  1. hdu3613 Best Reward【Manacher】

    Best Reward Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)Total ...

  2. hdu3374 String Problem【最小表示法】【exKMP】

    String Problem Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)To ...

  3. okvis论文解读

    C. Keypoint Matching and Keyframe Selection 我们的处理流程采用定制的多尺度SSE优化Harris角点检测器与BRISK描述符提取相结合[12].检测器通过逐 ...

  4. ubuntu 搜狗输入法 在中断失效

    实测是更换了皮肤后,出现在中断输入故障,乱码.在其他界面可能是正常的,更换语言没用. killall fcitx输入法突然好了(根据网友所说,更改一堆东西貌似并没有什么用) 此时关闭输入法皮肤一切正常 ...

  5. FFmpeg制作+x264+faac

    https://blog.csdn.net/leixiaohua1020/article/details/47071547  雷神的博客 https://www.jianshu.com/p/3f023 ...

  6. android gradle jnilibs

    https://blog.csdn.net/xx326664162/article/details/51167849 [ABIXCPU] Android jniLibs下目录详解(.so文件) htt ...

  7. AndroidStudio_RecyclerView

    在这里回顾一下RecyclerView的用法 RecyclerView的用法与Button的用法很类似,只是要增加一个Adapter.java文件和item.xml文件 具体用法: 1.在page1. ...

  8. Javascript面向对象编程(三):非构造函数的继承(对象的深拷贝与浅拷贝)

    Javascript面向对象编程(三):非构造函数的继承   作者: 阮一峰 日期: 2010年5月24日 这个系列的第一部分介绍了"封装",第二部分介绍了使用构造函数实现&quo ...

  9. nodejs 学习一 process.execPath 、 __dirname、process.cwd()的区别

    process.execPath node.exe的绝对路径 __dirname 当前执行到__dirname文件文件路径 process.cwd() 启动node命令的目录的绝对路劲

  10. 对web标准化(或网站重构)知道哪些相关的知识,简述几条你知道的Web标准?

    网页主要有三部分组成:结构(Structrue).表现(Presentation)和行为(Behavior).对应的网站标准也分为三方面: 1.结构化标准语言,主要包括XHTML和XML: 2.表现标 ...