VLCTransportBar.m 8.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236
  1. /*****************************************************************************
  2. * VLC for iOS
  3. *****************************************************************************
  4. * Copyright (c) 2015 VideoLAN. All rights reserved.
  5. * $Id$
  6. *
  7. * Authors: Tobias Conradi <videolan # tobias-conradi.de>
  8. *
  9. * Refer to the COPYING file of the official project for license.
  10. *****************************************************************************/
  11. #import "VLCTransportBar.h"
  12. #import "VLCBufferingBar.h"
  13. @interface VLCTransportBar ()
  14. @property (nonatomic) VLCBufferingBar *bufferingBar;
  15. @property (nonatomic) UIView *playbackPositionMarker;
  16. @property (nonatomic) UIView *scrubbingPostionMarker;
  17. @property (nonatomic) UIImageView *leftHintImageView;
  18. @property (nonatomic) UIImageView *rightHintImageView;
  19. @end
  20. @implementation VLCTransportBar
  21. static const CGFloat VLCTransportBarMarkerWidth = 2.0;
  22. static inline void sharedSetup(VLCTransportBar *self) {
  23. CGRect bounds = self.bounds;
  24. // Bar:
  25. VLCBufferingBar *bar = [[VLCBufferingBar alloc] initWithFrame:bounds];
  26. UIColor *barColor = [UIColor lightGrayColor];
  27. bar.bufferColor = barColor;
  28. bar.borderColor = barColor;
  29. bar.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
  30. bar.bufferStartFraction = self.bufferStartFraction;
  31. bar.bufferEndFraction = self.bufferEndFraction;
  32. self.bufferingBar = bar;
  33. [self addSubview:bar];
  34. // Marker:
  35. UIColor *markerColor = [UIColor whiteColor];
  36. UIView *playbackMarker = [[UIView alloc] initWithFrame:CGRectMake(0, 0, VLCTransportBarMarkerWidth, CGRectGetHeight(bounds))];
  37. playbackMarker.autoresizingMask = UIViewAutoresizingFlexibleHeight;
  38. playbackMarker.backgroundColor = markerColor;
  39. [self addSubview:playbackMarker];
  40. self.playbackPositionMarker = playbackMarker;
  41. UIView *scrubbingMarker = [[UIView alloc] initWithFrame:CGRectMake(0, 0, VLCTransportBarMarkerWidth, CGRectGetHeight(bounds))];
  42. [self addSubview:scrubbingMarker];
  43. scrubbingMarker.backgroundColor = markerColor;
  44. self.scrubbingPostionMarker = scrubbingMarker;
  45. // Labels:
  46. CGFloat size = [UIFont preferredFontForTextStyle:UIFontTextStyleCallout].pointSize;
  47. UIFont *font = [UIFont monospacedDigitSystemFontOfSize:size weight:UIFontWeightSemibold];
  48. UIColor *textColor = [UIColor whiteColor];
  49. UILabel *markerLabel = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, 10, 10)];
  50. markerLabel.font = font;
  51. markerLabel.textColor = textColor;
  52. [self addSubview:markerLabel];
  53. self->_markerTimeLabel = markerLabel;
  54. UILabel *remainingLabel = [[UILabel alloc] initWithFrame:CGRectZero];
  55. remainingLabel.font = font;
  56. remainingLabel.textColor = textColor;
  57. [self addSubview:remainingLabel];
  58. self->_remainingTimeLabel = remainingLabel;
  59. CGFloat iconLength = 32.0;
  60. CGRect imageRect = CGRectMake(0, 0, iconLength, iconLength);
  61. UIImageView *leftHintImageView = [[UIImageView alloc] initWithFrame:imageRect];
  62. [self addSubview:leftHintImageView];
  63. self.leftHintImageView = leftHintImageView;
  64. UIImageView *rightHintImageView = [[UIImageView alloc] initWithFrame:imageRect];
  65. [self addSubview:rightHintImageView];
  66. self.rightHintImageView = rightHintImageView;
  67. }
  68. - (instancetype)initWithFrame:(CGRect)frame
  69. {
  70. self = [super initWithFrame:frame];
  71. if (self) {
  72. sharedSetup(self);
  73. }
  74. return self;
  75. }
  76. - (void)awakeFromNib {
  77. [super awakeFromNib];
  78. sharedSetup(self);
  79. }
  80. - (void)setBufferStartFraction:(CGFloat)bufferStartFraction {
  81. CGFloat fraction = MAX(0.0, MIN(bufferStartFraction, 1.0));
  82. _bufferStartFraction = fraction;
  83. self.bufferingBar.bufferStartFraction = fraction;
  84. }
  85. - (void)setBufferEndFraction:(CGFloat)bufferEndFraction {
  86. CGFloat fraction = MAX(0.0, MIN(bufferEndFraction, 1.0));
  87. _bufferEndFraction = fraction;
  88. self.bufferingBar.bufferEndFraction = fraction;
  89. }
  90. - (void)setPlaybackFraction:(CGFloat)playbackFraction {
  91. CGFloat fraction = MAX(0.0, MIN(playbackFraction, 1.0));
  92. _playbackFraction = fraction;
  93. if (!self.scrubbing) {
  94. [self setScrubbingFraction:fraction];
  95. }
  96. [self setNeedsLayout];
  97. }
  98. - (void)setScrubbingFraction:(CGFloat)scrubbingFraction {
  99. _scrubbingFraction = MAX(0.0, MIN(scrubbingFraction, 1.0));
  100. [self setNeedsLayout];
  101. }
  102. - (void)setScrubbing:(BOOL)scrubbing {
  103. _scrubbing = scrubbing;
  104. [self setNeedsLayout];
  105. }
  106. - (UIImage *)imageForHint:(VLCTransportBarHint)hint
  107. {
  108. NSString *imageName = nil;
  109. switch (hint) {
  110. case VLCTransportBarHintScanForward:
  111. imageName = @"NowPlayingFastForward.png";
  112. break;
  113. case VLCTransportBarHintJumpForward10:
  114. imageName = @"NowPlayingSkip10Forward.png";
  115. break;
  116. case VLCTransportBarHintJumpBackward10:
  117. imageName = @"NowPlayingSkip10Backward.png";
  118. break;
  119. default:
  120. break;
  121. }
  122. if (imageName) {
  123. return [UIImage imageNamed:imageName];
  124. }
  125. return nil;
  126. }
  127. - (void)setHint:(VLCTransportBarHint)hint
  128. {
  129. _hint = hint;
  130. UIImage *leftImage = nil;
  131. UIImage *rightImage = nil;
  132. switch (hint) {
  133. case VLCTransportBarHintScanForward:
  134. case VLCTransportBarHintJumpForward10:
  135. rightImage = [self imageForHint:hint];
  136. break;
  137. case VLCTransportBarHintJumpBackward10:
  138. leftImage = [self imageForHint:hint];
  139. break;
  140. default:
  141. break;
  142. }
  143. // TODO: add animations
  144. self.leftHintImageView.image = leftImage;
  145. self.rightHintImageView.image = rightImage;
  146. }
  147. - (void)layoutSubviews {
  148. [super layoutSubviews];
  149. const CGRect bounds = self.bounds;
  150. const CGFloat width = CGRectGetWidth(bounds)-VLCTransportBarMarkerWidth;
  151. self.playbackPositionMarker.center = CGPointMake(width*self.playbackFraction+VLCTransportBarMarkerWidth/2.0,
  152. CGRectGetMidY(bounds));
  153. const BOOL withThumbnail = NO;
  154. const CGRect scrubberFrame = scrubbingMarkerFrameForBounds_fraction_withThumb(bounds,
  155. self.scrubbingFraction,
  156. withThumbnail);
  157. self.scrubbingPostionMarker.frame = scrubberFrame;
  158. UILabel *remainingLabel = self.remainingTimeLabel;
  159. [remainingLabel sizeToFit];
  160. CGRect remainingLabelFrame = remainingLabel.frame;
  161. remainingLabelFrame.origin.y = CGRectGetMaxY(bounds)+15.0;
  162. remainingLabelFrame.origin.x = width-CGRectGetWidth(remainingLabelFrame);
  163. remainingLabel.frame = remainingLabelFrame;
  164. UILabel *markerLabel = self.markerTimeLabel;
  165. [markerLabel sizeToFit];
  166. CGPoint timeLabelCenter = remainingLabel.center;
  167. timeLabelCenter.x = self.scrubbingPostionMarker.center.x;
  168. markerLabel.center = timeLabelCenter;
  169. CGRect markerLabelFrame = markerLabel.frame;
  170. UIImageView *leftHint = self.leftHintImageView;
  171. CGFloat leftImageSize = CGRectGetWidth(leftHint.bounds);
  172. leftHint.center = CGPointMake(CGRectGetMinX(markerLabelFrame)-leftImageSize, timeLabelCenter.y);
  173. UIImageView *rightHint = self.rightHintImageView;
  174. CGFloat rightImageSize = CGRectGetWidth(rightHint.bounds);
  175. rightHint.center = CGPointMake(CGRectGetMaxX(markerLabelFrame)+rightImageSize, timeLabelCenter.y);
  176. CGFloat remainingAlfa = CGRectIntersectsRect(markerLabel.frame, remainingLabelFrame) ? 0.0 : 1.0;
  177. remainingLabel.alpha = remainingAlfa;
  178. }
  179. static CGRect scrubbingMarkerFrameForBounds_fraction_withThumb(CGRect bounds, CGFloat fraction, BOOL withThumbnail) {
  180. const CGFloat width = CGRectGetWidth(bounds)-VLCTransportBarMarkerWidth;
  181. const CGFloat height = CGRectGetHeight(bounds);
  182. // when scrubbing marker is 4x instead of 3x bar heigt
  183. const CGFloat scrubbingHeight = height * (withThumbnail ? 4.0 : 3.0);
  184. // x position is always center of marker == view width * fraction
  185. const CGFloat scrubbingXPosition = width*fraction;
  186. CGFloat scrubbingYPosition = 0;
  187. if (withThumbnail) {
  188. // scrubbing marker bottom and bar buttom are same
  189. scrubbingYPosition = height-scrubbingHeight;
  190. } else {
  191. // scrubbing marker y center == bar y center
  192. scrubbingYPosition = height/2.0 - scrubbingHeight/2.0;
  193. }
  194. return CGRectMake(scrubbingXPosition,
  195. scrubbingYPosition,
  196. VLCTransportBarMarkerWidth,
  197. scrubbingHeight);
  198. }
  199. @end