// // POBaseStyleTableViewCell.m // powerone // // Created by kinghai on 2018/8/3. // Copyright © 2018年 onecloud.ltd. All rights reserved. // #import "POBaseStyleTableViewCell.h" #import "BigBtn.h" #define DefaultCornerRadius 10 //默认视图圆角 #define DefaultShowShadow YES //默认显示阴影 #define DefaultShadowColor RGBACOLOR(0, 0, 0, 0.3) //默认阴影颜色 #define DefaultShadowOpacity 0.2 //默认阴影不透明度 #define DefaultShadowOffset CGSizeMake(0, 3) //默认阴影偏移 #define DefaultShadowRadius 3 //默认阴影半径(并不是指阴影拐角处的圆角半径,而是阴影超出视图边界的半径) #define DefaultEdgeInsets UIEdgeInsetsMake(5, 8, 5, 8) //默认背景卡片距离cell的边距 #define DefaultCorners UIRectCornerAllCorners //默认四个角都是圆角 #define DefaultStyleViewSize CGSizeMake(SCREENWIDTH-DefaultEdgeInsets.left-DefaultEdgeInsets.right, 50-DefaultEdgeInsets.top-DefaultEdgeInsets.bottom) //默认cell的样式背景视图高宽 #define DefaultNoShadowSide PONoShadowSideNone //默认四边都有阴影 #define StyleBackgroundViewBackgroundColor [UIColor whiteColor] //样式背景视图的颜色 @implementation POCellStyleDataModel - (instancetype)init { if (self = [super init]) { _cornerRadius = DefaultCornerRadius; _showShadow = DefaultShowShadow; _shadowColor = DefaultShadowColor; _shadowOpacity = DefaultShadowOpacity; _shadowOffset = DefaultShadowOffset; _shadowRadius = DefaultShadowRadius; _corners = DefaultCorners; _styleViewSize = DefaultStyleViewSize; _noShadowSide = DefaultNoShadowSide; _cellBackgroundColor = StyleBackgroundViewBackgroundColor; _edgeInsets = DefaultEdgeInsets; } return self; } @end @implementation POCellStyleBackgroundView /** 如果styleModel=nil则使用默认值 */ - (void)setupViewWithStyleModel:(POCellStyleDataModel *)styleModel { CGFloat cornerRadius = DefaultCornerRadius; BOOL showShadow = DefaultShowShadow; CGColorRef shadowColor = DefaultShadowColor.CGColor; CGFloat shadowOpacity = DefaultShadowOpacity; CGSize shadowOffset = DefaultShadowOffset; CGFloat shadowRadius = DefaultShadowRadius; UIRectCorner corners = DefaultCorners; CGSize styleViewSize = DefaultStyleViewSize; PONoShadowSide noShadowSide = DefaultNoShadowSide; UIColor *cellBackgroundColor = StyleBackgroundViewBackgroundColor; _styleModel = styleModel; if (_styleModel != nil) { cornerRadius = _styleModel.cornerRadius; showShadow = _styleModel.showShadow; shadowColor = _styleModel.shadowColor.CGColor; shadowOpacity = _styleModel.shadowOpacity; shadowOffset = _styleModel.shadowOffset; shadowRadius = _styleModel.shadowRadius; corners = _styleModel.corners; styleViewSize = _styleModel.styleViewSize; noShadowSide = _styleModel.noShadowSide; cellBackgroundColor = _styleModel.cellBackgroundColor?:StyleBackgroundViewBackgroundColor; } //解决复用cell的bug self.layer.mask = nil;//复用cell的时候mask还存在,所以要重新设置为nil NSArray *sublayerArray = [NSArray arrayWithArray:self.layer.sublayers];//因为self.layer.sublayers在执行removeFromSuperlayer时是变化的 for (CALayer *layer in sublayerArray) { [layer removeFromSuperlayer];//移除cornerLayer和lineLayer } //设置圆角 if (corners == UIRectCornerAllCorners || corners == (UIRectCornerBottomLeft|UIRectCornerBottomRight|UIRectCornerTopLeft|UIRectCornerTopRight) || cornerRadius == 0) { //四周圆角 self.backgroundColor = cellBackgroundColor; self.layer.cornerRadius = cornerRadius; } else { //任意圆角 self.backgroundColor = nil;//需要设置view的背景色为空,否则cornerLayer露出的圆角部分会显示这个颜色,阴影部分也会变成在view的边界出现 self.layer.cornerRadius = cornerRadius;//设置任意圆角原本不用设置self.layer.cornerRadius,但是考虑到复用cell的bug,如果复用的cell原本设置了self.layer.cornerRadius=0,会导致设置部分圆角时不出现圆角 CGRect viewFrame = CGRectMake(0, 0, styleViewSize.width, styleViewSize.height ); CGPathRef path = [UIBezierPath bezierPathWithRoundedRect:viewFrame byRoundingCorners:corners cornerRadii:CGSizeMake(cornerRadius, corners)].CGPath; CAShapeLayer *shapeLayer = [CAShapeLayer layer]; shapeLayer.path = path; CALayer *cornerLayer = [CALayer layer]; cornerLayer.frame = viewFrame; cornerLayer.backgroundColor = _styleModel.cellBackgroundColor.CGColor?:StyleBackgroundViewBackgroundColor.CGColor; cornerLayer.mask = shapeLayer; [self.layer addSublayer:cornerLayer];//设置self.layer.mask = shapeLayer;会导致阴影消失 } //设置分隔线 if ((noShadowSide & PONoShadowSideBottom) == PONoShadowSideBottom) { CGFloat lineHeight = 1; CGRect bounds = CGRectInset(CGRectMake(0, 0, styleViewSize.width, styleViewSize.height), 0, 0);//获取样式背景视图的size CALayer *lineLayer = [CALayer new]; lineLayer.frame = CGRectMake(CGRectGetMinX(bounds), bounds.size.height-lineHeight, bounds.size.width, lineHeight); lineLayer.backgroundColor = UIColorFromHex(0xF3F9F5).CGColor; [self.layer addSublayer:lineLayer];//上部分有圆角的cell加上分隔线 } //设置阴影 if (showShadow && (noShadowSide & PONoShadowSideAll) != PONoShadowSideAll) { self.layer.shadowColor = shadowColor; self.layer.shadowOpacity = shadowOpacity; self.layer.shadowOffset = shadowOffset; self.layer.shadowRadius = shadowRadius;//不是指阴影拐角处的半径,而是指阴影超出视图边界的半径 CGFloat additionMarginForShowShadow = self.layer.shadowRadius+10;//self.layer.shadowRadius是深色阴影的宽度,10是为扩散的浅色阴影而预留的范围以免无法显示阴影 CGRect maskRect = CGRectMake(-additionMarginForShowShadow, -additionMarginForShowShadow, styleViewSize.width+2*additionMarginForShowShadow, styleViewSize.height+2*additionMarginForShowShadow);//这是包含四边阴影的范围 if ((noShadowSide & PONoShadowSideNone) == PONoShadowSideNone) { //由于PONoShadowSide值的特殊性,只有一个位是1,为a=0001、0010、b=0100、1000等,所以比如a|b之后变成0101,(a|b)和a或者b的按位与运算等于a或b maskRect = CGRectZero; } else { if ((noShadowSide & PONoShadowSideTop) == PONoShadowSideTop) { maskRect.origin.y += additionMarginForShowShadow; maskRect.size.height -= additionMarginForShowShadow; } if ((noShadowSide & PONoShadowSideBottom) == PONoShadowSideBottom) { maskRect.size.height -= additionMarginForShowShadow; } if ((noShadowSide & PONoShadowSideLeft) == PONoShadowSideLeft) { maskRect.origin.x -= additionMarginForShowShadow; maskRect.size.width -= additionMarginForShowShadow; } if ((noShadowSide & PONoShadowSideRight) == PONoShadowSideRight) { maskRect.size.width -= additionMarginForShowShadow; } } if (CGRectEqualToRect(maskRect, CGRectZero) == NO) { CGPathRef path = [UIBezierPath bezierPathWithRect:maskRect].CGPath;//由于阴影超出layer的边界,所以剪切的时候要显示阴影,需要剪切rect包含阴影 CAShapeLayer *shapeLayer = [CAShapeLayer layer]; shapeLayer.path = path; self.layer.mask = shapeLayer;//将某一边的阴影剪切掉 } self.layer.masksToBounds = NO; } else { //无阴影不能设置为yes self.layer.masksToBounds = NO; } } @end @interface POBaseStyleTableViewCell () @end @implementation POBaseStyleTableViewCell - (instancetype)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier { if (self = [super initWithStyle:style reuseIdentifier:reuseIdentifier]) { self.selectionStyle = UITableViewCellSelectionStyleNone; self.backgroundColor = [UIColor clearColor]; _styleBackgroundView = [POCellStyleBackgroundView new]; [self insertSubview:_styleBackgroundView atIndex:0];//不能使用self.backgroundView = _styleBackgroundView;,否则会在左滑恢复之后sbv的位置变动成和cell一样大然后才恢复为正常 —— 由于_styleBackgroundView在最底层,所以它的子视图无法响应手势 } return self; } - (void)setStyleModel:(POCellStyleDataModel *)styleModel { _styleModel = styleModel; [self setupStyleBackgroundViewWithStyleModel:_styleModel]; } - (void)setupStyleBackgroundViewWithStyleModel:(POCellStyleDataModel *)styleModel { UIEdgeInsets edgeInsets = DefaultEdgeInsets; if (styleModel != nil) { edgeInsets = styleModel.edgeInsets; } [_styleBackgroundView setupViewWithStyleModel:styleModel]; [_styleBackgroundView mas_updateConstraints:^(MASConstraintMaker *make) { //不能使用mas_make,会导致之前设置的约束无法完全覆盖 make.edges.equalTo(self).insets(edgeInsets); }]; } - (void)setSelected:(BOOL)selected animated:(BOOL)animated { [super setSelected:selected animated:animated]; // Configure the view for the selected state } - (void)setHighlighted:(BOOL)highlighted animated:(BOOL)animated { [super setHighlighted:highlighted animated:animated]; _styleBackgroundView.backgroundColor = _styleModel.cellBackgroundColor?:StyleBackgroundViewBackgroundColor;;//当cell被点击时,子控件的背景色会消失,所以要在这个方法中重新设置背景色(如果是非全部圆角则点击时背景色不会消失,因为这个背景色是通过添加CALayer显示的) } - (void)setAccessoryType:(UITableViewCellAccessoryType)accessoryType { if(accessoryType == UITableViewCellAccessoryDisclosureIndicator) { [self po_setAccessoryType:accessoryType]; } else { self.accessoryView = nil; [super setAccessoryType:accessoryType]; } } @end