修改UI
This commit is contained in:
27
Pods/JXCategoryView/Sources/Title/JXCategoryTitleCell.h
generated
Normal file
27
Pods/JXCategoryView/Sources/Title/JXCategoryTitleCell.h
generated
Normal file
@@ -0,0 +1,27 @@
|
||||
//
|
||||
// JXCategoryTitleCell.h
|
||||
// UI系列测试
|
||||
//
|
||||
// Created by jiaxin on 2018/3/15.
|
||||
// Copyright © 2018年 jiaxin. All rights reserved.
|
||||
//
|
||||
|
||||
#import "JXCategoryIndicatorCell.h"
|
||||
#import "JXCategoryViewDefines.h"
|
||||
@class JXCategoryTitleCellModel;
|
||||
|
||||
@interface JXCategoryTitleCell : JXCategoryIndicatorCell
|
||||
|
||||
@property (nonatomic, strong) UILabel *titleLabel;
|
||||
@property (nonatomic, strong) UILabel *maskTitleLabel;
|
||||
@property (nonatomic, strong) NSLayoutConstraint *titleLabelCenterX;
|
||||
@property (nonatomic, strong) NSLayoutConstraint *titleLabelCenterY;
|
||||
@property (nonatomic, strong) NSLayoutConstraint *maskTitleLabelCenterX;
|
||||
|
||||
- (JXCategoryCellSelectedAnimationBlock)preferredTitleZoomAnimationBlock:(JXCategoryTitleCellModel *)cellModel baseScale:(CGFloat)baseScale;
|
||||
|
||||
- (JXCategoryCellSelectedAnimationBlock)preferredTitleStrokeWidthAnimationBlock:(JXCategoryTitleCellModel *)cellModel attributedString:(NSMutableAttributedString *)attributedString;
|
||||
|
||||
- (JXCategoryCellSelectedAnimationBlock)preferredTitleColorAnimationBlock:(JXCategoryTitleCellModel *)cellModel;
|
||||
|
||||
@end
|
||||
240
Pods/JXCategoryView/Sources/Title/JXCategoryTitleCell.m
generated
Normal file
240
Pods/JXCategoryView/Sources/Title/JXCategoryTitleCell.m
generated
Normal file
@@ -0,0 +1,240 @@
|
||||
//
|
||||
// JXCategoryTitleCell.m
|
||||
// UI系列测试
|
||||
//
|
||||
// Created by jiaxin on 2018/3/15.
|
||||
// Copyright © 2018年 jiaxin. All rights reserved.
|
||||
//
|
||||
|
||||
#import "JXCategoryTitleCell.h"
|
||||
#import "JXCategoryTitleCellModel.h"
|
||||
#import "JXCategoryFactory.h"
|
||||
#import "RTLManager.h"
|
||||
|
||||
@interface JXCategoryTitleCell ()
|
||||
@property (nonatomic, strong) CALayer *titleMaskLayer;
|
||||
@property (nonatomic, strong) CALayer *maskTitleMaskLayer;
|
||||
@property (nonatomic, strong) NSLayoutConstraint *maskTitleLabelCenterY;
|
||||
@end
|
||||
|
||||
@implementation JXCategoryTitleCell
|
||||
|
||||
- (void)initializeViews {
|
||||
[super initializeViews];
|
||||
|
||||
self.isAccessibilityElement = true;
|
||||
self.accessibilityTraits = UIAccessibilityTraitButton;
|
||||
_titleLabel = [[UILabel alloc] init];
|
||||
self.titleLabel.clipsToBounds = YES;
|
||||
self.titleLabel.textAlignment = NSTextAlignmentCenter;
|
||||
self.titleLabel.translatesAutoresizingMaskIntoConstraints = NO;
|
||||
[self.contentView addSubview:self.titleLabel];
|
||||
|
||||
self.titleLabelCenterX = [self.titleLabel.centerXAnchor constraintEqualToAnchor:self.contentView.centerXAnchor constant:0];
|
||||
self.titleLabelCenterY = [self.titleLabel.centerYAnchor constraintEqualToAnchor:self.contentView.centerYAnchor constant:0];
|
||||
|
||||
_titleMaskLayer = [CALayer layer];
|
||||
self.titleMaskLayer.backgroundColor = [UIColor redColor].CGColor;
|
||||
|
||||
_maskTitleLabel = [[UILabel alloc] init];
|
||||
self.maskTitleLabel.hidden = YES;
|
||||
self.maskTitleLabel.translatesAutoresizingMaskIntoConstraints = NO;
|
||||
self.maskTitleLabel.textAlignment = NSTextAlignmentCenter;
|
||||
[self.contentView addSubview:self.maskTitleLabel];
|
||||
|
||||
self.maskTitleLabelCenterX = [self.maskTitleLabel.centerXAnchor constraintEqualToAnchor:self.contentView.centerXAnchor];
|
||||
self.maskTitleLabelCenterY = [self.maskTitleLabel.centerYAnchor constraintEqualToAnchor:self.contentView.centerYAnchor];
|
||||
|
||||
_maskTitleMaskLayer = [CALayer layer];
|
||||
self.maskTitleMaskLayer.backgroundColor = [UIColor redColor].CGColor;
|
||||
self.maskTitleLabel.layer.mask = self.maskTitleMaskLayer;
|
||||
|
||||
[NSLayoutConstraint activateConstraints:@[self.titleLabelCenterX, self.titleLabelCenterY, self.maskTitleLabelCenterX, self.maskTitleLabelCenterY]];
|
||||
}
|
||||
|
||||
- (void)layoutSubviews {
|
||||
[super layoutSubviews];
|
||||
|
||||
JXCategoryTitleCellModel *myCellModel = (JXCategoryTitleCellModel *)self.cellModel;
|
||||
switch (myCellModel.titleLabelAnchorPointStyle) {
|
||||
case JXCategoryTitleLabelAnchorPointStyleCenter: {
|
||||
self.titleLabel.layer.anchorPoint = CGPointMake(0.5, 0.5);
|
||||
self.maskTitleLabel.layer.anchorPoint = CGPointMake(0.5, 0.5);
|
||||
self.titleLabelCenterY.constant = 0 + myCellModel.titleLabelVerticalOffset;
|
||||
break;
|
||||
}
|
||||
case JXCategoryTitleLabelAnchorPointStyleTop: {
|
||||
self.titleLabel.layer.anchorPoint = CGPointMake(0.5, 0);
|
||||
self.maskTitleLabel.layer.anchorPoint = CGPointMake(0.5, 0);
|
||||
CGFloat percent = (myCellModel.titleLabelCurrentZoomScale - myCellModel.titleLabelNormalZoomScale)/(myCellModel.titleLabelSelectedZoomScale - myCellModel.titleLabelNormalZoomScale);
|
||||
self.titleLabelCenterY.constant = -myCellModel.titleHeight/2 - myCellModel.titleLabelVerticalOffset - myCellModel.titleLabelZoomSelectedVerticalOffset*percent;
|
||||
break;
|
||||
}
|
||||
case JXCategoryTitleLabelAnchorPointStyleBottom: {
|
||||
self.titleLabel.layer.anchorPoint = CGPointMake(0.5, 1);
|
||||
self.maskTitleLabel.layer.anchorPoint = CGPointMake(0.5, 1);
|
||||
CGFloat percent = (myCellModel.titleLabelCurrentZoomScale - myCellModel.titleLabelNormalZoomScale)/(myCellModel.titleLabelSelectedZoomScale - myCellModel.titleLabelNormalZoomScale);
|
||||
self.titleLabelCenterY.constant = myCellModel.titleHeight/2 + myCellModel.titleLabelVerticalOffset + myCellModel.titleLabelZoomSelectedVerticalOffset*percent;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
- (void)reloadData:(JXCategoryBaseCellModel *)cellModel {
|
||||
[super reloadData:cellModel];
|
||||
|
||||
JXCategoryTitleCellModel *myCellModel = (JXCategoryTitleCellModel *)cellModel;
|
||||
self.accessibilityLabel = myCellModel.title;
|
||||
self.titleLabel.numberOfLines = myCellModel.titleNumberOfLines;
|
||||
self.maskTitleLabel.numberOfLines = myCellModel.titleNumberOfLines;
|
||||
|
||||
if (myCellModel.isTitleLabelZoomEnabled) {
|
||||
//先把font设置为缩放的最大值,再缩小到最小值,最后根据当前的titleLabelZoomScale值,进行缩放更新。这样就能避免transform从小到大时字体模糊
|
||||
UIFont *maxScaleFont = [UIFont fontWithDescriptor:myCellModel.titleFont.fontDescriptor size:myCellModel.titleFont.pointSize*myCellModel.titleLabelSelectedZoomScale];
|
||||
CGFloat baseScale = myCellModel.titleFont.lineHeight/maxScaleFont.lineHeight;
|
||||
if (myCellModel.isSelectedAnimationEnabled && [self checkCanStartSelectedAnimation:myCellModel]) {
|
||||
JXCategoryCellSelectedAnimationBlock block = [self preferredTitleZoomAnimationBlock:myCellModel baseScale:baseScale];
|
||||
[self addSelectedAnimationBlock:block];
|
||||
} else {
|
||||
self.titleLabel.font = maxScaleFont;
|
||||
self.maskTitleLabel.font = maxScaleFont;
|
||||
CGAffineTransform currentTransform = CGAffineTransformMakeScale(baseScale*myCellModel.titleLabelCurrentZoomScale, baseScale*myCellModel.titleLabelCurrentZoomScale);
|
||||
self.titleLabel.transform = currentTransform;
|
||||
self.maskTitleLabel.transform = currentTransform;
|
||||
}
|
||||
} else {
|
||||
if (myCellModel.isSelected) {
|
||||
self.titleLabel.font = myCellModel.titleSelectedFont;
|
||||
self.maskTitleLabel.font = myCellModel.titleSelectedFont;
|
||||
} else {
|
||||
self.titleLabel.font = myCellModel.titleFont;
|
||||
self.maskTitleLabel.font = myCellModel.titleFont;
|
||||
}
|
||||
}
|
||||
|
||||
NSString *titleString = myCellModel.title ? myCellModel.title : @"";
|
||||
NSMutableAttributedString *attributedString = [[NSMutableAttributedString alloc] initWithString:titleString];
|
||||
if (myCellModel.isTitleLabelStrokeWidthEnabled) {
|
||||
if (myCellModel.isSelectedAnimationEnabled && [self checkCanStartSelectedAnimation:myCellModel]) {
|
||||
JXCategoryCellSelectedAnimationBlock block = [self preferredTitleStrokeWidthAnimationBlock:myCellModel attributedString:attributedString];
|
||||
[self addSelectedAnimationBlock:block];
|
||||
} else {
|
||||
[attributedString addAttribute:NSStrokeWidthAttributeName value:@(myCellModel.titleLabelCurrentStrokeWidth) range:NSMakeRange(0, titleString.length)];
|
||||
self.titleLabel.attributedText = attributedString;
|
||||
self.maskTitleLabel.attributedText = attributedString;
|
||||
}
|
||||
} else {
|
||||
self.titleLabel.attributedText = attributedString;
|
||||
self.maskTitleLabel.attributedText = attributedString;
|
||||
}
|
||||
|
||||
if (myCellModel.isTitleLabelMaskEnabled) {
|
||||
self.maskTitleLabel.hidden = NO;
|
||||
self.titleLabel.textColor = myCellModel.titleNormalColor;
|
||||
self.maskTitleLabel.textColor = myCellModel.titleSelectedColor;
|
||||
[self.contentView setNeedsLayout];
|
||||
[self.contentView layoutIfNeeded];
|
||||
|
||||
CGRect topMaskframe = myCellModel.backgroundViewMaskFrame;
|
||||
//将相对于cell的backgroundViewMaskFrame转换为相对于maskTitleLabel
|
||||
//使用self.bounds.size.width而不是self.contentView.bounds.size.width。因为某些情况下,会出现self.bounds是正确的,而self.contentView.bounds还是重用前的状态。
|
||||
topMaskframe.origin.y = 0;
|
||||
CGRect bottomMaskFrame = topMaskframe;
|
||||
CGFloat maskStartX = 0;
|
||||
if (self.maskTitleLabel.bounds.size.width >= self.bounds.size.width) {
|
||||
topMaskframe.origin.x -= (self.maskTitleLabel.bounds.size.width -self.bounds.size.width)/2;
|
||||
bottomMaskFrame.size.width = self.maskTitleLabel.bounds.size.width;
|
||||
maskStartX = -(self.maskTitleLabel.bounds.size.width -self.bounds.size.width)/2;
|
||||
} else {
|
||||
bottomMaskFrame.size.width = self.bounds.size.width;
|
||||
topMaskframe.origin.x -= (self.bounds.size.width -self.maskTitleLabel.bounds.size.width)/2;
|
||||
maskStartX = 0;
|
||||
}
|
||||
bottomMaskFrame.origin.x = topMaskframe.origin.x;
|
||||
if (topMaskframe.origin.x > maskStartX) {
|
||||
bottomMaskFrame.origin.x = topMaskframe.origin.x - bottomMaskFrame.size.width;
|
||||
} else {
|
||||
bottomMaskFrame.origin.x = CGRectGetMaxX(topMaskframe);
|
||||
}
|
||||
|
||||
// 适配RTL布局(镜像x值)
|
||||
if ([RTLManager supportRTL]) {
|
||||
topMaskframe.origin.x = self.maskTitleMaskLayer.superlayer.frame.size.width - CGRectGetMaxX(topMaskframe);
|
||||
bottomMaskFrame.origin.x = self.titleMaskLayer.superlayer.frame.size.width - CGRectGetMaxX(bottomMaskFrame);
|
||||
}
|
||||
|
||||
[CATransaction begin];
|
||||
[CATransaction setDisableActions:YES];
|
||||
if (topMaskframe.size.width > 0 && CGRectIntersectsRect(topMaskframe, self.maskTitleLabel.frame)) {
|
||||
self.titleLabel.layer.mask = self.titleMaskLayer;
|
||||
self.maskTitleMaskLayer.frame = topMaskframe;
|
||||
self.titleMaskLayer.frame = bottomMaskFrame;
|
||||
} else {
|
||||
self.maskTitleMaskLayer.frame = topMaskframe;
|
||||
self.titleLabel.layer.mask = nil;
|
||||
}
|
||||
[CATransaction commit];
|
||||
} else {
|
||||
self.maskTitleLabel.hidden = YES;
|
||||
self.titleLabel.layer.mask = nil;
|
||||
if (myCellModel.isSelectedAnimationEnabled && [self checkCanStartSelectedAnimation:myCellModel]) {
|
||||
JXCategoryCellSelectedAnimationBlock block = [self preferredTitleColorAnimationBlock:myCellModel];
|
||||
[self addSelectedAnimationBlock:block];
|
||||
} else {
|
||||
self.titleLabel.textColor = myCellModel.titleCurrentColor;
|
||||
}
|
||||
}
|
||||
|
||||
[self startSelectedAnimationIfNeeded:myCellModel];
|
||||
}
|
||||
|
||||
#pragma mark - Public
|
||||
|
||||
- (JXCategoryCellSelectedAnimationBlock)preferredTitleZoomAnimationBlock:(JXCategoryTitleCellModel *)cellModel baseScale:(CGFloat)baseScale {
|
||||
__weak typeof(self) weakSelf = self;
|
||||
return ^(CGFloat percent) {
|
||||
if (cellModel.isSelected) {
|
||||
//将要选中,scale从小到大插值渐变
|
||||
cellModel.titleLabelCurrentZoomScale = [JXCategoryFactory interpolationFrom:cellModel.titleLabelNormalZoomScale to:cellModel.titleLabelSelectedZoomScale percent:percent];
|
||||
} else {
|
||||
//将要取消选中,scale从大到小插值渐变
|
||||
cellModel.titleLabelCurrentZoomScale = [JXCategoryFactory interpolationFrom:cellModel.titleLabelSelectedZoomScale to:cellModel.titleLabelNormalZoomScale percent:percent];
|
||||
}
|
||||
CGAffineTransform currentTransform = CGAffineTransformMakeScale(baseScale*cellModel.titleLabelCurrentZoomScale, baseScale*cellModel.titleLabelCurrentZoomScale);
|
||||
weakSelf.titleLabel.transform = currentTransform;
|
||||
weakSelf.maskTitleLabel.transform = currentTransform;
|
||||
};
|
||||
}
|
||||
|
||||
- (JXCategoryCellSelectedAnimationBlock)preferredTitleStrokeWidthAnimationBlock:(JXCategoryTitleCellModel *)cellModel attributedString:(NSMutableAttributedString *)attributedString {
|
||||
__weak typeof(self) weakSelf = self;
|
||||
return ^(CGFloat percent) {
|
||||
if (cellModel.isSelected) {
|
||||
//将要选中,StrokeWidth从小到大插值渐变
|
||||
cellModel.titleLabelCurrentStrokeWidth = [JXCategoryFactory interpolationFrom:cellModel.titleLabelNormalStrokeWidth to:cellModel.titleLabelSelectedStrokeWidth percent:percent];
|
||||
} else {
|
||||
//将要取消选中,StrokeWidth从大到小插值渐变
|
||||
cellModel.titleLabelCurrentStrokeWidth = [JXCategoryFactory interpolationFrom:cellModel.titleLabelSelectedStrokeWidth to:cellModel.titleLabelNormalStrokeWidth percent:percent];
|
||||
}
|
||||
[attributedString addAttribute:NSStrokeWidthAttributeName value:@(cellModel.titleLabelCurrentStrokeWidth) range:NSMakeRange(0, attributedString.string.length)];
|
||||
weakSelf.titleLabel.attributedText = attributedString;
|
||||
weakSelf.maskTitleLabel.attributedText = attributedString;
|
||||
};
|
||||
}
|
||||
|
||||
- (JXCategoryCellSelectedAnimationBlock)preferredTitleColorAnimationBlock:(JXCategoryTitleCellModel *)cellModel {
|
||||
__weak typeof(self) weakSelf = self;
|
||||
return ^(CGFloat percent) {
|
||||
if (cellModel.isSelected) {
|
||||
//将要选中,textColor从titleNormalColor到titleSelectedColor插值渐变
|
||||
cellModel.titleCurrentColor = [JXCategoryFactory interpolationColorFrom:cellModel.titleNormalColor to:cellModel.titleSelectedColor percent:percent];
|
||||
} else {
|
||||
//将要取消选中,textColor从titleSelectedColor到titleNormalColor插值渐变
|
||||
cellModel.titleCurrentColor = [JXCategoryFactory interpolationColorFrom:cellModel.titleSelectedColor to:cellModel.titleNormalColor percent:percent];
|
||||
}
|
||||
weakSelf.titleLabel.textColor = cellModel.titleCurrentColor;
|
||||
};
|
||||
}
|
||||
|
||||
@end
|
||||
44
Pods/JXCategoryView/Sources/Title/JXCategoryTitleCellModel.h
generated
Normal file
44
Pods/JXCategoryView/Sources/Title/JXCategoryTitleCellModel.h
generated
Normal file
@@ -0,0 +1,44 @@
|
||||
//
|
||||
// JXCategoryTitleCellModel.h
|
||||
// UI系列测试
|
||||
//
|
||||
// Created by jiaxin on 2018/3/15.
|
||||
// Copyright © 2018年 jiaxin. All rights reserved.
|
||||
//
|
||||
|
||||
#import "JXCategoryIndicatorCellModel.h"
|
||||
#import <UIKit/UIKit.h>
|
||||
#import "JXCategoryViewDefines.h"
|
||||
|
||||
@interface JXCategoryTitleCellModel : JXCategoryIndicatorCellModel
|
||||
|
||||
@property (nonatomic, copy) NSString *title;
|
||||
|
||||
@property (nonatomic, assign, readonly) CGFloat titleHeight;
|
||||
|
||||
@property (nonatomic, assign) NSInteger titleNumberOfLines;
|
||||
@property (nonatomic, assign) CGFloat titleLabelVerticalOffset;
|
||||
|
||||
@property (nonatomic, strong) UIColor *titleNormalColor;
|
||||
@property (nonatomic, strong) UIColor *titleCurrentColor;
|
||||
@property (nonatomic, strong) UIColor *titleSelectedColor;
|
||||
|
||||
@property (nonatomic, strong) UIFont *titleFont;
|
||||
@property (nonatomic, strong) UIFont *titleSelectedFont;
|
||||
|
||||
@property (nonatomic, assign, getter=isTitleLabelMaskEnabled) BOOL titleLabelMaskEnabled;
|
||||
@property (nonatomic, assign, getter=isTitleLabelZoomEnabled) BOOL titleLabelZoomEnabled;
|
||||
|
||||
@property (nonatomic, assign) CGFloat titleLabelNormalZoomScale;
|
||||
@property (nonatomic, assign) CGFloat titleLabelCurrentZoomScale;
|
||||
@property (nonatomic, assign) CGFloat titleLabelSelectedZoomScale;
|
||||
@property (nonatomic, assign) CGFloat titleLabelZoomSelectedVerticalOffset;
|
||||
|
||||
@property (nonatomic, assign, getter=isTitleLabelStrokeWidthEnabled) BOOL titleLabelStrokeWidthEnabled;
|
||||
@property (nonatomic, assign) CGFloat titleLabelNormalStrokeWidth;
|
||||
@property (nonatomic, assign) CGFloat titleLabelCurrentStrokeWidth;
|
||||
@property (nonatomic, assign) CGFloat titleLabelSelectedStrokeWidth;
|
||||
|
||||
@property (nonatomic, assign) JXCategoryTitleLabelAnchorPointStyle titleLabelAnchorPointStyle;
|
||||
|
||||
@end
|
||||
31
Pods/JXCategoryView/Sources/Title/JXCategoryTitleCellModel.m
generated
Normal file
31
Pods/JXCategoryView/Sources/Title/JXCategoryTitleCellModel.m
generated
Normal file
@@ -0,0 +1,31 @@
|
||||
//
|
||||
// JXCategoryTitleCellModel.m
|
||||
// UI系列测试
|
||||
//
|
||||
// Created by jiaxin on 2018/3/15.
|
||||
// Copyright © 2018年 jiaxin. All rights reserved.
|
||||
//
|
||||
|
||||
#import "JXCategoryTitleCellModel.h"
|
||||
|
||||
@implementation JXCategoryTitleCellModel
|
||||
|
||||
- (void)setTitle:(NSString *)title {
|
||||
_title = title;
|
||||
|
||||
[self updateNumberSizeWidthIfNeeded];
|
||||
}
|
||||
|
||||
- (void)setTitleFont:(UIFont *)titleFont {
|
||||
_titleFont = titleFont;
|
||||
|
||||
[self updateNumberSizeWidthIfNeeded];
|
||||
}
|
||||
|
||||
- (void)updateNumberSizeWidthIfNeeded {
|
||||
if (self.titleFont) {
|
||||
_titleHeight = [self.title boundingRectWithSize:CGSizeMake(CGFLOAT_MAX, CGFLOAT_MAX) options:NSStringDrawingUsesLineFragmentOrigin attributes:@{NSFontAttributeName : self.titleFont} context:nil].size.height;
|
||||
}
|
||||
}
|
||||
|
||||
@end
|
||||
63
Pods/JXCategoryView/Sources/Title/JXCategoryTitleView.h
generated
Normal file
63
Pods/JXCategoryView/Sources/Title/JXCategoryTitleView.h
generated
Normal file
@@ -0,0 +1,63 @@
|
||||
//
|
||||
// JXCategoryView.h
|
||||
// UI系列测试
|
||||
//
|
||||
// Created by jiaxin on 2018/3/15.
|
||||
// Copyright © 2018年 jiaxin. All rights reserved.
|
||||
//
|
||||
|
||||
#import "JXCategoryIndicatorView.h"
|
||||
#import "JXCategoryTitleCell.h"
|
||||
#import "JXCategoryTitleCellModel.h"
|
||||
#import "JXCategoryViewDefines.h"
|
||||
|
||||
@class JXCategoryTitleView;
|
||||
|
||||
@protocol JXCategoryTitleViewDataSource <NSObject>
|
||||
@optional
|
||||
// 如果将JXCategoryTitleView嵌套进UITableView的cell,每次重用的时候,JXCategoryTitleView进行reloadData时,会重新计算所有的title宽度。所以该应用场景,需要UITableView的cellModel缓存titles的文字宽度,再通过该代理方法返回给JXCategoryTitleView。
|
||||
// 如果实现了该方法就以该方法返回的宽度为准,不触发内部默认的文字宽度计算。
|
||||
- (CGFloat)categoryTitleView:(JXCategoryTitleView *)titleView widthForTitle:(NSString *)title;
|
||||
@end
|
||||
|
||||
|
||||
@interface JXCategoryTitleView : JXCategoryIndicatorView
|
||||
|
||||
@property (nonatomic, weak) id<JXCategoryTitleViewDataSource> titleDataSource;
|
||||
|
||||
@property (nonatomic, strong) NSArray <NSString *>*titles;
|
||||
|
||||
@property (nonatomic, assign) NSInteger titleNumberOfLines; //默认:1
|
||||
|
||||
@property (nonatomic, strong) UIColor *titleColor; //默认:[UIColor blackColor]
|
||||
|
||||
@property (nonatomic, strong) UIColor *titleSelectedColor; //默认:[UIColor redColor]
|
||||
|
||||
@property (nonatomic, strong) UIFont *titleFont; //默认:[UIFont systemFontOfSize:15]
|
||||
|
||||
@property (nonatomic, strong) UIFont *titleSelectedFont; //文字被选中的字体。默认:与titleFont一样
|
||||
|
||||
@property (nonatomic, assign, getter=isTitleColorGradientEnabled) BOOL titleColorGradientEnabled; //默认:NO,title的颜色是否渐变过渡
|
||||
|
||||
@property (nonatomic, assign, getter=isTitleLabelMaskEnabled) BOOL titleLabelMaskEnabled; //默认:NO,titleLabel是否遮罩过滤。
|
||||
|
||||
//----------------------titleLabelZoomEnabled-----------------------//
|
||||
@property (nonatomic, assign, getter=isTitleLabelZoomEnabled) BOOL titleLabelZoomEnabled; //默认为NO。为YES时titleSelectedFont失效,以titleFont为准。
|
||||
|
||||
@property (nonatomic, assign, getter=isTitleLabelZoomScrollGradientEnabled) BOOL titleLabelZoomScrollGradientEnabled; //手势滚动中,是否需要更新状态。默认为YES
|
||||
|
||||
@property (nonatomic, assign) CGFloat titleLabelZoomScale; //默认1.2,titleLabelZoomEnabled为YES才生效。是对字号的缩放,比如titleFont的pointSize为10,放大之后字号就是10*1.2=12。
|
||||
|
||||
@property (nonatomic, assign) CGFloat titleLabelZoomSelectedVerticalOffset; //titleLabelZoomEnabled设置为YES,会对titleLabel进行transform缩放,当titleLabelZoomScale过大时(比如设置为2),选中的文本被放大之后底部会有很大的空白,从视觉上看就跟其他未选中的文本不在一个水平线上。这个时候就可以用这个值进行调整。
|
||||
|
||||
//----------------------titleLabelStrokeWidth-----------------------//
|
||||
@property (nonatomic, assign, getter=isTitleLabelStrokeWidthEnabled) BOOL titleLabelStrokeWidthEnabled; //默认:NO
|
||||
|
||||
@property (nonatomic, assign) CGFloat titleLabelSelectedStrokeWidth; //默认:-3,用于控制字体的粗细(底层通过NSStrokeWidthAttributeName实现)。使用该属性,务必让titleFont和titleSelectedFont设置为一样的!!!
|
||||
|
||||
//----------------------titleLabel缩放中心位置-----------------------//
|
||||
@property (nonatomic, assign) CGFloat titleLabelVerticalOffset; //titleLabel锚点垂直方向的位置偏移,数值越大越偏离中心,默认为:0
|
||||
|
||||
@property (nonatomic, assign) JXCategoryTitleLabelAnchorPointStyle titleLabelAnchorPointStyle; //titleLabel锚点位置,用于调整titleLabel缩放时的基准位置。默认为:JXCategoryTitleLabelAnchorPointStyleCenter
|
||||
|
||||
@end
|
||||
164
Pods/JXCategoryView/Sources/Title/JXCategoryTitleView.m
generated
Normal file
164
Pods/JXCategoryView/Sources/Title/JXCategoryTitleView.m
generated
Normal file
@@ -0,0 +1,164 @@
|
||||
//
|
||||
// JXCategoryView.m
|
||||
// UI系列测试
|
||||
//
|
||||
// Created by jiaxin on 2018/3/15.
|
||||
// Copyright © 2018年 jiaxin. All rights reserved.
|
||||
//
|
||||
|
||||
#import "JXCategoryTitleView.h"
|
||||
#import "JXCategoryFactory.h"
|
||||
|
||||
@implementation JXCategoryTitleView
|
||||
|
||||
- (void)initializeData {
|
||||
[super initializeData];
|
||||
|
||||
_titleNumberOfLines = 1;
|
||||
_titleLabelZoomEnabled = NO;
|
||||
_titleLabelZoomScale = 1.2;
|
||||
_titleColor = [UIColor blackColor];
|
||||
_titleSelectedColor = [UIColor redColor];
|
||||
_titleFont = [UIFont systemFontOfSize:15];
|
||||
_titleColorGradientEnabled = NO;
|
||||
_titleLabelMaskEnabled = NO;
|
||||
_titleLabelZoomScrollGradientEnabled = YES;
|
||||
_titleLabelStrokeWidthEnabled = NO;
|
||||
_titleLabelSelectedStrokeWidth = -3;
|
||||
_titleLabelVerticalOffset = 0;
|
||||
_titleLabelAnchorPointStyle = JXCategoryTitleLabelAnchorPointStyleCenter;
|
||||
}
|
||||
|
||||
- (UIFont *)titleSelectedFont {
|
||||
if (_titleSelectedFont) {
|
||||
return _titleSelectedFont;
|
||||
}
|
||||
return self.titleFont;
|
||||
}
|
||||
|
||||
#pragma mark - Override
|
||||
|
||||
- (Class)preferredCellClass {
|
||||
return [JXCategoryTitleCell class];
|
||||
}
|
||||
|
||||
- (void)refreshDataSource {
|
||||
NSMutableArray *tempArray = [NSMutableArray arrayWithCapacity:self.titles.count];
|
||||
for (int i = 0; i < self.titles.count; i++) {
|
||||
JXCategoryTitleCellModel *cellModel = [[JXCategoryTitleCellModel alloc] init];
|
||||
[tempArray addObject:cellModel];
|
||||
}
|
||||
self.dataSource = [NSArray arrayWithArray:tempArray];
|
||||
}
|
||||
|
||||
- (void)refreshSelectedCellModel:(JXCategoryBaseCellModel *)selectedCellModel unselectedCellModel:(JXCategoryBaseCellModel *)unselectedCellModel {
|
||||
[super refreshSelectedCellModel:selectedCellModel unselectedCellModel:unselectedCellModel];
|
||||
|
||||
JXCategoryTitleCellModel *myUnselectedCellModel = (JXCategoryTitleCellModel *)unselectedCellModel;
|
||||
JXCategoryTitleCellModel *myselectedCellModel = (JXCategoryTitleCellModel *)selectedCellModel;
|
||||
if (self.isSelectedAnimationEnabled && (selectedCellModel.selectedType == JXCategoryCellSelectedTypeClick || selectedCellModel.selectedType == JXCategoryCellSelectedTypeCode)) {
|
||||
//开启了动画过渡,且cell在屏幕内,current的属性值会在cell里面进行动画插值更新
|
||||
//1、当unselectedCell在屏幕外的时候,还是需要在这里更新值
|
||||
//2、当selectedCell在屏幕外的时候,还是需要在这里更新值(比如调用selectItemAtIndex方法选中的时候)
|
||||
BOOL isUnselectedCellVisible = NO;
|
||||
BOOL isSelectedCellVisible = NO;
|
||||
NSArray *indexPaths = [self.collectionView indexPathsForVisibleItems];
|
||||
for (NSIndexPath *indexPath in indexPaths) {
|
||||
if (indexPath.item == myUnselectedCellModel.index) {
|
||||
isUnselectedCellVisible = YES;
|
||||
continue;
|
||||
} else if (indexPath.item == myselectedCellModel.index) {
|
||||
isSelectedCellVisible = YES;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if (!isUnselectedCellVisible) {
|
||||
//但是当unselectedCell在屏幕外时,不会在cell里面通过动画插值更新,在这里直接更新
|
||||
myUnselectedCellModel.titleCurrentColor = myUnselectedCellModel.titleNormalColor;
|
||||
myUnselectedCellModel.titleLabelCurrentZoomScale = myUnselectedCellModel.titleLabelNormalZoomScale;
|
||||
myUnselectedCellModel.titleLabelCurrentStrokeWidth = myUnselectedCellModel.titleLabelNormalStrokeWidth;
|
||||
}
|
||||
if (!isSelectedCellVisible) {
|
||||
//但是当selectedCell在屏幕外时,不会在cell里面通过动画插值更新,在这里直接更新
|
||||
myselectedCellModel.titleCurrentColor = myselectedCellModel.titleSelectedColor;
|
||||
myselectedCellModel.titleLabelCurrentZoomScale = myselectedCellModel.titleLabelSelectedZoomScale;
|
||||
myselectedCellModel.titleLabelCurrentStrokeWidth = myselectedCellModel.titleLabelSelectedStrokeWidth;
|
||||
}
|
||||
} else {
|
||||
//没有开启动画,可以直接更新属性
|
||||
myselectedCellModel.titleCurrentColor = myselectedCellModel.titleSelectedColor;
|
||||
myselectedCellModel.titleLabelCurrentZoomScale = myselectedCellModel.titleLabelSelectedZoomScale;
|
||||
myselectedCellModel.titleLabelCurrentStrokeWidth = myselectedCellModel.titleLabelSelectedStrokeWidth;
|
||||
|
||||
myUnselectedCellModel.titleCurrentColor = myUnselectedCellModel.titleNormalColor;
|
||||
myUnselectedCellModel.titleLabelCurrentZoomScale = myUnselectedCellModel.titleLabelNormalZoomScale;
|
||||
myUnselectedCellModel.titleLabelCurrentStrokeWidth = myUnselectedCellModel.titleLabelNormalStrokeWidth;
|
||||
}
|
||||
}
|
||||
|
||||
- (void)refreshLeftCellModel:(JXCategoryBaseCellModel *)leftCellModel rightCellModel:(JXCategoryBaseCellModel *)rightCellModel ratio:(CGFloat)ratio {
|
||||
[super refreshLeftCellModel:leftCellModel rightCellModel:rightCellModel ratio:ratio];
|
||||
|
||||
JXCategoryTitleCellModel *leftModel = (JXCategoryTitleCellModel *)leftCellModel;
|
||||
JXCategoryTitleCellModel *rightModel = (JXCategoryTitleCellModel *)rightCellModel;
|
||||
|
||||
if (self.isTitleLabelZoomEnabled && self.isTitleLabelZoomScrollGradientEnabled) {
|
||||
leftModel.titleLabelCurrentZoomScale = [JXCategoryFactory interpolationFrom:self.titleLabelZoomScale to:1.0 percent:ratio];
|
||||
rightModel.titleLabelCurrentZoomScale = [JXCategoryFactory interpolationFrom:1.0 to:self.titleLabelZoomScale percent:ratio];
|
||||
}
|
||||
|
||||
if (self.isTitleLabelStrokeWidthEnabled) {
|
||||
leftModel.titleLabelCurrentStrokeWidth = [JXCategoryFactory interpolationFrom:leftModel.titleLabelSelectedStrokeWidth to:leftModel.titleLabelNormalStrokeWidth percent:ratio];
|
||||
rightModel.titleLabelCurrentStrokeWidth = [JXCategoryFactory interpolationFrom:rightModel.titleLabelNormalStrokeWidth to:rightModel.titleLabelSelectedStrokeWidth percent:ratio];
|
||||
}
|
||||
|
||||
if (self.isTitleColorGradientEnabled) {
|
||||
leftModel.titleCurrentColor = [JXCategoryFactory interpolationColorFrom:self.titleSelectedColor to:self.titleColor percent:ratio];
|
||||
rightModel.titleCurrentColor = [JXCategoryFactory interpolationColorFrom:self.titleColor to:self.titleSelectedColor percent:ratio];
|
||||
}
|
||||
}
|
||||
|
||||
- (CGFloat)preferredCellWidthAtIndex:(NSInteger)index {
|
||||
if (self.cellWidth == JXCategoryViewAutomaticDimension) {
|
||||
if (self.titleDataSource && [self.titleDataSource respondsToSelector:@selector(categoryTitleView:widthForTitle:)]) {
|
||||
return [self.titleDataSource categoryTitleView:self widthForTitle:self.titles[index]];
|
||||
} else {
|
||||
return ceilf([self.titles[index] boundingRectWithSize:CGSizeMake(MAXFLOAT, self.bounds.size.height) options:NSStringDrawingUsesLineFragmentOrigin|NSStringDrawingUsesFontLeading attributes:@{NSFontAttributeName : self.titleFont} context:nil].size.width);
|
||||
}
|
||||
} else {
|
||||
return self.cellWidth;
|
||||
}
|
||||
}
|
||||
|
||||
- (void)refreshCellModel:(JXCategoryBaseCellModel *)cellModel index:(NSInteger)index {
|
||||
[super refreshCellModel:cellModel index:index];
|
||||
|
||||
JXCategoryTitleCellModel *model = (JXCategoryTitleCellModel *)cellModel;
|
||||
model.title = self.titles[index];
|
||||
model.titleNumberOfLines = self.titleNumberOfLines;
|
||||
model.titleFont = self.titleFont;
|
||||
model.titleSelectedFont = self.titleSelectedFont;
|
||||
model.titleNormalColor = self.titleColor;
|
||||
model.titleSelectedColor = self.titleSelectedColor;
|
||||
model.titleLabelMaskEnabled = self.isTitleLabelMaskEnabled;
|
||||
model.titleLabelZoomEnabled = self.isTitleLabelZoomEnabled;
|
||||
model.titleLabelNormalZoomScale = 1;
|
||||
model.titleLabelZoomSelectedVerticalOffset = self.titleLabelZoomSelectedVerticalOffset;
|
||||
model.titleLabelSelectedZoomScale = self.titleLabelZoomScale;
|
||||
model.titleLabelStrokeWidthEnabled = self.isTitleLabelStrokeWidthEnabled;
|
||||
model.titleLabelNormalStrokeWidth = 0;
|
||||
model.titleLabelSelectedStrokeWidth = self.titleLabelSelectedStrokeWidth;
|
||||
model.titleLabelVerticalOffset = self.titleLabelVerticalOffset;
|
||||
model.titleLabelAnchorPointStyle = self.titleLabelAnchorPointStyle;
|
||||
if (index == self.selectedIndex) {
|
||||
model.titleCurrentColor = model.titleSelectedColor;
|
||||
model.titleLabelCurrentZoomScale = model.titleLabelSelectedZoomScale;
|
||||
model.titleLabelCurrentStrokeWidth= model.titleLabelSelectedStrokeWidth;
|
||||
}else {
|
||||
model.titleCurrentColor = model.titleNormalColor;
|
||||
model.titleLabelCurrentZoomScale = model.titleLabelNormalZoomScale;
|
||||
model.titleLabelCurrentStrokeWidth = model.titleLabelNormalStrokeWidth;
|
||||
}
|
||||
}
|
||||
|
||||
@end
|
||||
Reference in New Issue
Block a user