| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441 |
- //
- // NTESMediaPreviewViewController.m
- // NIM
- //
- // Created by chris on 2017/9/21.
- // Copyright © 2017年 Netease. All rights reserved.
- //
- #import "NTESMediaPreviewViewController.h"
- #import "UIView+NTES.h"
- #import "UIImageView+WebCache.h"
- #import "UIImage+ForceDecode.h"
- #import "UIImage+NTESColor.h"
- #import "NTESGalleryViewController.h"
- #import "MessageViewController.h"
- #import "NTESVideoViewController.h"
- @interface NTESMediaPreviewViewHeader : UICollectionReusableView
- @property (nonatomic,strong) UILabel *titleLabel;
- - (void)refresh:(NSString *)title;
- @end
- @interface NTESMediaPriviewViewCell : UICollectionViewCell
- @property (nonatomic,strong) UIImageView *imageView;
- @property (nonatomic,strong) UILabel *durationLabel;
- - (void)refresh:(NTESMediaPreviewObject *)object;
- @end
- @interface NTESMediaPreviewViewController ()<UICollectionViewDelegate,UICollectionViewDataSource>
- {
- BOOL _scollToFocus;
- NSCalendar *_calendar;
- NSMutableArray *_titles;
- NSMutableDictionary<NSString *, NSMutableArray *> *_contents;
- }
- @property (nonatomic,copy) NSArray *objects;
- @property (nonatomic,strong) NTESMediaPreviewObject *focusObject;
- @property (nonatomic,strong) UICollectionView *collectionView;
- @property (nonatomic,assign) NSInteger itemCountPerLine;
- @property (nonatomic,assign) CGFloat minimumInteritemSpacing;
- @property (nonatomic,assign) CGFloat minimumLineSpacing;
- @end
- @implementation NTESMediaPreviewViewController
- - (instancetype)initWithPriviewObjects:(NSArray<NTESMediaPreviewObject *> *) objects
- focusObject:(NTESMediaPreviewObject *)focusObject
- {
- self = [super init];
- if (self)
- {
- _objects = objects;
- _focusObject = focusObject;
- _itemCountPerLine = 3;
- _minimumInteritemSpacing = 1.0f;
- _minimumLineSpacing = 1.0f;
- _calendar = [NSCalendar currentCalendar];
- _contents = [[NSMutableDictionary alloc] init];
- _titles = [[NSMutableArray alloc] init];
- }
- return self;
- }
- - (void)viewDidLoad {
- [super viewDidLoad];
- self.navigationItem.title = @"图片和视频";
-
- [self sort];
-
- UICollectionViewFlowLayout *layout = [[UICollectionViewFlowLayout alloc] init];
- self.collectionView = [[UICollectionView alloc] initWithFrame:self.view.bounds collectionViewLayout:layout];
- self.collectionView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
- self.collectionView.backgroundColor = UIColorFromRGB(0x1d1d1d);
- self.collectionView.delegate = self;
- self.collectionView.dataSource = self;
- [self.collectionView registerClass:[NTESMediaPriviewViewCell class] forCellWithReuseIdentifier:@"cell"];
- [self.collectionView registerClass:[NTESMediaPreviewViewHeader class]forSupplementaryViewOfKind:UICollectionElementKindSectionHeader withReuseIdentifier:@"header"];
- UIButton * btn = [UIButton buttonWithType:UIButtonTypeCustom];
- btn.frame = CGRectMake(0, 0, 40, 40);
- [btn setImage:[UIImage imageNamed:@"fanhui2"] forState:UIControlStateNormal];
- btn.imageEdgeInsets = UIEdgeInsetsMake(0, -20, 0, 0);
- [btn addTarget:self action:@selector(backClick) forControlEvents:UIControlEventTouchUpInside];
- UIBarButtonItem *leftItem = [[UIBarButtonItem alloc] initWithCustomView:btn];
- UIBarButtonItem *nagetiveSpacer = [[UIBarButtonItem alloc]initWithBarButtonSystemItem:UIBarButtonSystemItemFixedSpace target:nil action:nil];
- nagetiveSpacer.width = -12;//这个值可以根据自己需要自己调整
- self.navigationItem.leftBarButtonItems = @[nagetiveSpacer, leftItem];
-
- [self.view addSubview:self.collectionView];
- }
- -(void)backClick{
- [self.navigationController popViewControllerAnimated:YES];
- }
- - (void)viewWillAppear:(BOOL)animated{
- self.tabBarController.tabBar.hidden = YES;
- }
- - (void)viewDidDisappear:(BOOL)animated{
- self.tabBarController.tabBar.hidden = NO;
- }
- - (void)viewDidLayoutSubviews
- {
- [super viewDidLayoutSubviews];
- if (!_scollToFocus && self.objects.count)
- {
- NSIndexPath *indexpath = [self indexPath:self.focusObject];
- [self.collectionView scrollToItemAtIndexPath:indexpath atScrollPosition:UICollectionViewScrollPositionTop animated:NO];
- _scollToFocus = YES;
- }
- }
- - (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath
- {
- CGFloat width = (collectionView.width - self.minimumInteritemSpacing * (self.itemCountPerLine - 1)) / self.itemCountPerLine;
- CGFloat height = width;
- return CGSizeMake(width, height);
- }
- - (CGFloat)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout minimumInteritemSpacingForSectionAtIndex:(NSInteger)section
- {
- return self.minimumInteritemSpacing;
- }
- - (CGFloat)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout minimumLineSpacingForSectionAtIndex:(NSInteger)section
- {
- return self.minimumLineSpacing;
- }
- - (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout referenceSizeForHeaderInSection:(NSInteger)section
- {
- return CGSizeMake(collectionView.width, 45);
- }
- - (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section
- {
- NSString *title = [_titles objectAtIndex:section];
- NSArray *array = [_contents objectForKey:title];
- return array.count;
- }
- - (NSInteger)numberOfSectionsInCollectionView:(UICollectionView *)collectionView
- {
- return _titles.count;
- }
- - (__kindof UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
- {
- NTESMediaPriviewViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:@"cell" forIndexPath:indexPath];
- NTESMediaPreviewObject *object = [self objectAtIndex:indexPath];
- [cell refresh:object];
- return cell;
- }
- -(UICollectionReusableView *)collectionView:(UICollectionView *)collectionView viewForSupplementaryElementOfKind:(NSString *)kind atIndexPath:(NSIndexPath *)indexPath
- {
- NTESMediaPreviewViewHeader *reusableView;
- if (kind==UICollectionElementKindSectionHeader)
- {
- reusableView = [collectionView dequeueReusableSupplementaryViewOfKind:UICollectionElementKindSectionHeader withReuseIdentifier:@"header" forIndexPath:indexPath];
- NSString *title = [_titles objectAtIndex:indexPath.section];
- [reusableView refresh:title];
- }
- return reusableView;
- }
- - (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath
- {
- NSArray *viewControllers = self.navigationController.viewControllers;
- NSMutableArray *vcs = [[NSMutableArray alloc] init];
- for (UIViewController *vc in viewControllers)
- {
- [vcs addObject:vc];
- if ([vc isKindOfClass:[MessageViewController class]])
- {
- break;
- }
- }
- [vcs addObject:self];
- self.navigationController.viewControllers = [NSArray arrayWithArray:vcs];
-
- NTESMediaPreviewObject *object = [self objectAtIndex:indexPath];
- if (object.type == NTESMediaPreviewTypeImage)
- {
- NTESGalleryItem *item = [[NTESGalleryItem alloc] init];
- item.thumbPath = [object thumbPath];
- item.imageURL = [object url];
- item.name = [object displayName];
- item.itemId = [object objectId];
- item.size = [object imageSize];
-
- NTESGalleryViewController *vc = [[NTESGalleryViewController alloc] initWithItem:item session:nil];
- vc.hidesBottomBarWhenPushed = YES;
- [self.navigationController pushViewController:vc animated:YES];
- }
- else if(object.type == NTESMediaPreviewTypeVideo)
- {
- NTESVideoViewItem *item = [[NTESVideoViewItem alloc] init];
- item.path = [object path];
- item.url = [object url];
- item.itemId = [object objectId];
-
- NTESVideoViewController *vc = [[NTESVideoViewController alloc] initWithVideoViewItem:item];
- vc.hidesBottomBarWhenPushed = YES;
- [self.navigationController pushViewController:vc animated:YES];
- }
- }
- - (NTESMediaPreviewObject *)objectAtIndex:(NSIndexPath *)indexPath
- {
- NSString *key = [_titles objectAtIndex:indexPath.section];
- NSArray *array = [_contents objectForKey:key];
- return [array objectAtIndex:indexPath.row];
- }
- - (NSIndexPath *)indexPath:(NTESMediaPreviewObject *)object
- {
- NSString *key = [self keyForPreviewObject:object];
- NSArray *array = [_contents objectForKey:key];
-
- NSInteger section = [_titles indexOfObject:key];
- section = (section != NSNotFound? section : 0);
- NSInteger row = [array indexOfObject:object];
- row = (row != NSNotFound? row : 0);
-
- return [NSIndexPath indexPathForRow:row inSection:section];
- }
- - (void)sort
- {
- [_contents removeAllObjects];
- [_titles removeAllObjects];
-
- [self.objects enumerateObjectsUsingBlock:^(id _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
- NTESMediaPreviewObject *object = obj;
- NSString *key = [self keyForPreviewObject:object];
- NSMutableArray *array = [_contents objectForKey:key];
- if (!array)
- {
- array = [[NSMutableArray alloc] init];
- [_contents setObject:array forKey:key];
-
- //因为objects是有序的,这里可以保证 titles 也是有序的,只有第一次出现这个 key 时才添加到 title
- [_titles addObject:key];
- }
- [array addObject:object];
- }];
- }
- - (NSString *)keyForPreviewObject:(NTESMediaPreviewObject *)object
- {
- NSTimeInterval time = object.timestamp;
- NSDate * date = [NSDate dateWithTimeIntervalSince1970:time];
- NSDate * now = [NSDate date];
- NSCalendarUnit components = (NSCalendarUnit)(NSCalendarUnitYear|NSCalendarUnitMonth|NSCalendarUnitWeekOfMonth);
- NSDateComponents *dateComponents = [_calendar components:components fromDate:date];
- NSDateComponents *nowComponents = [_calendar components:components fromDate:now];
-
- NSString *key;
- if (dateComponents.year == nowComponents.year && dateComponents.month == nowComponents.month && dateComponents.weekOfMonth == nowComponents.weekOfMonth)
- {
- key = @"本周";
- }
- else
- {
- key = [NSString stringWithFormat:@"%zd年%zd月",dateComponents.year,dateComponents.month];
- }
- return key;
- }
- #pragma mark - 旋转处理 (iOS8 or above)
- - (void)viewWillTransitionToSize:(CGSize)size
- withTransitionCoordinator:(id<UIViewControllerTransitionCoordinator>)coordinator
- {
- [super viewWillTransitionToSize:size withTransitionCoordinator:coordinator];
- if (![self isViewLoaded]) {
- return;
- }
- [self.collectionView.collectionViewLayout invalidateLayout];
- }
- @end
- FOUNDATION_STATIC_INLINE NSUInteger NTESCacheCostForImage(UIImage *image) {
- return image.size.height * image.size.width * image.scale * image.scale;
- }
- @implementation NTESMediaPreviewObject
- - (BOOL)isEqual:(id)object
- {
- NTESMediaPreviewObject *obj = (NTESMediaPreviewObject *)object;
- return [self.objectId isEqualToString:obj.objectId];
- }
- @end
- @implementation NTESMediaPriviewViewCell
- - (instancetype)initWithFrame:(CGRect)frame
- {
- self = [super initWithFrame:frame];
- if (self)
- {
- _imageView = [[UIImageView alloc] initWithFrame:frame];
- _imageView.contentMode = UIViewContentModeScaleAspectFill;
- _imageView.clipsToBounds = YES;
- [self.contentView addSubview:_imageView];
- _durationLabel = [[UILabel alloc] initWithFrame:CGRectZero];
- _durationLabel.font = [UIFont systemFontOfSize:13.f];
- _durationLabel.textColor = UIColorFromRGB(0xffffff);
- _durationLabel.shadowColor = UIColorFromRGB(0x0);
- _durationLabel.shadowOffset = CGSizeMake(0.5, 0.5);
- [self.contentView addSubview:_durationLabel];
- }
- return self;
- }
- - (void)refresh:(NTESMediaPreviewObject *)object
- {
- static NSCache *previewImageCache;
- static UIImage *placeHolderImage;
- static NSCache *durationCache;
- static dispatch_once_t onceToken;
- dispatch_once(&onceToken, ^{
- previewImageCache = [[NSCache alloc] init];
- durationCache = [[NSCache alloc] init];
- placeHolderImage = [UIImage imageWithColor:[UIColor grayColor]];
- });
- self.imageView.image = nil;
- UIImage *image = [previewImageCache objectForKey:object.thumbPath];
- if (!image && [[NSFileManager defaultManager] fileExistsAtPath:object.thumbPath])
- {
- //存磁盘读出
- image = [UIImage imageWithContentsOfFile:object.thumbPath];
- //预解码
- image = [UIImage decodedImageWithImage:image];
- //缓存
- NSUInteger cost = NTESCacheCostForImage(image);
- [previewImageCache setObject:image forKey:object.thumbPath cost:cost];
- }
- if (!image && object.thumbUrl)
- {
- [self.imageView sd_setImageWithURL:[NSURL URLWithString:object.thumbUrl] placeholderImage:placeHolderImage];
- }
- else
- {
- self.imageView.image = image;
- }
-
- //刷新时长框
- CGRect originFrame = self.durationLabel.frame;
- if (object.duration > 0)
- {
- NSString *duration = [durationCache objectForKey:object.thumbPath];
- if (!duration)
- {
- NSInteger seconds = (object.duration+500)/1000; //四舍五入
- duration = [NSString stringWithFormat:@"%02zd:%02zd",seconds / 60,seconds % 60];
- [durationCache setObject:duration forKey:object.thumbPath];
- }
- self.durationLabel.text = duration;
- }
- else
- {
- self.durationLabel.text = nil;
- }
- [self.durationLabel sizeToFit];
- if (!CGRectEqualToRect(originFrame, self.durationLabel.frame))
- {
- [self setNeedsLayout];
- }
-
- }
- - (void)layoutSubviews
- {
- [super layoutSubviews];
- self.imageView.frame = self.contentView.bounds;
- CGFloat right = 5.f;
- CGFloat botttom = 5.f;
- self.durationLabel.right = self.width - right;
- self.durationLabel.bottom = self.height - botttom;
- }
- @end
- @implementation NTESMediaPreviewViewHeader
- - (instancetype)initWithFrame:(CGRect)frame
- {
- self = [super initWithFrame:frame];
- if (self)
- {
- _titleLabel = [[UILabel alloc] initWithFrame:CGRectZero];
- _titleLabel.font = [UIFont systemFontOfSize:15.f];
- _titleLabel.textColor = UIColorFromRGB(0xffffff);
- [self addSubview:_titleLabel];
- }
- return self;
- }
- - (void)refresh:(NSString *)title
- {
- self.titleLabel.text = title;
- [self.titleLabel sizeToFit];
- }
- - (void)layoutSubviews
- {
- [super layoutSubviews];
- self.titleLabel.left = 10.f;
- self.titleLabel.centerY = self.height * .5f;
- }
- @end
|