Skip to content

Commit

Permalink
2.7.6
Browse files Browse the repository at this point in the history
  • Loading branch information
MoLice committed Aug 29, 2018
1 parent 7b05d2d commit 5daa02d
Show file tree
Hide file tree
Showing 41 changed files with 1,039 additions and 459 deletions.
4 changes: 2 additions & 2 deletions QMUIKit.podspec
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
Pod::Spec.new do |s|
s.name = "QMUIKit"
s.version = "2.7.5"
s.version = "2.7.6"
s.summary = "致力于提高项目 UI 开发效率的解决方案"
s.description = <<-DESC
QMUI iOS 是一个致力于提高项目 UI 开发效率的解决方案,其设计目的是用于辅助快速搭建一个具备基本设计还原效果的 iOS 项目,同时利用自身提供的丰富控件及兼容处理, 让开发者能专注于业务需求而无需耗费精力在基础代码的设计上。不管是新项目的创建,或是已有项目的维护,均可使开发效率和项目质量得到大幅度提升。
Expand Down Expand Up @@ -214,7 +214,7 @@ Pod::Spec.new do |s|
end

ss.subspec 'QMUIPopupMenuView' do |sss|
sss.source_files = 'QMUIKit/QMUIComponents/QMUIPopupMenuView.{h,m}'
sss.source_files = 'QMUIKit/QMUIComponents/QMUIPopupMenuView/*.{h,m}'
sss.dependency 'QMUIKit/QMUIComponents/QMUIButton'
sss.dependency 'QMUIKit/QMUIComponents/QMUIPopupContainerView'
end
Expand Down
2 changes: 1 addition & 1 deletion QMUIKit/Info.plist
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
<key>CFBundlePackageType</key>
<string>FMWK</string>
<key>CFBundleShortVersionString</key>
<string>2.7.5</string>
<string>2.7.6</string>
<key>CFBundleVersion</key>
<string>$(CURRENT_PROJECT_VERSION)</string>
<key>NSPrincipalClass</key>
Expand Down
2 changes: 1 addition & 1 deletion QMUIKit/QMUIComponents/QMUIButton/QMUIButton.h
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ typedef NS_ENUM(NSUInteger, QMUIButtonImagePosition) {
/**
* 设置按钮里图标和文字之间的间隔,会自动响应 imagePosition 的变化而变化,默认为0。<br/>
* 系统默认实现需要同时设置 titleEdgeInsets 和 imageEdgeInsets,同时还需考虑 contentEdgeInsets 的增加(否则不会影响布局,可能会让图标或文字溢出或挤压),使用该属性可以避免以上情况。<br/>
* @warning 会与 imageEdgeInsets、 imageEdgeInsets、 contentEdgeInsets 共同作用。
* @warning 会与 imageEdgeInsets、 titleEdgeInsets、 contentEdgeInsets 共同作用。
*/
@property(nonatomic, assign) IBInspectable CGFloat spacingBetweenImageAndTitle;

Expand Down
14 changes: 4 additions & 10 deletions QMUIKit/QMUIComponents/QMUIButton/QMUIButton.m
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ - (CGSize)sizeThatFits:(CGSize)size {
size = CGSizeMax;
}

BOOL isImageViewShowing = self.imageView && !self.imageView.hidden;
BOOL isImageViewShowing = !!self.currentImage;
BOOL isTitleLabelShowing = self.titleLabel && !self.titleLabel.hidden;
CGSize imageTotalSize = CGSizeZero;// 包含 imageEdgeInsets 那些空间
CGSize titleTotalSize = CGSizeZero;// 包含 titleEdgeInsets 那些空间
Expand All @@ -77,7 +77,7 @@ - (CGSize)sizeThatFits:(CGSize)size {
// 图片和文字上下排版时,宽度以文字或图片的最大宽度为最终宽度
if (isImageViewShowing) {
CGFloat imageLimitWidth = contentLimitSize.width - UIEdgeInsetsGetHorizontalValue(self.imageEdgeInsets);
CGSize imageSize = [self.imageView sizeThatFits:CGSizeMake(imageLimitWidth, CGFLOAT_MAX)];// 假设图片高度必定完整显示
CGSize imageSize = self.currentImage.size;
imageSize.width = fmin(imageSize.width, imageLimitWidth);
imageTotalSize = CGSizeMake(imageSize.width + UIEdgeInsetsGetHorizontalValue(self.imageEdgeInsets), imageSize.height + UIEdgeInsetsGetVerticalValue(self.imageEdgeInsets));
}
Expand All @@ -102,7 +102,7 @@ - (CGSize)sizeThatFits:(CGSize)size {

if (isImageViewShowing) {
CGFloat imageLimitHeight = contentLimitSize.height - UIEdgeInsetsGetVerticalValue(self.imageEdgeInsets);
CGSize imageSize = [self.imageView sizeThatFits:CGSizeMake(CGFLOAT_MAX, imageLimitHeight)];// 假设图片宽度必定完整显示,高度不超过按钮内容
CGSize imageSize = self.currentImage.size;
imageSize.height = fmin(imageSize.height, imageLimitHeight);
imageTotalSize = CGSizeMake(imageSize.width + UIEdgeInsetsGetHorizontalValue(self.imageEdgeInsets), imageSize.height + UIEdgeInsetsGetVerticalValue(self.imageEdgeInsets));
}
Expand Down Expand Up @@ -134,7 +134,7 @@ - (void)layoutSubviews {
return;
}

BOOL isImageViewShowing = self.imageView && !self.imageView.hidden;
BOOL isImageViewShowing = !!self.currentImage;
BOOL isTitleLabelShowing = self.titleLabel && !self.titleLabel.hidden;
CGSize imageLimitSize = CGSizeZero;
CGSize titleLimitSize = CGSizeZero;
Expand Down Expand Up @@ -518,13 +518,7 @@ - (void)updateImageRenderingModeIfNeeded {
if (!normalImage) return;

for (NSNumber *number in states) {
if (number.unsignedIntegerValue > UIControlStateNormal && [self qmui_hasCustomizedButtonPropWithType:QMUICustomizeButtonPropTypeImage forState:number.unsignedIntegerValue]) {
// 这个 state 自定义过 image,就不用处理
continue;
}

UIImage *image = [self imageForState:number.unsignedIntegerValue];

if (self.adjustsImageTintColorAutomatically) {
// 这里的 setImage: 操作不需要使用 renderingMode 对 image 重新处理,而是放到重写的 setImage:forState 里去做就行了
[self setImage:image forState:[number unsignedIntegerValue]];
Expand Down
5 changes: 4 additions & 1 deletion QMUIKit/QMUIComponents/QMUIButton/QMUINavigationButton.m
Original file line number Diff line number Diff line change
Expand Up @@ -355,9 +355,12 @@ - (BOOL)detectSetItemsWhenPopping {
} else {
if (self.qmui_navigationBar && [self.qmui_navigationBar.delegate isKindOfClass:[UINavigationController class]]) {
UINavigationController *navController = (UINavigationController *)self.qmui_navigationBar.delegate;

QMUILog(@"UINavigationItem (QMUINavigationButton)", @"navigationController is %@, topViewController is %@, viewControllers is %@, willAppearByInteractivePopGestureRecognizer is %@, navigationControllerPopGestureRecognizerChanging is %@", navController, navController.topViewController, navController.viewControllers, StringFromBOOL(navController.topViewController.qmui_willAppearByInteractivePopGestureRecognizer), StringFromBOOL(navController.topViewController.qmui_navigationControllerPopGestureRecognizerChanging));

if (navController.topViewController.qmui_willAppearByInteractivePopGestureRecognizer && navController.topViewController.qmui_navigationControllerPopGestureRecognizerChanging) {
// 注意,判断条件里的 qmui_navigationControllerPopGestureRecognizerChanging 关键在于,它是在 viewWillAppear: 执行后才被置为 YES,而 QMUICommonViewController 是在 viewWillAppear: 里调用 setNavigationItems:,所以刚好过滤了这种场景。因为测试过,在 viewWillAppear: 里操作 items 是没问题的,但在那之后的操作就会有问题。
QMUILog(@"UINavigationItem (QMUINavigationButton)", @"拦截了一次可能产生顶部按钮混乱的操作,navigationController is %@, topViewController is %@", navController, navController.topViewController);
QMUILog(@"UINavigationItem (QMUINavigationButton)", @"拦截了一次可能产生顶部按钮混乱的操作");
return YES;
}
}
Expand Down
3 changes: 2 additions & 1 deletion QMUIKit/QMUIComponents/QMUIImagePreviewView.m
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
#import "QMUICollectionViewPagingLayout.h"
#import "NSObject+QMUI.h"
#import "UICollectionView+QMUI.h"
#import "UIView+QMUI.h"
#import "QMUIEmptyView.h"
#import "QMUILog.h"
#import "QMUIPieProgressView.h"
Expand All @@ -36,7 +37,7 @@ - (instancetype)initWithFrame:(CGRect)frame {

- (void)layoutSubviews {
[super layoutSubviews];
self.zoomImageView.frame = CGRectApplyAffineTransform(self.contentView.bounds, self.zoomImageView.transform);
self.zoomImageView.qmui_frameApplyTransform = self.contentView.bounds;
}

@end
Expand Down
9 changes: 7 additions & 2 deletions QMUIKit/QMUIComponents/QMUIImagePreviewViewController.m
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
#import "QMUIImagePreviewViewController.h"
#import "QMUICore.h"
#import "CALayer+QMUI.h"
#import "UIView+QMUI.h"

@implementation QMUIImagePreviewViewController (UIAppearance)

Expand Down Expand Up @@ -95,7 +96,7 @@ - (void)initSubviews {

- (void)viewDidLayoutSubviews {
[super viewDidLayoutSubviews];
self.imagePreviewView.frame = CGRectApplyAffineTransform(self.view.bounds, self.imagePreviewView.transform);
self.imagePreviewView.qmui_frameApplyTransform = self.view.bounds;
}

- (void)viewWillAppear:(BOOL)animated {
Expand Down Expand Up @@ -349,6 +350,10 @@ - (void)startPreviewWithFadingAnimation:(BOOL)isFading orFromRect:(CGRect)rect {
- (void)exitPreviewByFadingAnimation:(BOOL)isFading orToRect:(CGRect)rect {

if (isFading) {
if (!self.backgroundColorTemporarily) {
// 如果是手势触发的 exit,在手势 began 时就已经设置好 backgroundColorTemporarily 了,所以这里只为那种单击或者用代码 exit 的情况
self.backgroundColorTemporarily = self.view.backgroundColor;
}
[UIView animateWithDuration:.25 delay:0.0 options:QMUIViewAnimationOptionsCurveOut animations:^{
self.view.alpha = 0;
} completion:^(BOOL finished) {
Expand Down Expand Up @@ -435,7 +440,7 @@ - (void)resetExitGesture {
self.gestureZoomImageView.transform = CGAffineTransformIdentity;
self.gestureBeganLocation = CGPointZero;
self.gestureZoomImageView = nil;
self.view.backgroundColor = self.backgroundColorTemporarily;
self.view.backgroundColor = self.backgroundColorTemporarily;// 重置回之前的遮罩背景色,因此要求每一种 exit 方式在 exit 之前都要先给 self.backgroundColorTemporarily 赋值
}

@end
12 changes: 6 additions & 6 deletions QMUIKit/QMUIComponents/QMUILogManagerViewController.m
Original file line number Diff line number Diff line change
Expand Up @@ -153,24 +153,24 @@ - (void)handleMenuItemEvent {
menuView.maximumWidth = 124;
menuView.safetyMarginsOfSuperview = UIEdgeInsetsSetRight(menuView.safetyMarginsOfSuperview, 6);
menuView.items = @[
[QMUIPopupMenuItem itemWithImage:nil title:@"开启全部" handler:^(QMUIPopupMenuView *aMenuView, QMUIPopupMenuItem *aItem) {
[QMUIPopupMenuButtonItem itemWithImage:nil title:@"开启全部" handler:^(QMUIPopupMenuButtonItem *aItem) {
for (NSString *logName in self.allNames) {
[[QMUILogger sharedInstance].logNameManager setEnabled:YES forLogName:logName];
}
[self reloadData];
[aMenuView hideWithAnimated:YES];
[aItem.menuView hideWithAnimated:YES];
}],
[QMUIPopupMenuItem itemWithImage:nil title:@"禁用全部" handler:^(QMUIPopupMenuView *aMenuView, QMUIPopupMenuItem *aItem) {
[QMUIPopupMenuButtonItem itemWithImage:nil title:@"禁用全部" handler:^(QMUIPopupMenuButtonItem *aItem) {
for (NSString *logName in self.allNames) {
[[QMUILogger sharedInstance].logNameManager setEnabled:NO forLogName:logName];
}
[self reloadData];
[aMenuView hideWithAnimated:YES];
[aItem.menuView hideWithAnimated:YES];
}],
[QMUIPopupMenuItem itemWithImage:nil title:@"清空全部" handler:^(QMUIPopupMenuView *aMenuView, QMUIPopupMenuItem *aItem) {
[QMUIPopupMenuButtonItem itemWithImage:nil title:@"清空全部" handler:^(QMUIPopupMenuButtonItem *aItem) {
[[QMUILogger sharedInstance].logNameManager removeAllNames];
[self reloadData];
[aMenuView hideWithAnimated:YES];
[aItem.menuView hideWithAnimated:YES];
}]];
[menuView layoutWithTargetView:self.navigationItem.rightBarButtonItem.qmui_view];
[menuView showWithAnimated:YES];
Expand Down
9 changes: 0 additions & 9 deletions QMUIKit/QMUIComponents/QMUIMarqueeLabel.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,15 +34,6 @@
/// 在文字滚动到左右边缘时,是否要显示一个阴影渐变遮罩,默认为 YES。
@property(nonatomic, assign) IBInspectable BOOL shouldFadeAtEdge;

/// 渐变遮罩的宽度,默认为 20。
@property(nonatomic, assign) IBInspectable CGFloat fadeWidth;

/// 渐变遮罩外边缘的颜色,请使用带 Alpha 通道的颜色
@property(nonatomic, strong) IBInspectable UIColor *fadeStartColor;

/// 渐变遮罩内边缘的颜色,一般是 fadeStartColor 的 alpha 通道为 0 的色值
@property(nonatomic, strong) IBInspectable UIColor *fadeEndColor;

/// YES 表示文字会在打开 shouldFadeAtEdge 的情况下,从左边的渐隐区域之后显示,NO 表示不管有没有打开 shouldFadeAtEdge,都会从 label 的边缘开始显示。默认为 NO。
/// @note 如果文字宽度本身就没超过 label 宽度(也即无需滚动),此时必定不会显示渐隐,则这个属性不会影响文字的显示位置。
@property(nonatomic, assign) IBInspectable BOOL textStartAfterFade;
Expand Down
107 changes: 25 additions & 82 deletions QMUIKit/QMUIComponents/QMUIMarqueeLabel.m
Original file line number Diff line number Diff line change
Expand Up @@ -16,14 +16,16 @@ @interface QMUIMarqueeLabel ()
@property(nonatomic, strong) CADisplayLink *displayLink;
@property(nonatomic, assign) CGFloat offsetX;
@property(nonatomic, assign) CGFloat textWidth;

@property(nonatomic, strong) CAGradientLayer *fadeLeftLayer;
@property(nonatomic, strong) CAGradientLayer *fadeRightLayer;
@property(nonatomic, assign) CGFloat fadeStartPercent; // 渐变开始的百分比,默认为0,不建议改
@property(nonatomic, assign) CGFloat fadeEndPercent; // 渐变结束的百分比,例如0.2,则表示 0~20% 是渐变区间

@property(nonatomic, assign) BOOL isFirstDisplay;

@property(nonatomic, strong) CAGradientLayer *fadeLayer;

/// 绘制文本时重复绘制的次数,用于实现首尾连接的滚动效果,1 表示不首尾连接,大于 1 表示首尾连接。
@property(nonatomic, assign) NSInteger textRepeatCount;

@end

@implementation QMUIMarqueeLabel
Expand All @@ -48,12 +50,11 @@ - (instancetype)initWithCoder:(NSCoder *)aDecoder {

- (void)didInitialize {
self.speed = .5;
self.fadeStartPercent = 0;
self.fadeEndPercent = .2;
self.pauseDurationWhenMoveToEdge = 2.5;
self.spacingBetweenHeadToTail = 40;
self.automaticallyValidateVisibleFrame = YES;
self.fadeWidth = 20;
self.fadeStartColor = UIColorMakeWithRGBA(255, 255, 255, 1);
self.fadeEndColor = UIColorMakeWithRGBA(255, 255, 255, 0);
self.shouldFadeAtEdge = YES;
self.textStartAfterFade = NO;

Expand Down Expand Up @@ -115,8 +116,9 @@ - (void)drawTextInRect:(CGRect)rect {
// 考虑渐变遮罩的偏移
CGFloat textOffsetXByFade = 0;
BOOL shouldTextStartAfterFade = self.shouldFadeAtEdge && self.textStartAfterFade && self.textWidth > CGRectGetWidth(self.bounds);
if (shouldTextStartAfterFade && textInitialX < self.fadeWidth) {
textOffsetXByFade = self.fadeWidth;
CGFloat fadeWidth = CGRectGetWidth(self.bounds) * .5 * MAX(0, self.fadeEndPercent - self.fadeStartPercent);
if (shouldTextStartAfterFade && textInitialX < fadeWidth) {
textOffsetXByFade = fadeWidth;
}
textInitialX += textOffsetXByFade;

Expand All @@ -130,13 +132,9 @@ - (void)drawTextInRect:(CGRect)rect {

- (void)layoutSubviews {
[super layoutSubviews];
if (self.fadeLeftLayer) {
self.fadeLeftLayer.frame = CGRectMake(0, 0, self.fadeWidth, CGRectGetHeight(self.bounds));
[self.layer qmui_bringSublayerToFront:self.fadeLeftLayer];// 显示非英文字符时,UILabel 内部会额外多出一层 layer 盖住了这里的 fadeLayer,所以要手动提到最前面
}
if (self.fadeRightLayer) {
self.fadeRightLayer.frame = CGRectMake(CGRectGetWidth(self.bounds) - self.fadeWidth, 0, self.fadeWidth, CGRectGetHeight(self.bounds));
[self.layer qmui_bringSublayerToFront:self.fadeRightLayer];// 显示非英文字符时,UILabel 内部会额外多出一层 layer 盖住了这里的 fadeLayer,所以要手动提到最前面

if (self.fadeLayer) {
self.fadeLayer.frame = self.bounds;
}
}

Expand Down Expand Up @@ -181,7 +179,8 @@ - (void)handleDisplayLink:(CADisplayLink *)displayLink {
}

- (BOOL)shouldPlayDisplayLink {
BOOL result = self.window && CGRectGetWidth(self.bounds) > 0 && self.textWidth > CGRectGetWidth(self.bounds);
CGFloat fadeWidth = CGRectGetWidth(self.bounds) * .5 * MAX(0, self.fadeEndPercent - self.fadeStartPercent);
BOOL result = self.window && CGRectGetWidth(self.bounds) > 0 && (self.textWidth + fadeWidth) > CGRectGetWidth(self.bounds);

// 如果 label.frame 在 window 可视区域之外,也视为不可见,暂停掉 displayLink
if (result && self.automaticallyValidateVisibleFrame) {
Expand All @@ -194,78 +193,22 @@ - (BOOL)shouldPlayDisplayLink {
return result;
}

- (void)setOffsetX:(CGFloat)offsetX {
_offsetX = offsetX;
[self updateFadeLayersHidden];
}

- (void)setShouldFadeAtEdge:(BOOL)shouldFadeAtEdge {
_shouldFadeAtEdge = shouldFadeAtEdge;
if (shouldFadeAtEdge) {
[self initFadeLayersIfNeeded];
}
[self updateFadeLayersHidden];
}

- (void)setFadeStartColor:(UIColor *)fadeStartColor {
_fadeStartColor = fadeStartColor;
[self updateFadeLayerColors];
}

- (void)setFadeEndColor:(UIColor *)fadeEndColor {
_fadeEndColor = fadeEndColor;
[self updateFadeLayerColors];
}

- (void)updateFadeLayerColors {
if (self.fadeLeftLayer) {
if (self.fadeStartColor && self.fadeEndColor) {
self.fadeLeftLayer.colors = @[(id)self.fadeStartColor.CGColor,
(id)self.fadeEndColor.CGColor];
} else {
self.fadeLeftLayer.colors = nil;
}
}
if (self.fadeRightLayer) {
if (self.fadeStartColor && self.fadeEndColor) {
self.fadeRightLayer.colors = @[(id)self.fadeStartColor.CGColor,
(id)self.fadeEndColor.CGColor];
} else {
self.fadeRightLayer.colors = nil;
_fadeLayer = [CAGradientLayer layer];
self.fadeLayer.locations = @[@(self.fadeStartPercent), @(self.fadeEndPercent), @(1 - self.fadeEndPercent), @(1 - self.fadeStartPercent)];
self.fadeLayer.startPoint = CGPointMake(0, .5);
self.fadeLayer.endPoint = CGPointMake(1, .5);
self.fadeLayer.colors = @[(id)UIColorMakeWithRGBA(255, 255, 255, 0).CGColor, (id)UIColorMakeWithRGBA(255, 255, 255, 1).CGColor, (id)UIColorMakeWithRGBA(255, 255, 255, 1).CGColor, (id)UIColorMakeWithRGBA(255, 255, 255, 0).CGColor];
self.layer.mask = self.fadeLayer;
} else {
if (self.layer.mask == self.fadeLayer) {
self.layer.mask = nil;
}
}
}

- (void)updateFadeLayersHidden {
if (!self.fadeLeftLayer || !self.fadeRightLayer) {
return;
}

BOOL shouldShowFadeLeftLayer = self.shouldFadeAtEdge && (self.offsetX < 0 || (self.offsetX == 0 && !self.isFirstDisplay));
self.fadeLeftLayer.hidden = !shouldShowFadeLeftLayer;

BOOL shouldShowFadeRightLayer = self.shouldFadeAtEdge && (self.textWidth > CGRectGetWidth(self.bounds) && self.offsetX != self.textWidth - CGRectGetWidth(self.bounds));
self.fadeRightLayer.hidden = !shouldShowFadeRightLayer;
}

- (void)initFadeLayersIfNeeded {
if (!self.fadeLeftLayer) {
self.fadeLeftLayer = [CAGradientLayer layer];// 请保留自带的 hidden 动画
self.fadeLeftLayer.startPoint = CGPointMake(0, .5);
self.fadeLeftLayer.endPoint = CGPointMake(1, .5);
[self.layer addSublayer:self.fadeLeftLayer];
[self setNeedsLayout];
}

if (!self.fadeRightLayer) {
self.fadeRightLayer = [CAGradientLayer layer];// 请保留自带的 hidden 动画
self.fadeRightLayer.startPoint = CGPointMake(1, .5);
self.fadeRightLayer.endPoint = CGPointMake(0, .5);
[self.layer addSublayer:self.fadeRightLayer];
[self setNeedsLayout];
}

[self updateFadeLayerColors];
[self setNeedsLayout];
}

#pragma mark - Superclass
Expand Down
Loading

0 comments on commit 5daa02d

Please sign in to comment.