123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242 |
- //
- // 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"
- @interface JXCategoryTitleCell ()
- @property (nonatomic, strong) CALayer *titleMaskLayer;
- @property (nonatomic, strong) CALayer *maskTitleMaskLayer;
- @property (nonatomic, strong) NSLayoutConstraint *titleLabelCenterX;
- @property (nonatomic, strong) NSLayoutConstraint *titleLabelCenterY;
- @property (nonatomic, strong) NSLayoutConstraint *maskTitleLabelCenterX;
- @property (nonatomic, strong) NSLayoutConstraint *maskTitleLabelCenterY;
- @end
- @implementation JXCategoryTitleCell
- - (void)initializeViews
- {
- [super initializeViews];
-
- _titleLabel = [[UILabel alloc] init];
- self.titleLabel.clipsToBounds = YES;
- self.titleLabel.textAlignment = NSTextAlignmentCenter;
- self.titleLabel.translatesAutoresizingMaskIntoConstraints = NO;
- [self.contentView addSubview:self.titleLabel];
- self.titleLabelCenterX = [NSLayoutConstraint constraintWithItem:self.titleLabel attribute:NSLayoutAttributeCenterX relatedBy:NSLayoutRelationEqual toItem:self.contentView attribute:NSLayoutAttributeCenterX multiplier:1 constant:0];
- self.titleLabelCenterY = [NSLayoutConstraint constraintWithItem:self.titleLabel attribute:NSLayoutAttributeCenterY relatedBy:NSLayoutRelationEqual toItem:self.contentView attribute:NSLayoutAttributeCenterY multiplier:1 constant:0];
- [NSLayoutConstraint activateConstraints:@[self.titleLabelCenterX, self.titleLabelCenterY]];
- _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 = [NSLayoutConstraint constraintWithItem:self.maskTitleLabel attribute:NSLayoutAttributeCenterX relatedBy:NSLayoutRelationEqual toItem:self.contentView attribute:NSLayoutAttributeCenterX multiplier:1 constant:0];
- self.maskTitleLabelCenterY = [NSLayoutConstraint constraintWithItem:self.maskTitleLabel attribute:NSLayoutAttributeCenterY relatedBy:NSLayoutRelationEqual toItem:self.contentView attribute:NSLayoutAttributeCenterY multiplier:1 constant:0];
- [NSLayoutConstraint activateConstraints:@[self.maskTitleLabelCenterX, self.maskTitleLabelCenterY]];
- _maskTitleMaskLayer = [CALayer layer];
- self.maskTitleMaskLayer.backgroundColor = [UIColor redColor].CGColor;
- self.maskTitleLabel.layer.mask = self.maskTitleMaskLayer;
- }
- - (void)layoutSubviews {
- [super layoutSubviews];
- //因为titleLabel是通过约束布局的,在layoutSubviews方法中,它的frame并没有确定。像子类JXCategoryNumberCell中的numberLabel需要依赖于titleLabel的frame进行布局。所以这里必须立马触发self.contentView的视图布局。
- [self.contentView setNeedsLayout];
- [self.contentView layoutIfNeeded];
- JXCategoryTitleCellModel *myCellModel = (JXCategoryTitleCellModel *)self.cellModel;
- switch (myCellModel.titleLabelAnchorPointStyle) {
- case JXCategoryTitleLabelAnchorPointStyleCenter:
- self.titleLabelCenterY.constant = 0 + myCellModel.titleLabelVerticalOffset;
- break;
- case JXCategoryTitleLabelAnchorPointStyleTop:
- self.titleLabelCenterY.constant = -self.titleLabel.bounds.size.height/2 - myCellModel.titleLabelVerticalOffset;
- break;
- case JXCategoryTitleLabelAnchorPointStyleBottom:
- self.titleLabelCenterY.constant = self.titleLabel.bounds.size.height/2 + myCellModel.titleLabelVerticalOffset;
- break;
- default:
- break;
- }
- }
- - (void)reloadData:(JXCategoryBaseCellModel *)cellModel {
- [super reloadData:cellModel];
- JXCategoryTitleCellModel *myCellModel = (JXCategoryTitleCellModel *)cellModel;
- self.titleLabel.numberOfLines = myCellModel.titleNumberOfLines;
- self.maskTitleLabel.numberOfLines = myCellModel.titleNumberOfLines;
- switch (myCellModel.titleLabelAnchorPointStyle) {
- case JXCategoryTitleLabelAnchorPointStyleCenter:
- self.titleLabel.layer.anchorPoint = CGPointMake(0.5, 0.5);
- self.maskTitleLabel.layer.anchorPoint = CGPointMake(0.5, 0.5);
- break;
- case JXCategoryTitleLabelAnchorPointStyleTop:
- self.titleLabel.layer.anchorPoint = CGPointMake(0.5, 0);
- self.maskTitleLabel.layer.anchorPoint = CGPointMake(0.5, 0);
- break;
- case JXCategoryTitleLabelAnchorPointStyleBottom:
- self.titleLabel.layer.anchorPoint = CGPointMake(0.5, 1);
- self.maskTitleLabel.layer.anchorPoint = CGPointMake(0.5, 1);
- break;
- default:
- break;
- }
- 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);
- }
- [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];
- }
- - (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
|