POBaseStyleTableViewCell.m 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248
  1. //
  2. // POBaseStyleTableViewCell.m
  3. // powerone
  4. //
  5. // Created by kinghai on 2018/8/3.
  6. // Copyright © 2018年 onecloud.ltd. All rights reserved.
  7. //
  8. #import "POBaseStyleTableViewCell.h"
  9. #import "BigBtn.h"
  10. #define DefaultCornerRadius 10 //默认视图圆角
  11. #define DefaultShowShadow YES //默认显示阴影
  12. #define DefaultShadowColor RGBACOLOR(0, 0, 0, 0.3) //默认阴影颜色
  13. #define DefaultShadowOpacity 0.2 //默认阴影不透明度
  14. #define DefaultShadowOffset CGSizeMake(0, 3) //默认阴影偏移
  15. #define DefaultShadowRadius 3 //默认阴影半径(并不是指阴影拐角处的圆角半径,而是阴影超出视图边界的半径)
  16. #define DefaultEdgeInsets UIEdgeInsetsMake(5, 8, 5, 8) //默认背景卡片距离cell的边距
  17. #define DefaultCorners UIRectCornerAllCorners //默认四个角都是圆角
  18. #define DefaultStyleViewSize CGSizeMake(SCREENWIDTH-DefaultEdgeInsets.left-DefaultEdgeInsets.right, 50-DefaultEdgeInsets.top-DefaultEdgeInsets.bottom) //默认cell的样式背景视图高宽
  19. #define DefaultNoShadowSide PONoShadowSideNone //默认四边都有阴影
  20. #define StyleBackgroundViewBackgroundColor [UIColor whiteColor] //样式背景视图的颜色
  21. @implementation POCellStyleDataModel
  22. - (instancetype)init
  23. {
  24. if (self = [super init])
  25. {
  26. _cornerRadius = DefaultCornerRadius;
  27. _showShadow = DefaultShowShadow;
  28. _shadowColor = DefaultShadowColor;
  29. _shadowOpacity = DefaultShadowOpacity;
  30. _shadowOffset = DefaultShadowOffset;
  31. _shadowRadius = DefaultShadowRadius;
  32. _corners = DefaultCorners;
  33. _styleViewSize = DefaultStyleViewSize;
  34. _noShadowSide = DefaultNoShadowSide;
  35. _cellBackgroundColor = StyleBackgroundViewBackgroundColor;
  36. _edgeInsets = DefaultEdgeInsets;
  37. }
  38. return self;
  39. }
  40. @end
  41. @implementation POCellStyleBackgroundView
  42. /** 如果styleModel=nil则使用默认值 */
  43. - (void)setupViewWithStyleModel:(POCellStyleDataModel *)styleModel
  44. {
  45. CGFloat cornerRadius = DefaultCornerRadius;
  46. BOOL showShadow = DefaultShowShadow;
  47. CGColorRef shadowColor = DefaultShadowColor.CGColor;
  48. CGFloat shadowOpacity = DefaultShadowOpacity;
  49. CGSize shadowOffset = DefaultShadowOffset;
  50. CGFloat shadowRadius = DefaultShadowRadius;
  51. UIRectCorner corners = DefaultCorners;
  52. CGSize styleViewSize = DefaultStyleViewSize;
  53. PONoShadowSide noShadowSide = DefaultNoShadowSide;
  54. UIColor *cellBackgroundColor = StyleBackgroundViewBackgroundColor;
  55. _styleModel = styleModel;
  56. if (_styleModel != nil)
  57. {
  58. cornerRadius = _styleModel.cornerRadius;
  59. showShadow = _styleModel.showShadow;
  60. shadowColor = _styleModel.shadowColor.CGColor;
  61. shadowOpacity = _styleModel.shadowOpacity;
  62. shadowOffset = _styleModel.shadowOffset;
  63. shadowRadius = _styleModel.shadowRadius;
  64. corners = _styleModel.corners;
  65. styleViewSize = _styleModel.styleViewSize;
  66. noShadowSide = _styleModel.noShadowSide;
  67. cellBackgroundColor = _styleModel.cellBackgroundColor?:StyleBackgroundViewBackgroundColor;
  68. }
  69. //解决复用cell的bug
  70. self.layer.mask = nil;//复用cell的时候mask还存在,所以要重新设置为nil
  71. NSArray *sublayerArray = [NSArray arrayWithArray:self.layer.sublayers];//因为self.layer.sublayers在执行removeFromSuperlayer时是变化的
  72. for (CALayer *layer in sublayerArray)
  73. {
  74. [layer removeFromSuperlayer];//移除cornerLayer和lineLayer
  75. }
  76. //设置圆角
  77. if (corners == UIRectCornerAllCorners || corners == (UIRectCornerBottomLeft|UIRectCornerBottomRight|UIRectCornerTopLeft|UIRectCornerTopRight) || cornerRadius == 0)
  78. {
  79. //四周圆角
  80. self.backgroundColor = cellBackgroundColor;
  81. self.layer.cornerRadius = cornerRadius;
  82. }
  83. else
  84. {
  85. //任意圆角
  86. self.backgroundColor = nil;//需要设置view的背景色为空,否则cornerLayer露出的圆角部分会显示这个颜色,阴影部分也会变成在view的边界出现
  87. self.layer.cornerRadius = cornerRadius;//设置任意圆角原本不用设置self.layer.cornerRadius,但是考虑到复用cell的bug,如果复用的cell原本设置了self.layer.cornerRadius=0,会导致设置部分圆角时不出现圆角
  88. CGRect viewFrame = CGRectMake(0, 0, styleViewSize.width, styleViewSize.height );
  89. CGPathRef path = [UIBezierPath bezierPathWithRoundedRect:viewFrame byRoundingCorners:corners cornerRadii:CGSizeMake(cornerRadius, corners)].CGPath;
  90. CAShapeLayer *shapeLayer = [CAShapeLayer layer];
  91. shapeLayer.path = path;
  92. CALayer *cornerLayer = [CALayer layer];
  93. cornerLayer.frame = viewFrame;
  94. cornerLayer.backgroundColor = _styleModel.cellBackgroundColor.CGColor?:StyleBackgroundViewBackgroundColor.CGColor;
  95. cornerLayer.mask = shapeLayer;
  96. [self.layer addSublayer:cornerLayer];//设置self.layer.mask = shapeLayer;会导致阴影消失
  97. }
  98. //设置分隔线
  99. if ((noShadowSide & PONoShadowSideBottom) == PONoShadowSideBottom)
  100. {
  101. CGFloat lineHeight = 1;
  102. CGRect bounds = CGRectInset(CGRectMake(0, 0, styleViewSize.width, styleViewSize.height), 0, 0);//获取样式背景视图的size
  103. CALayer *lineLayer = [CALayer new];
  104. lineLayer.frame = CGRectMake(CGRectGetMinX(bounds), bounds.size.height-lineHeight, bounds.size.width, lineHeight);
  105. lineLayer.backgroundColor = UIColorFromHex(0xF3F9F5).CGColor;
  106. [self.layer addSublayer:lineLayer];//上部分有圆角的cell加上分隔线
  107. }
  108. //设置阴影
  109. if (showShadow && (noShadowSide & PONoShadowSideAll) != PONoShadowSideAll)
  110. {
  111. self.layer.shadowColor = shadowColor;
  112. self.layer.shadowOpacity = shadowOpacity;
  113. self.layer.shadowOffset = shadowOffset;
  114. self.layer.shadowRadius = shadowRadius;//不是指阴影拐角处的半径,而是指阴影超出视图边界的半径
  115. CGFloat additionMarginForShowShadow = self.layer.shadowRadius+10;//self.layer.shadowRadius是深色阴影的宽度,10是为扩散的浅色阴影而预留的范围以免无法显示阴影
  116. CGRect maskRect = CGRectMake(-additionMarginForShowShadow, -additionMarginForShowShadow, styleViewSize.width+2*additionMarginForShowShadow, styleViewSize.height+2*additionMarginForShowShadow);//这是包含四边阴影的范围
  117. if ((noShadowSide & PONoShadowSideNone) == PONoShadowSideNone)
  118. {
  119. //由于PONoShadowSide值的特殊性,只有一个位是1,为a=0001、0010、b=0100、1000等,所以比如a|b之后变成0101,(a|b)和a或者b的按位与运算等于a或b
  120. maskRect = CGRectZero;
  121. }
  122. else
  123. {
  124. if ((noShadowSide & PONoShadowSideTop) == PONoShadowSideTop)
  125. {
  126. maskRect.origin.y += additionMarginForShowShadow;
  127. maskRect.size.height -= additionMarginForShowShadow;
  128. }
  129. if ((noShadowSide & PONoShadowSideBottom) == PONoShadowSideBottom)
  130. {
  131. maskRect.size.height -= additionMarginForShowShadow;
  132. }
  133. if ((noShadowSide & PONoShadowSideLeft) == PONoShadowSideLeft)
  134. {
  135. maskRect.origin.x -= additionMarginForShowShadow;
  136. maskRect.size.width -= additionMarginForShowShadow;
  137. }
  138. if ((noShadowSide & PONoShadowSideRight) == PONoShadowSideRight)
  139. {
  140. maskRect.size.width -= additionMarginForShowShadow;
  141. }
  142. }
  143. if (CGRectEqualToRect(maskRect, CGRectZero) == NO)
  144. {
  145. CGPathRef path = [UIBezierPath bezierPathWithRect:maskRect].CGPath;//由于阴影超出layer的边界,所以剪切的时候要显示阴影,需要剪切rect包含阴影
  146. CAShapeLayer *shapeLayer = [CAShapeLayer layer];
  147. shapeLayer.path = path;
  148. self.layer.mask = shapeLayer;//将某一边的阴影剪切掉
  149. }
  150. self.layer.masksToBounds = NO;
  151. }
  152. else
  153. {
  154. //无阴影不能设置为yes
  155. self.layer.masksToBounds = NO;
  156. }
  157. }
  158. @end
  159. @interface POBaseStyleTableViewCell ()
  160. @end
  161. @implementation POBaseStyleTableViewCell
  162. - (instancetype)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier
  163. {
  164. if (self = [super initWithStyle:style reuseIdentifier:reuseIdentifier])
  165. {
  166. self.selectionStyle = UITableViewCellSelectionStyleNone;
  167. self.backgroundColor = [UIColor clearColor];
  168. _styleBackgroundView = [POCellStyleBackgroundView new];
  169. [self insertSubview:_styleBackgroundView atIndex:0];//不能使用self.backgroundView = _styleBackgroundView;,否则会在左滑恢复之后sbv的位置变动成和cell一样大然后才恢复为正常 —— 由于_styleBackgroundView在最底层,所以它的子视图无法响应手势
  170. }
  171. return self;
  172. }
  173. - (void)setStyleModel:(POCellStyleDataModel *)styleModel
  174. {
  175. _styleModel = styleModel;
  176. [self setupStyleBackgroundViewWithStyleModel:_styleModel];
  177. }
  178. - (void)setupStyleBackgroundViewWithStyleModel:(POCellStyleDataModel *)styleModel
  179. {
  180. UIEdgeInsets edgeInsets = DefaultEdgeInsets;
  181. if (styleModel != nil)
  182. {
  183. edgeInsets = styleModel.edgeInsets;
  184. }
  185. [_styleBackgroundView setupViewWithStyleModel:styleModel];
  186. [_styleBackgroundView mas_updateConstraints:^(MASConstraintMaker *make)
  187. {
  188. //不能使用mas_make,会导致之前设置的约束无法完全覆盖
  189. make.edges.equalTo(self).insets(edgeInsets);
  190. }];
  191. }
  192. - (void)setSelected:(BOOL)selected animated:(BOOL)animated
  193. {
  194. [super setSelected:selected animated:animated];
  195. // Configure the view for the selected state
  196. }
  197. - (void)setHighlighted:(BOOL)highlighted animated:(BOOL)animated
  198. {
  199. [super setHighlighted:highlighted animated:animated];
  200. _styleBackgroundView.backgroundColor = _styleModel.cellBackgroundColor?:StyleBackgroundViewBackgroundColor;;//当cell被点击时,子控件的背景色会消失,所以要在这个方法中重新设置背景色(如果是非全部圆角则点击时背景色不会消失,因为这个背景色是通过添加CALayer显示的)
  201. }
  202. - (void)setAccessoryType:(UITableViewCellAccessoryType)accessoryType
  203. {
  204. if(accessoryType == UITableViewCellAccessoryDisclosureIndicator)
  205. {
  206. [self po_setAccessoryType:accessoryType];
  207. }
  208. else
  209. {
  210. self.accessoryView = nil;
  211. [super setAccessoryType:accessoryType];
  212. }
  213. }
  214. @end