zoukankan      html  css  js  c++  java
  • 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
    //  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]};
    }

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

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

    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;
        }

     效果如下图:

  • 相关阅读:
    【题解】Atcoder ARC#76 F-Exhausted?
    【题解】SCOI2006萌萌哒
    【题解】51nod1967 路径定向
    巧克力之树 [点分治+树状数组]
    thr [树链剖分+dp]
    [bzoj4361] isn [树状数组+dp+容斥原理]
    [POI2015][bzoj4383] Pustynia [线段树优化建图+拓扑排序]
    [HNOI2015][bzoj4011] 落叶枫音 [拓扑DP]
    [Atcoder Grand Contest 006 F][AGC006F] Blackout [染色]
    [bzoj4712] 洪水 [树链剖分+线段树+dp]
  • 原文地址:https://www.cnblogs.com/jys509/p/4909919.html
Copyright © 2011-2022 走看看