HJAudioBubble.m 7.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254
  1. //
  2. // HJAudioBubble.m
  3. // HJAudioBubbleDemo
  4. //
  5. // Created by WHJ on 2017/11/30.
  6. // Copyright © 2017年 WHJ. All rights reserved.
  7. //
  8. #import "HJAudioBubble.h"
  9. @interface HJAudioBubble ()
  10. /** 背景气泡图片 */
  11. @property (nonatomic, strong) UIImageView *baseView;
  12. /** 播放图片 */
  13. @property (nonatomic, strong) UIImageView *playIconV;
  14. /** 时长显示 */
  15. @property (nonatomic, strong) UILabel *timeLabel;
  16. /** HJAudioBubbleConfig */
  17. @property (nonatomic, strong) HJAudioBubbleConfig *bubbleConfig;
  18. @end
  19. static const CGFloat kTimeLabelW = 60.f;
  20. static const CGFloat kPlayIconW = 20.f;
  21. @implementation HJAudioBubble
  22. #pragma mark - Life Circle
  23. -(instancetype)initWithFrame:(CGRect)frame;{
  24. self = [super initWithFrame:frame];
  25. if(self){
  26. [self setupUI];
  27. }
  28. return self;
  29. }
  30. - (instancetype)init
  31. {
  32. self = [super init];
  33. if (self) {
  34. [self setupUI];
  35. }
  36. return self;
  37. }
  38. #pragma mark - About UI
  39. - (void)setupUI{
  40. [self addSubview:self.baseView];
  41. [self.baseView addSubview:self.playIconV];
  42. [self addSubview:self.timeLabel];
  43. self.bubbleConfig = kHJAudioBubbleConfig;
  44. [self refreshUI];
  45. }
  46. - (void)prepareLayout{
  47. //布局baseView
  48. CGFloat baseW = 0;
  49. if (self.bubbleConfig.timeShowType == HJAudioBubbleTimeShowType_inContainer) {
  50. baseW = CGRectGetWidth(self.frame);
  51. }else if (self.bubbleConfig.timeShowType == HJAudioBubbleTimeShowType_outContainer){
  52. baseW = CGRectGetWidth(self.frame) - kTimeLabelW;
  53. }else{
  54. baseW = CGRectGetWidth(self.frame);
  55. }
  56. self.baseView.frame = CGRectMake(0, 0, baseW, CGRectGetHeight(self.frame));
  57. self.baseView.center = CGPointMake(self.baseView.center.x, CGRectGetHeight(self.frame)/2.f);
  58. //布局playIconV
  59. CGFloat baseViewH = CGRectGetHeight(self.baseView.frame);
  60. // self.playIconV.frame = CGRectMake(self.bubbleConfig.iconMargin, 0, kPlayIconW, kPlayIconW);
  61. // self.playIconV.center = CGPointMake(self.playIconV.center.x, CGRectGetHeight(self.frame)/2.f);
  62. self.playIconV.frame = self.baseView.bounds;
  63. //布局timeLabel
  64. self.timeLabel.frame = CGRectMake(0, 0, kTimeLabelW, baseViewH);
  65. self.timeLabel.hidden = NO;
  66. }
  67. - (void)hj_layout{
  68. //布局前准备
  69. [self prepareLayout];
  70. CGFloat baseViewH = CGRectGetHeight(self.baseView.frame);
  71. CGFloat baseW = CGRectGetWidth(self.baseView.frame);
  72. //根据时长显示位置及气泡左右调整布局
  73. switch (self.bubbleConfig.timeShowType) {
  74. case HJAudioBubbleTimeShowType_inContainer:
  75. self.timeLabel.center = self.baseView.center;
  76. if (self.bubbleShowRight) {
  77. self.baseView.layer.transform = CATransform3DMakeRotation(M_PI, 0, 1, 0);
  78. }else{
  79. self.baseView.layer.transform = CATransform3DIdentity;
  80. }
  81. break;
  82. case HJAudioBubbleTimeShowType_outContainer:
  83. if (self.bubbleShowRight) {
  84. self.timeLabel.frame = CGRectMake(0, 0, kTimeLabelW, baseViewH);
  85. self.baseView.frame = CGRectMake(CGRectGetMaxX(self.timeLabel.frame), 0, baseW, CGRectGetHeight(self.frame));
  86. self.baseView.layer.transform = CATransform3DMakeRotation(M_PI, 0, 1, 0);
  87. }else{
  88. self.timeLabel.frame = CGRectMake(CGRectGetMaxX(self.baseView.frame), 0, kTimeLabelW, baseViewH);
  89. self.baseView.layer.transform = CATransform3DIdentity;
  90. }
  91. break;
  92. case HJAudioBubbleTimeShowType_none:
  93. if (self.bubbleShowRight) {
  94. self.baseView.layer.transform = CATransform3DMakeRotation(M_PI, 0, 1, 0);
  95. }else{
  96. self.baseView.layer.transform = CATransform3DIdentity;
  97. }
  98. self.timeLabel.hidden = YES;
  99. break;
  100. default:
  101. break;
  102. }
  103. }
  104. #pragma mark - Pravite Method
  105. - (UIImage *)handleBubbleImage:(UIImage *)image{
  106. image = [image stretchableImageWithLeftCapWidth:floorf(image.size.width-10) topCapHeight:floorf(image.size.height-10)];
  107. return image;
  108. }
  109. #pragma mark - Public Method
  110. //开始动画
  111. - (void)startAnimating;{
  112. if (self.bubbleConfig.animatingBubble) {
  113. [self.bubbleConfig.animatingBubble stopAnimating];
  114. self.bubbleConfig.animatingBubble = nil;
  115. }
  116. [self.playIconV startAnimating];
  117. self.bubbleConfig.animatingBubble = self;
  118. }
  119. //结束动画
  120. - (void)stopAnimating;{
  121. if (self.bubbleClickBlock) {
  122. self.bubbleClickBlock(NO);
  123. }
  124. [self.playIconV stopAnimating];
  125. }
  126. #pragma mark - Event response
  127. - (void)audioBubbleClicked:(UITapGestureRecognizer *)tap{
  128. if (self.playIconV.isAnimating) {
  129. [self stopAnimating];
  130. }else{
  131. [self startAnimating];
  132. }
  133. if (self.bubbleClickBlock) {
  134. self.bubbleClickBlock(self.playIconV.isAnimating);
  135. }
  136. }
  137. - (void)audioBubbleLongPress:(UILongPressGestureRecognizer *)longPress{
  138. if (longPress.state == UIGestureRecognizerStateEnded) {
  139. if (self.longPressCallBack) {
  140. self.longPressCallBack();
  141. [self stopAnimating];
  142. }
  143. }
  144. }
  145. #pragma mark - Delegate methods
  146. #pragma mark - Getters/Setters/Lazy
  147. - (UIImageView *)baseView{
  148. if (!_baseView) {
  149. _baseView = [[UIImageView alloc] init];
  150. _baseView.userInteractionEnabled = YES;
  151. UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(audioBubbleClicked:)];
  152. UILongPressGestureRecognizer *longPress = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:@selector(audioBubbleLongPress:)];
  153. [_baseView addGestureRecognizer:tap];
  154. [_baseView addGestureRecognizer:longPress];
  155. [_baseView setImage:[UIImage imageNamed:@"du_voice_background"]];
  156. }
  157. return _baseView;
  158. }
  159. - (UIImageView *)playIconV{
  160. if (!_playIconV) {
  161. _playIconV = [[UIImageView alloc] init];
  162. _playIconV.userInteractionEnabled = YES;
  163. _playIconV.backgroundColor = [UIColor clearColor];
  164. _playIconV.contentMode = UIViewContentModeScaleAspectFit;
  165. }
  166. return _playIconV;
  167. }
  168. - (UILabel *)timeLabel{
  169. if (!_timeLabel) {
  170. _timeLabel = [[UILabel alloc] init];
  171. _timeLabel.font = [UIFont systemFontOfSize:12];
  172. _timeLabel.textColor = [UIColor darkGrayColor];
  173. _timeLabel.textAlignment = NSTextAlignmentCenter;
  174. _timeLabel.backgroundColor = [UIColor clearColor];
  175. }
  176. return _timeLabel;
  177. }
  178. //设置气泡显示位置
  179. - (void)setBubbleShowRight:(BOOL)bubbleShowRight{
  180. _bubbleShowRight = bubbleShowRight;
  181. [self refreshUI];
  182. }
  183. - (void)setFrame:(CGRect)frame{
  184. [super setFrame:frame];
  185. [self refreshUI];
  186. }
  187. //设置时长
  188. - (void)setTimeStr:(NSString *)timeStr{
  189. _timeStr = timeStr;
  190. self.timeLabel.text = timeStr;
  191. }
  192. - (void)refreshUI{
  193. //设置气泡
  194. // self.baseView.image = self.bubbleShowRight?self.bubbleConfig.rightBubbleImage:self.bubbleConfig.leftBubbleImage;
  195. // self.baseView.backgroundColor = self.bubbleShowRight?self.bubbleConfig.rightBubbleBgColor:self.bubbleConfig.leftBubbleBgColor;
  196. self.baseView.backgroundColor = kWhiteColor;
  197. // RGB(240, 240, 240);
  198. //设置播放动画图片
  199. _playIconV.image = self.bubbleConfig.voiceDefaultImage;
  200. _playIconV.animationDuration = self.bubbleConfig.duration;
  201. _playIconV.animationImages = self.bubbleConfig.voiceAnimationImages;
  202. self.baseView.layer.masksToBounds = YES;
  203. self.baseView.layer.cornerRadius = 3;
  204. //设置时长样式
  205. _timeLabel.font = kHJAudioBubbleConfig.timeFont;
  206. _timeLabel.textColor = kHJAudioBubbleConfig.timeColor;
  207. //重新布局
  208. [self hj_layout];
  209. }
  210. @end