2
0

BubbleTipView.m 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240
  1. //
  2. // BubbleTipView.m
  3. // WFChat UIKit
  4. //
  5. // Created by WF Chat on 2017/9/12.
  6. // Copyright © 2017年 WildFireChat. All rights reserved.
  7. //
  8. #import "BubbleTipView.h"
  9. #import <QuartzCore/QuartzCore.h>
  10. #define kDefaultbubbleTipTextColor [UIColor whiteColor]
  11. #define kDefaultbubbleTipBackgroundColor [UIColor redColor]
  12. #define kDefaultOverlayColor [UIColor colorWithWhite:1.0f alpha:0.3]
  13. #define kDefaultbubbleTipTextFont [UIFont systemFontOfSize:[UIFont smallSystemFontSize]]
  14. #define kDefaultbubbleTipShadowColor [UIColor clearColor]
  15. #define kbubbleTipStrokeColor [UIColor whiteColor]
  16. #define kbubbleTipStrokeWidth 0.0f
  17. #define kMarginToDrawInside (kbubbleTipStrokeWidth * 2)
  18. #define kShadowOffset CGSizeMake(0.0f, 3.0f)
  19. #define kShadowOpacity 0.2f
  20. #define kShadowColor [UIColor colorWithWhite:0.0f alpha:kShadowOpacity]
  21. #define kShadowRadius 1.0f
  22. #define kbubbleTipHeight 18.0f
  23. #define kbubbleTipTextSideMargin 6.0f
  24. #define kbubbleTipCornerRadius 10.0f
  25. #define kDefaultbubbleTipAlignment RC_MESSAGE_BUBBLE_TIP_VIEW_ALIGNMENT_TOP_RIGHT
  26. #define IOS_SYSTEM_VERSION_LESS_THAN(v) \
  27. ([[[UIDevice currentDevice] systemVersion] \
  28. compare:v \
  29. options:NSNumericSearch] == NSOrderedAscending)
  30. @implementation BubbleTipView
  31. - (void)awakeFromNib {
  32. [super awakeFromNib];
  33. [self setup];
  34. }
  35. - (instancetype)initWithFrame:(CGRect)frame {
  36. self = [super initWithFrame:frame];
  37. if (self) {
  38. [self setup];
  39. }
  40. return self;
  41. }
  42. - (instancetype)initWithCoder:(NSCoder *)aDecoder {
  43. self = [super initWithCoder:aDecoder];
  44. if (self) {
  45. [self setup];
  46. }
  47. return self;
  48. }
  49. - (instancetype)initWithSuperView:(UIView *)parentView {
  50. if ((self = [self initWithFrame:CGRectZero])) {
  51. [parentView addSubview:self];
  52. }
  53. return self;
  54. }
  55. - (void)setup {
  56. self.backgroundColor = [UIColor clearColor];
  57. self.bubbleTipBackgroundColor = kDefaultbubbleTipBackgroundColor;
  58. // _bubbleTipOverlayColor = kDefaultOverlayColor;
  59. // self.bubbleTipTextColor = kDefaultbubbleTipTextColor;
  60. self.bubbleTipTextShadowColor = kDefaultbubbleTipShadowColor;
  61. self.bubbleTipTextFont = kDefaultbubbleTipTextFont;
  62. }
  63. - (void)layoutSubviews {
  64. [super layoutSubviews];
  65. // return;
  66. CGRect newFrame = self.frame;
  67. CGRect superviewFrame =
  68. CGRectIsEmpty(_frameToPositionInRelationWith) ? self.superview.frame : _frameToPositionInRelationWith;
  69. CGFloat textWidth = [self sizeOfTextForCurrentSettings].width;
  70. CGFloat viewWidth = textWidth + kbubbleTipTextSideMargin + (kMarginToDrawInside * 2);
  71. CGFloat viewHeight = kbubbleTipHeight + (kMarginToDrawInside * 2);
  72. if (self.isShowNotificationNumber) {
  73. newFrame.size.width = viewWidth;
  74. newFrame.size.height = viewHeight;
  75. newFrame.origin.y = 0;
  76. newFrame.origin.x = 48;
  77. }else{
  78. newFrame.size.width = 10;
  79. newFrame.size.height = 10;
  80. newFrame.origin.y = 4;
  81. newFrame.origin.x = 54;
  82. }
  83. newFrame.origin.x += _bubbleTipPositionAdjustment.x;
  84. newFrame.origin.y += _bubbleTipPositionAdjustment.y;
  85. self.frame = CGRectIntegral(newFrame);
  86. [self setNeedsDisplay];
  87. }
  88. #pragma mark - Private
  89. - (CGSize)sizeOfTextForCurrentSettings {
  90. CGSize size;
  91. if (@available(iOS 7.0, *)) {
  92. size = [self.bubbleTipText sizeWithAttributes:@{NSFontAttributeName : self.bubbleTipTextFont}];
  93. } else {
  94. size = [self.bubbleTipText sizeWithFont:kDefaultbubbleTipTextFont];
  95. }
  96. if (self.bubbleTipText.length == 1) {
  97. size.width = 12;
  98. }
  99. if (self.bubbleTipText.length == 2) {
  100. size.width = 18;
  101. }
  102. if (self.bubbleTipText.length == 3) {
  103. size.width = 18;
  104. }
  105. return CGSizeMake(ceilf(size.width), ceilf(size.height));
  106. }
  107. #pragma mark - Setters
  108. - (void)setBubbleTipNumber:(int)msgCount {
  109. if (msgCount < 100 && msgCount > 0) {
  110. if(self.isShowNotificationNumber)
  111. [self setBubbleTipText:[NSString stringWithFormat:@"%d", msgCount]];
  112. else
  113. [self setBubbleTipText:@" "];
  114. } else if (msgCount >= 100) {
  115. if(self.isShowNotificationNumber)
  116. [self setBubbleTipText:@"···"];
  117. else
  118. [self setBubbleTipText:@" "];
  119. } else {
  120. [self setHidden:YES];
  121. }
  122. [self layoutSubviews];
  123. }
  124. #pragma mark - Drawing
  125. - (void)drawRect:(CGRect)rect {
  126. BOOL anyTextToDraw = (self.bubbleTipText.length > 0);
  127. if(!self.isShowNotificationNumber)
  128. [self setBubbleTipText:@" "];
  129. if (anyTextToDraw) {
  130. CGContextRef ctx = UIGraphicsGetCurrentContext();
  131. CGRect rectToDraw = CGRectInset(rect, kMarginToDrawInside, kMarginToDrawInside);
  132. UIBezierPath *borderPath =
  133. [UIBezierPath bezierPathWithRoundedRect:rectToDraw
  134. byRoundingCorners:(UIRectCorner)UIRectCornerAllCorners
  135. cornerRadii:CGSizeMake(kbubbleTipCornerRadius, kbubbleTipCornerRadius)];
  136. /* Background and shadow */
  137. CGContextSaveGState(ctx);
  138. {
  139. CGContextAddPath(ctx, borderPath.CGPath);
  140. CGContextSetFillColorWithColor(ctx, self.bubbleTipBackgroundColor.CGColor);
  141. // CGContextSetShadowWithColor(ctx, kShadowOffset, kShadowRadius, kShadowColor.CGColor);
  142. CGContextDrawPath(ctx, kCGPathFill);
  143. }
  144. CGContextRestoreGState(ctx);
  145. /* Stroke */
  146. CGContextSaveGState(ctx);
  147. {
  148. CGContextAddPath(ctx, borderPath.CGPath);
  149. CGContextSetLineWidth(ctx, kbubbleTipStrokeWidth);
  150. CGContextSetStrokeColorWithColor(ctx, kbubbleTipStrokeColor.CGColor);
  151. CGContextDrawPath(ctx, kCGPathStroke);
  152. }
  153. CGContextRestoreGState(ctx);
  154. /* Text */
  155. CGContextSaveGState(ctx);
  156. {
  157. CGContextSetFillColorWithColor(ctx, kDefaultbubbleTipTextColor.CGColor);
  158. CGContextSetShadowWithColor(ctx, self.bubbleTipTextShadowOffset, 1.0,
  159. self.bubbleTipTextShadowColor.CGColor);
  160. CGRect textFrame = rectToDraw;
  161. CGSize textSize = [self sizeOfTextForCurrentSettings];
  162. textFrame.size.height = textSize.height;
  163. textFrame.origin.y = rectToDraw.origin.y + ceilf((rectToDraw.size.height - textFrame.size.height) / 2.0f);
  164. if(IOS_SYSTEM_VERSION_LESS_THAN(@"7.0"))
  165. {
  166. [self.bubbleTipText drawInRect:textFrame
  167. withFont:self.bubbleTipTextFont
  168. lineBreakMode:NSLineBreakByCharWrapping
  169. alignment:NSTextAlignmentCenter];
  170. }
  171. else
  172. {
  173. NSMutableParagraphStyle *paragraphStyle = [[NSMutableParagraphStyle alloc] init];
  174. paragraphStyle.lineBreakMode = NSLineBreakByCharWrapping;
  175. paragraphStyle.alignment = NSTextAlignmentCenter;
  176. [self.bubbleTipText drawInRect:textFrame
  177. withAttributes:@{
  178. NSFontAttributeName : self.bubbleTipTextFont,
  179. NSForegroundColorAttributeName : kDefaultbubbleTipTextColor,
  180. NSParagraphStyleAttributeName : paragraphStyle
  181. }];
  182. }
  183. }
  184. CGContextRestoreGState(ctx);
  185. }
  186. }
  187. @end