Skip to content

Commit

Permalink
2.9.0
Browse files Browse the repository at this point in the history
  • Loading branch information
MoLice committed Nov 1, 2018
1 parent 5b82d91 commit be231f9
Show file tree
Hide file tree
Showing 13 changed files with 151 additions and 142 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -10,16 +10,19 @@
#import <UIKit/UIKit.h>
#import "QMUIAsset.h"

// checkbox 的 margin 默认值
extern const UIEdgeInsets QMUIImagePickerCollectionViewCellDefaultCheckboxButtonMargins;

@class QMUIButton;

/**
* 图片选择空间里的九宫格 cell,支持显示 checkbox、饼状进度条及重试按钮(iCloud 图片需要)
*/
@interface QMUIImagePickerCollectionViewCell : UICollectionViewCell

/// 收藏的资源的心形图片
@property(nonatomic, strong) UIImage *favoriteImage UI_APPEARANCE_SELECTOR;

/// 收藏的资源的心形图片的上下左右间距,相对于 cell 左下角零点而言,也即如果 left 越大则越往右,bottom 越大则越往上,另外 top 会影响底部遮罩的高度
@property(nonatomic, assign) UIEdgeInsets favoriteImageMargins UI_APPEARANCE_SELECTOR;

/// checkbox 未被选中时显示的图片
@property(nonatomic, strong) UIImage *checkboxImage UI_APPEARANCE_SELECTOR;

Expand All @@ -29,30 +32,26 @@ extern const UIEdgeInsets QMUIImagePickerCollectionViewCellDefaultCheckboxButton
/// checkbox 的 margin,定位从每个 cell(即每张图片)的最右边开始计算
@property(nonatomic, assign) UIEdgeInsets checkboxButtonMargins UI_APPEARANCE_SELECTOR;

/// videoMarkImageView 的 icon
@property(nonatomic, strong) UIImage *videoMarkImage UI_APPEARANCE_SELECTOR;

/// videoMarkImageView 的 margin,定位从每个 cell(即每张图片)的左下角开始计算
@property(nonatomic, assign) UIEdgeInsets videoMarkImageViewMargins UI_APPEARANCE_SELECTOR;

/// videoDurationLabel 的字号
@property(nonatomic, strong) UIFont *videoDurationLabelFont UI_APPEARANCE_SELECTOR;

/// videoDurationLabel 的字体颜色
@property(nonatomic, strong) UIColor *videoDurationLabelTextColor UI_APPEARANCE_SELECTOR;

/// videoDurationLabel 布局是对齐右下角再做 margins 偏移
/// 视频时长文字的间距,相对于 cell 右下角而言,也即如果 right 越大则越往左,bottom 越大则越往上,另外 top 会影响底部遮罩的高度
@property(nonatomic, assign) UIEdgeInsets videoDurationLabelMargins UI_APPEARANCE_SELECTOR;

@property(nonatomic, strong, readonly) UIImageView *contentImageView;
@property(nonatomic, strong, readonly) UIImageView *favoriteImageView;
@property(nonatomic, strong, readonly) QMUIButton *checkboxButton;
@property(nonatomic, strong, readonly) UIImageView *videoMarkImageView;
@property(nonatomic, strong, readonly) UILabel *videoDurationLabel;
@property(nonatomic, strong, readonly) CAGradientLayer *videoBottomShadowLayer;
@property(nonatomic, strong, readonly) CAGradientLayer *bottomShadowLayer;// 当出现收藏或者视频时长文字时就会显示遮罩,遮罩高度为 favoriteImage 和 videoDurationLabel 中最高者的高度

@property(nonatomic, assign, getter=isSelectable) BOOL selectable;
@property(nonatomic, assign, getter=isChecked) BOOL checked;
@property(nonatomic, assign) QMUIAssetDownloadStatus downloadStatus; // Cell 中对应资源的下载状态,这个值的变动会相应地调整 UI 表现
@property(nonatomic, copy) NSString *assetIdentifier;// 当前这个 cell 正在展示的 QMUIAsset 的 identifier

- (void)renderWithAsset:(QMUIAsset *)asset referenceSize:(CGSize)referenceSize;

@end
Original file line number Diff line number Diff line change
Expand Up @@ -14,48 +14,45 @@
#import "UILabel+QMUI.h"
#import "CALayer+QMUI.h"
#import "QMUIButton.h"

// checkbox 的 margin 默认值
const UIEdgeInsets QMUIImagePickerCollectionViewCellDefaultCheckboxButtonMargins = {6, 0, 0, 6};
const UIEdgeInsets QMUIImagePickerCollectionViewCellDefaultVideoMarkImageViewMargins = {0, 8, 8, 0};

#import "UIView+QMUI.h"
#import "NSString+QMUI.h"

@interface QMUIImagePickerCollectionViewCell ()

@property(nonatomic, strong, readwrite) UIImageView *favoriteImageView;
@property(nonatomic, strong, readwrite) QMUIButton *checkboxButton;
@property(nonatomic, strong, readwrite) CAGradientLayer *bottomShadowLayer;

@end


@implementation QMUIImagePickerCollectionViewCell

@synthesize videoMarkImageView = _videoMarkImageView;
@synthesize videoDurationLabel = _videoDurationLabel;
@synthesize videoBottomShadowLayer = _videoBottomShadowLayer;

+ (void)initialize {
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
[QMUIImagePickerCollectionViewCell appearance].favoriteImage = [QMUIHelper imageWithName:@"QMUI_pickerImage_favorite"];
[QMUIImagePickerCollectionViewCell appearance].favoriteImageMargins = UIEdgeInsetsMake(6, 6, 6, 6);
[QMUIImagePickerCollectionViewCell appearance].checkboxImage = [QMUIHelper imageWithName:@"QMUI_pickerImage_checkbox"];
[QMUIImagePickerCollectionViewCell appearance].checkboxCheckedImage = [QMUIHelper imageWithName:@"QMUI_pickerImage_checkbox_checked"];
[QMUIImagePickerCollectionViewCell appearance].checkboxButtonMargins = QMUIImagePickerCollectionViewCellDefaultCheckboxButtonMargins;
[QMUIImagePickerCollectionViewCell appearance].videoMarkImage = [QMUIHelper imageWithName:@"QMUI_pickerImage_video_mark"];
[QMUIImagePickerCollectionViewCell appearance].videoMarkImageViewMargins = QMUIImagePickerCollectionViewCellDefaultVideoMarkImageViewMargins;
[QMUIImagePickerCollectionViewCell appearance].checkboxButtonMargins = UIEdgeInsetsMake(6, 6, 6, 6);
[QMUIImagePickerCollectionViewCell appearance].videoDurationLabelFont = UIFontMake(12);
[QMUIImagePickerCollectionViewCell appearance].videoDurationLabelTextColor = UIColorWhite;
[QMUIImagePickerCollectionViewCell appearance].videoDurationLabelMargins = UIEdgeInsetsMake(0, 0, 6, 6);
[QMUIImagePickerCollectionViewCell appearance].videoDurationLabelMargins = UIEdgeInsetsMake(5, 5, 5, 7);
});
}

- (instancetype)initWithFrame:(CGRect)frame {
self = [super initWithFrame:frame];
if (self) {
[self initImagePickerCollectionViewCellUI];
self.favoriteImage = [QMUIImagePickerCollectionViewCell appearance].favoriteImage;
self.favoriteImageMargins = [QMUIImagePickerCollectionViewCell appearance].favoriteImageMargins;
self.checkboxImage = [QMUIImagePickerCollectionViewCell appearance].checkboxImage;
self.checkboxCheckedImage = [QMUIImagePickerCollectionViewCell appearance].checkboxCheckedImage;
self.checkboxButtonMargins = [QMUIImagePickerCollectionViewCell appearance].checkboxButtonMargins;
self.videoMarkImage = [QMUIImagePickerCollectionViewCell appearance].videoMarkImage;
self.videoMarkImageViewMargins = [QMUIImagePickerCollectionViewCell appearance].videoMarkImageViewMargins;
self.videoDurationLabelFont = [QMUIImagePickerCollectionViewCell appearance].videoDurationLabelFont;
self.videoDurationLabelTextColor = [QMUIImagePickerCollectionViewCell appearance].videoDurationLabelTextColor;
self.videoDurationLabelMargins = [QMUIImagePickerCollectionViewCell appearance].videoDurationLabelMargins;
Expand All @@ -69,77 +66,90 @@ - (void)initImagePickerCollectionViewCellUI {
self.contentImageView.clipsToBounds = YES;
[self.contentView addSubview:self.contentImageView];

self.bottomShadowLayer = [CAGradientLayer layer];
[self.bottomShadowLayer qmui_removeDefaultAnimations];
self.bottomShadowLayer.colors = @[(id)UIColorMakeWithRGBA(0, 0, 0, 0).CGColor, (id)UIColorMakeWithRGBA(0, 0, 0, .6).CGColor];
self.bottomShadowLayer.hidden = YES;
[self.contentView.layer addSublayer:self.bottomShadowLayer];
[self setNeedsLayout];

self.favoriteImageView = [[UIImageView alloc] init];
self.favoriteImageView.hidden = YES;
[self.contentView addSubview:self.favoriteImageView];

self.checkboxButton = [[QMUIButton alloc] init];
self.checkboxButton.qmui_automaticallyAdjustTouchHighlightedInScrollView = YES;
self.checkboxButton.qmui_outsideEdge = UIEdgeInsetsMake(-6, -6, -6, -6);
self.checkboxButton.hidden = YES;
[self.contentView addSubview:self.checkboxButton];
}

- (void)initVideoBottomShadowLayerIfNeeded {
if (!_videoBottomShadowLayer) {
_videoBottomShadowLayer = [CAGradientLayer layer];
[_videoBottomShadowLayer qmui_removeDefaultAnimations];
_videoBottomShadowLayer.colors = @[(id)UIColorMakeWithRGBA(0, 0, 0, 0).CGColor, (id)UIColorMakeWithRGBA(0, 0, 0, .6).CGColor];
[self.contentView.layer addSublayer:_videoBottomShadowLayer];
[self setNeedsLayout];
}
}

- (void)initVideoMarkImageViewIfNeed {
if (_videoMarkImageView) {
return;
}
_videoMarkImageView = [[UIImageView alloc] init];
[_videoMarkImageView setImage:self.videoMarkImage];
[_videoMarkImageView sizeToFit];
[self.contentView addSubview:_videoMarkImageView];
[self setNeedsLayout];
}

- (void)initVideoDurationLabelIfNeed {
if (_videoDurationLabel) {
return;
- (void)renderWithAsset:(QMUIAsset *)asset referenceSize:(CGSize)referenceSize {
self.assetIdentifier = asset.identifier;

// 异步请求资源对应的缩略图
[asset requestThumbnailImageWithSize:referenceSize completion:^(UIImage *result, NSDictionary *info) {
if ([self.assetIdentifier isEqualToString:asset.identifier]) {
self.contentImageView.image = result;
} else {
self.contentImageView.image = nil;
}
}];

if (asset.assetType == QMUIAssetTypeVideo) {
[self initVideoDurationLabelIfNeeded];
self.videoDurationLabel.text = [NSString qmui_timeStringWithMinsAndSecsFromSecs:asset.duration];
self.videoDurationLabel.hidden = NO;
} else {
self.videoDurationLabel.hidden = YES;
}
_videoDurationLabel = [[UILabel alloc] init];
_videoDurationLabel.font = self.videoDurationLabelFont;
_videoDurationLabel.textColor = self.videoDurationLabelTextColor;
[self.contentView addSubview:_videoDurationLabel];

self.favoriteImageView.hidden = !asset.phAsset.favorite;

self.bottomShadowLayer.hidden = !((self.videoDurationLabel && !self.videoDurationLabel.hidden) || !self.favoriteImageView.hidden);

[self setNeedsLayout];
}

- (void)initVideoRelatedViewsIfNeeded {
[self initVideoBottomShadowLayerIfNeeded];
[self initVideoMarkImageViewIfNeed];
[self initVideoDurationLabelIfNeed];
}

- (void)layoutSubviews {
[super layoutSubviews];
self.contentImageView.frame = self.contentView.bounds;
if (_selectable) {
self.checkboxButton.frame = CGRectSetXY(self.checkboxButton.frame, CGRectGetWidth(self.contentView.bounds) - self.checkboxButtonMargins.right - CGRectGetWidth(self.checkboxButton.bounds), self.checkboxButtonMargins.top);
}

if (_videoBottomShadowLayer && _videoMarkImageView && _videoDurationLabel) {
_videoMarkImageView.frame = CGRectSetXY(_videoMarkImageView.frame, self.videoMarkImageViewMargins.left, CGRectGetHeight(self.contentView.bounds) - CGRectGetHeight(_videoMarkImageView.bounds) - self.videoMarkImageViewMargins.bottom);

[_videoDurationLabel sizeToFit];
_videoDurationLabel.frame = ({
CGFloat minX = CGRectGetWidth(self.contentView.bounds) - self.videoDurationLabelMargins.right - CGRectGetWidth(_videoDurationLabel.bounds);
CGFloat minY = CGRectGetHeight(self.contentView.bounds) - self.videoDurationLabelMargins.bottom - CGRectGetHeight(_videoDurationLabel.bounds);
CGRectSetXY(_videoDurationLabel.frame, minX, minY);
});

CGFloat videoBottomShadowLayerHeight = CGRectGetHeight(self.contentView.bounds) - CGRectGetMinY(_videoMarkImageView.frame) + self.videoMarkImageViewMargins.bottom;// 背景阴影遮罩的高度取决于(视频 icon 的高度 + 上下 margin)
_videoBottomShadowLayer.frame = CGRectFlatMake(0, CGRectGetHeight(self.contentView.bounds) - videoBottomShadowLayerHeight, CGRectGetWidth(self.contentView.bounds), videoBottomShadowLayerHeight);
CGFloat bottomShadowLayerHeight = 0;

if (!self.favoriteImageView.hidden) {
self.favoriteImageView.frame = CGRectSetXY(self.favoriteImageView.frame, self.favoriteImageMargins.left, CGRectGetHeight(self.contentView.bounds) - self.favoriteImageMargins.bottom - CGRectGetHeight(self.favoriteImageView.frame));
bottomShadowLayerHeight = CGRectGetHeight(self.favoriteImageView.frame) + UIEdgeInsetsGetVerticalValue(self.favoriteImageMargins);
}

if (self.videoDurationLabel && !self.videoDurationLabel.hidden) {
[self.videoDurationLabel sizeToFit];
self.videoDurationLabel.frame = CGRectSetXY(self.videoDurationLabel.frame, CGRectGetWidth(self.contentView.bounds) - self.videoDurationLabelMargins.right - CGRectGetWidth(self.videoDurationLabel.frame), CGRectGetHeight(self.contentView.bounds) - self.videoDurationLabelMargins.bottom - CGRectGetHeight(self.videoDurationLabel.frame));
bottomShadowLayerHeight = MAX(bottomShadowLayerHeight, CGRectGetHeight(self.videoDurationLabel.frame) + UIEdgeInsetsGetVerticalValue(self.videoDurationLabelMargins));
}

if (!self.bottomShadowLayer.hidden) {
self.bottomShadowLayer.frame = CGRectMake(0, CGRectGetHeight(self.contentView.bounds) - bottomShadowLayerHeight, CGRectGetWidth(self.contentView.bounds), bottomShadowLayerHeight);
}
}

- (void)setFavoriteImage:(UIImage *)favoriteImage {
if (![self.favoriteImage isEqual:favoriteImage]) {
self.favoriteImageView.image = favoriteImage;
[self.favoriteImageView sizeToFit];
[self setNeedsLayout];
}
_favoriteImage = favoriteImage;
}

- (void)setCheckboxImage:(UIImage *)checkboxImage {
if (![self.checkboxImage isEqual:checkboxImage]) {
[self.checkboxButton setImage:checkboxImage forState:UIControlStateNormal];
[self.checkboxButton sizeToFit];
[self setNeedsLayout];
}
_checkboxImage = checkboxImage;
}
Expand All @@ -149,22 +159,16 @@ - (void)setCheckboxCheckedImage:(UIImage *)checkboxCheckedImage {
[self.checkboxButton setImage:checkboxCheckedImage forState:UIControlStateSelected];
[self.checkboxButton setImage:checkboxCheckedImage forState:UIControlStateSelected|UIControlStateHighlighted];
[self.checkboxButton sizeToFit];
[self setNeedsLayout];
}
_checkboxCheckedImage = checkboxCheckedImage;
}

- (void)setVideoMarkImage:(UIImage *)videoMarkImage {
if (![self.videoMarkImage isEqual:videoMarkImage]) {
[_videoMarkImageView setImage:videoMarkImage];
[_videoMarkImageView sizeToFit];
}
_videoMarkImage = videoMarkImage;
}

- (void)setVideoDurationLabelFont:(UIFont *)videoDurationLabelFont {
if (![self.videoDurationLabelFont isEqual:videoDurationLabelFont]) {
_videoDurationLabel.font = videoDurationLabelFont;
[_videoDurationLabel qmui_calculateHeightAfterSetAppearance];
[self setNeedsLayout];
}
_videoDurationLabelFont = videoDurationLabelFont;
}
Expand Down Expand Up @@ -201,19 +205,12 @@ - (void)setDownloadStatus:(QMUIAssetDownloadStatus)downloadStatus {
}
}

- (UILabel *)videoDurationLabel {
[self initVideoRelatedViewsIfNeeded];
return _videoDurationLabel;
}

- (UIImageView *)videoMarkImageView {
[self initVideoRelatedViewsIfNeeded];
return _videoMarkImageView;
}

- (CAGradientLayer *)videoBottomShadowLayer {
[self initVideoRelatedViewsIfNeeded];
return _videoBottomShadowLayer;
- (void)initVideoDurationLabelIfNeeded {
if (!self.videoDurationLabel) {
_videoDurationLabel = [[UILabel alloc] qmui_initWithFont:self.videoDurationLabelFont textColor:self.videoDurationLabelTextColor];
[self.contentView addSubview:_videoDurationLabel];
[self setNeedsLayout];
}
}

@end
15 changes: 12 additions & 3 deletions QMUIKit/QMUIComponents/ImagePickerLibrary/QMUIImagePickerHelper.m
Original file line number Diff line number Diff line change
Expand Up @@ -21,15 +21,24 @@
@implementation QMUIImagePickerHelper

+ (void)springAnimationOfImageSelectedCountChangeWithCountLabel:(UILabel *)label {
[QMUIHelper actionSpringAnimationForView:label];
[self actionSpringAnimationForView:label];
}

+ (void)springAnimationOfImageCheckedWithCheckboxButton:(UIButton *)button {
[QMUIHelper actionSpringAnimationForView:button];
[self actionSpringAnimationForView:button];
}

+ (void)actionSpringAnimationForView:(UIView *)view {
NSTimeInterval duration = 0.6;
CAKeyframeAnimation *springAnimation = [CAKeyframeAnimation animationWithKeyPath:@"transform.scale"];
springAnimation.values = @[@.85, @1.15, @.9, @1.0,];
springAnimation.keyTimes = @[@(0.0 / duration), @(0.15 / duration) , @(0.3 / duration), @(0.45 / duration),];
springAnimation.duration = duration;
[view.layer addAnimation:springAnimation forKey:@"imagePickerActionSpring"];
}

+ (void)removeSpringAnimationOfImageCheckedWithCheckboxButton:(UIButton *)button {
[button.layer removeAnimationForKey:QMUISpringAnimationKey];
[button.layer removeAnimationForKey:@"imagePickerActionSpring"];
}

+ (QMUIAssetsGroup *)assetsGroupOfLastPickerAlbumWithUserIdentify:(NSString *)userIdentify {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@
#import "CALayer+QMUI.h"
#import "UIView+QMUI.h"
#import <MobileCoreServices/MobileCoreServices.h>
#import "NSString+QMUI.h"
#import "QMUIEmptyView.h"
#import "UIControl+QMUI.h"
#import "QMUILog.h"
Expand Down Expand Up @@ -337,29 +336,14 @@ - (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cell
identifier = kImageOrUnknownCellIdentifier;
}
QMUIImagePickerCollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:identifier forIndexPath:indexPath];
cell.assetIdentifier = imageAsset.identifier;

// 异步请求资源对应的缩略图
[imageAsset requestThumbnailImageWithSize:[self referenceImageSize] completion:^(UIImage *result, NSDictionary *info) {
if ([cell.assetIdentifier isEqualToString:imageAsset.identifier]) {
cell.contentImageView.image = result;
} else {
cell.contentImageView.image = nil;
}
}];

if (imageAsset.assetType == QMUIAssetTypeVideo) {
cell.videoDurationLabel.text = [NSString qmui_timeStringWithMinsAndSecsFromSecs:imageAsset.duration];
}
[cell renderWithAsset:imageAsset referenceSize:[self referenceImageSize]];

[cell.checkboxButton addTarget:self action:@selector(handleCheckBoxButtonClick:) forControlEvents:UIControlEventTouchUpInside];

cell.selectable = self.allowsMultipleSelection;
if (cell.selectable) {
// 如果该图片的 QMUIAsset 被包含在已选择图片的数组中,则控制该图片被选中
cell.checked = [self.selectedImageAssetArray containsObject:imageAsset];
}
[cell setNeedsLayout];
return cell;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,7 @@ - (void)NavigationBarTransition_viewWillLayoutSubviews {

BOOL shouldCustomNavigationBarTransition = NO;

if (!self.transitionNavigationBar || !self.transitionNavigationBar.superview) {
if (!self.transitionNavigationBar) {
if (isPushingViewContrller) {
if ([toViewController canCustomNavigationBarTransitionWhenPushAppearing] ||
[fromViewController canCustomNavigationBarTransitionWhenPushDisappearing]) {
Expand Down Expand Up @@ -195,10 +195,11 @@ - (void)addTransitionNavigationBarIfNeeded {
}

- (void)removeTransitionNavigationBar {
if (!self.transitionNavigationBar || !self.transitionNavigationBar.superview) {
if (!self.transitionNavigationBar) {
return;
}
[self.transitionNavigationBar removeFromSuperview];
self.transitionNavigationBar = nil;
}

- (void)resizeTransitionNavigationBarFrame {
Expand Down
Loading

0 comments on commit be231f9

Please sign in to comment.