您的位置:首页 > 移动开发 > IOS开发

iOS 新浪微博-5.1 首页微博列表_时间/配图

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

时间处理

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

NSDate+Time.h

#import <Foundation/Foundation.h>

@interface NSDate (Time)
/**
*  判断某个时间是否为今年
*/
- (BOOL)isThisYear;
/**
*  判断某个时间是否为昨天
*/
- (BOOL)isYesterday;
/**
*  判断某个时间是否为今天
*/
- (BOOL)isToday;
@end


NSDate+Time.m

//
//  NSDate+Time.m
//  Weibo
//
//  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:0];

return cmps.year == 0 && cmps.month == 0 && cmps.day == 1;
}

/**
*  判断某个时间是否为今天
*/
- (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:0];

if ([createDate isThisYear]) { // 今年
if ([createDate isYesterday]) { // 昨天
fmt.dateFormat = @"昨天 HH:mm";
return [fmt stringFromDate:createDate];
} else if ([createDate isToday]) { // 今天
if (cmps.hour >= 1) {
return [NSString stringWithFormat:@"%d小时前", (int)cmps.hour];
} else if (cmps.minute >= 1) {
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
//  Weibo
//
//  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
//  Weibo
//
//  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 = 0; 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 = 0; 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 - 1) * StatusPhotoMargin;

// 行数
NSUInteger rows = (count + maxCols - 1) / maxCols;
CGFloat photosH = rows * StatusPhotoWH + (rows - 1) * StatusPhotoMargin;

return CGSizeMake(photosW, photosH);
}
@end


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

/** 配图 */
CGFloat originalH = 0;
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;
}


效果如下图:

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: