SPSBBroadcastView.m 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173
  1. //
  2. // SPSBBroadcastView.m
  3. // 我的社保
  4. //
  5. // Created by shanp on 2021/5/12.
  6. //
  7. #import "SPSBBroadcastView.h"
  8. #import "SPSBUIGeneralHeader.h"
  9. #define LimitWidth (jxh_screenWidth() - 70)
  10. static NSString *const space = @" ";
  11. static const NSInteger SPConsultationBroadcastViewHeight = 45;
  12. @interface SPSBBroadcastView ()<CAAnimationDelegate> {
  13. UILabel *_broadcastLabel;
  14. void (^_reloadDataAction)(CGFloat height);
  15. UIView *_animationView;
  16. UILabel *_animationLabel;
  17. CGFloat _spaceWidth;
  18. CGFloat _broadcastWidth;
  19. bool _isAnimation;
  20. }
  21. @end
  22. @implementation SPSBBroadcastView
  23. - (instancetype)initWithReloadDataAction:(void (^)(CGFloat height))reloadDataAction {
  24. self = [super init];
  25. if (!self) return nil;
  26. _reloadDataAction = reloadDataAction;
  27. self.backgroundColor = spsb_FDF8EC_color();
  28. self.layer.masksToBounds = true;
  29. UIButton *deleteButton = [UIButton convenienceWithTarget:self action:@selector(deleteBroadcastView)];
  30. [self addSubview:deleteButton];
  31. [deleteButton makeConstraints:^(JXHConstraintMaker *make) {
  32. make.top.and.trailing.equalTo(0);
  33. make.size.equalTo(CGSizeMake(45, 45));
  34. }];
  35. UIImageView *deleteImageView = [[UIImageView alloc] initWithImage:jxh_getImage(notice_close)];
  36. [deleteButton addSubview:deleteImageView];
  37. [deleteImageView makeConstraints:^(JXHConstraintMaker *make) {
  38. make.size.equalTo(CGSizeMake(20, 20));
  39. make.center.equalTo(deleteButton);
  40. }];
  41. _broadcastLabel = [UILabel convenienceWithFont:spsb_font(13) text:@"" textColor:spsb_FF801A_color()];
  42. _broadcastLabel.backgroundColor = spsb_FDF8EC_color();
  43. [self addSubview:_broadcastLabel];
  44. [_broadcastLabel makeConstraints:^(JXHConstraintMaker *make) {
  45. make.leading.equalTo(15);
  46. make.centerY.equalTo(self);
  47. make.trailing.equalTo(-45);
  48. }];
  49. _animationView = [[UIView alloc] init];
  50. _animationView.layer.masksToBounds = true;
  51. _animationView.backgroundColor = spsb_FDF8EC_color();
  52. [self addSubview:_animationView];
  53. [_animationView makeConstraints:^(JXHConstraintMaker *make) {
  54. make.top.and.bottom.equalTo(0);
  55. make.leading.equalTo(15);
  56. make.trailing.equalTo(-45);
  57. }];
  58. _animationLabel = [UILabel convenienceWithFont:spsb_font(13) text:@"" textColor:spsb_FF801A_color()];
  59. _animationLabel.backgroundColor = spsb_FDF8EC_color();
  60. [_animationView addSubview:_animationLabel];
  61. [_animationLabel makeConstraints:^(JXHConstraintMaker *make) {
  62. make.leading.and.top.and.bottom.equalTo(0);
  63. }];
  64. _animationLabel.text = space;
  65. [_animationLabel sizeToFit];
  66. _spaceWidth = _animationLabel.bounds.size.width;
  67. return self;
  68. }
  69. - (void)deleteBroadcastView {
  70. _animationView.hidden = true;
  71. [_animationLabel.layer removeAnimationForKey:@"rollingAnimation"];
  72. _isAnimation = false;
  73. _reloadDataAction(0);
  74. }
  75. - (void)animationBeginFirst:(bool)flag {
  76. _isAnimation = true;
  77. CAKeyframeAnimation *animation = [CAKeyframeAnimation animationWithKeyPath:@"position"];
  78. if (flag) {
  79. CGFloat baseTime = (_broadcastWidth + _spaceWidth) / 50;
  80. CGFloat delay = 1 / (baseTime + 1);
  81. //设定关键帧位置,必须含起始与终止位置
  82. animation.values = @[[NSValue valueWithCGPoint:CGPointMake(_broadcastWidth + _spaceWidth / 2, SPConsultationBroadcastViewHeight / 2)],
  83. [NSValue valueWithCGPoint:CGPointMake(_broadcastWidth + _spaceWidth / 2, SPConsultationBroadcastViewHeight / 2)],
  84. [NSValue valueWithCGPoint:CGPointMake(-_spaceWidth / 2, SPConsultationBroadcastViewHeight / 2)]];
  85. //设定每个关键帧的时长,如果没有显式地设置,则默认每个帧的时间=总duration/(values.count - 1)
  86. animation.keyTimes = @[[NSNumber numberWithFloat:0.0],
  87. [NSNumber numberWithFloat:delay],
  88. [NSNumber numberWithFloat:1]];
  89. animation.timingFunctions = @[[CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionLinear], [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionLinear]];
  90. animation.delegate = self;
  91. animation.calculationMode = kCAAnimationLinear;
  92. animation.duration = baseTime + 1;
  93. } else {
  94. //设定关键帧位置,必须含起始与终止位置
  95. animation.values = @[[NSValue valueWithCGPoint:CGPointMake(_broadcastWidth + _spaceWidth / 2, SPConsultationBroadcastViewHeight / 2)],
  96. [NSValue valueWithCGPoint:CGPointMake(-_spaceWidth / 2, SPConsultationBroadcastViewHeight / 2)]];
  97. //设定每个关键帧的时长,如果没有显式地设置,则默认每个帧的时间=总duration/(values.count - 1)
  98. animation.keyTimes = @[[NSNumber numberWithFloat:0.0],
  99. [NSNumber numberWithFloat:1]];
  100. animation.timingFunctions = @[[CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionLinear], [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionLinear]];
  101. animation.delegate = self;
  102. animation.calculationMode = kCAAnimationLinear;
  103. animation.duration = (_broadcastWidth + _spaceWidth) / 50;
  104. }
  105. [_animationLabel.layer addAnimation:animation forKey:@"rollingAnimation"];
  106. }
  107. - (void)animationDidStop:(CAAnimation *)anim finished:(bool)flag {
  108. if (flag) {
  109. [_animationLabel.layer removeAnimationForKey:@"rollingAnimation"];
  110. [self animationBeginFirst:false];
  111. }
  112. }
  113. - (void)stopAnimation {
  114. if (_isAnimation) {
  115. [_animationLabel.layer removeAnimationForKey:@"rollingAnimation"];
  116. }
  117. }
  118. - (void)beginAnimation {
  119. if (_isAnimation) {
  120. [self animationBeginFirst:true];
  121. }
  122. }
  123. - (void)reloadData:(nullable NSString *)broadcastString {
  124. if (nil == broadcastString || broadcastString.length == 0) {
  125. [self deleteBroadcastView];
  126. return;
  127. }
  128. [_animationLabel.layer removeAnimationForKey:@"rollingAnimation"];
  129. _animationLabel.text = broadcastString;
  130. [_animationLabel sizeToFit];
  131. _broadcastWidth = _animationLabel.bounds.size.width;
  132. if (_broadcastWidth > LimitWidth) {
  133. _animationLabel.text = [NSString stringWithFormat:@"%@%@%@", broadcastString, space, broadcastString];
  134. [_animationLabel sizeToFit];
  135. _animationView.hidden = false;
  136. [self animationBeginFirst:true];
  137. } else {
  138. _animationView.hidden = true;
  139. _isAnimation = false;
  140. }
  141. _broadcastLabel.text = broadcastString;
  142. CGFloat height = SPConsultationBroadcastViewHeight;
  143. if ([broadcastString isEqualToString:@""]) {
  144. height = 0;
  145. }
  146. _reloadDataAction(height);
  147. }
  148. @end
  149. #undef LimitWidth