HMVideoSliderView.m 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360
  1. //
  2. // HMVideoSliderView.m
  3. // BuguLive
  4. //
  5. // Created by 范东 on 2018/12/27.
  6. // Copyright © 2018 xfg. All rights reserved.
  7. //
  8. #import "HMVideoSliderView.h"
  9. /** 滑块的大小 */
  10. #define kSliderBtnWH 19.0
  11. /** 间距 */
  12. #define kProgressMargin 2.0
  13. /** 进度的宽度 */
  14. #define kProgressW self.frame.size.width - kProgressMargin * 2
  15. /** 进度的高度 */
  16. #define kProgressH 3.0
  17. @interface HMVideoSliderView()
  18. /** 进度背景 */
  19. @property (nonatomic, strong) UIImageView *bgProgressView;
  20. /** 缓存进度 */
  21. @property (nonatomic, strong) UIImageView *bufferProgressView;
  22. /** 滑动进度 */
  23. @property (nonatomic, strong) UIImageView *sliderProgressView;
  24. /** 滑块 */
  25. @property (nonatomic, strong) HMSliderButton *sliderBtn;
  26. @property (nonatomic, assign) CGPoint lastPoint;
  27. @property (nonatomic, strong) UITapGestureRecognizer *tapGesture;
  28. @end
  29. @implementation HMVideoSliderView
  30. - (instancetype)initWithFrame:(CGRect)frame {
  31. if (self = [super initWithFrame:frame]) {
  32. self.allowTapped = YES;
  33. [self addSubViews];
  34. }
  35. return self;
  36. }
  37. - (void)awakeFromNib {
  38. [super awakeFromNib];
  39. self.allowTapped = YES;
  40. [self addSubViews];
  41. }
  42. - (void)layoutSubviews {
  43. [super layoutSubviews];
  44. if (self.sliderBtn.hidden) {
  45. self.bgProgressView.width = self.width;
  46. }else {
  47. self.bgProgressView.width = self.width - kProgressMargin * 2;
  48. }
  49. self.bgProgressView.centerY = self.height * 0.5;
  50. self.bufferProgressView.centerY = self.height * 0.5;
  51. self.sliderProgressView.centerY = self.height * 0.5;
  52. self.sliderBtn.centerY = self.height * 0.5;
  53. }
  54. /**
  55. 添加子视图
  56. */
  57. - (void)addSubViews {
  58. self.backgroundColor = [UIColor clearColor];
  59. [self addSubview:self.bgProgressView];
  60. [self addSubview:self.bufferProgressView];
  61. [self addSubview:self.sliderProgressView];
  62. [self addSubview:self.sliderBtn];
  63. // 初始化frame
  64. self.bgProgressView.frame = CGRectMake(kProgressMargin, 0, 0, kProgressH);
  65. self.bufferProgressView.frame = self.bgProgressView.frame;
  66. self.sliderProgressView.frame = self.bgProgressView.frame;
  67. self.sliderBtn.frame = CGRectMake(0, 0, kSliderBtnWH, kSliderBtnWH);
  68. // 添加点击手势
  69. self.tapGesture = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(tapped:)];
  70. [self addGestureRecognizer:self.tapGesture];
  71. }
  72. #pragma mark - Setter
  73. - (void)setMaximumTrackTintColor:(UIColor *)maximumTrackTintColor {
  74. _maximumTrackTintColor = maximumTrackTintColor;
  75. self.bgProgressView.backgroundColor = maximumTrackTintColor;
  76. }
  77. - (void)setMinimumTrackTintColor:(UIColor *)minimumTrackTintColor {
  78. _minimumTrackTintColor = minimumTrackTintColor;
  79. self.sliderProgressView.backgroundColor = minimumTrackTintColor;
  80. }
  81. - (void)setBufferTrackTintColor:(UIColor *)bufferTrackTintColor {
  82. _bufferTrackTintColor = bufferTrackTintColor;
  83. self.bufferProgressView.backgroundColor = bufferTrackTintColor;
  84. }
  85. - (void)setMaximumTrackImage:(UIImage *)maximumTrackImage {
  86. _maximumTrackImage = maximumTrackImage;
  87. self.bgProgressView.image = maximumTrackImage;
  88. self.maximumTrackTintColor = [UIColor clearColor];
  89. }
  90. - (void)setMinimumTrackImage:(UIImage *)minimumTrackImage {
  91. _minimumTrackImage = minimumTrackImage;
  92. self.sliderProgressView.image = minimumTrackImage;
  93. self.minimumTrackTintColor = [UIColor clearColor];
  94. }
  95. - (void)setBufferTrackImage:(UIImage *)bufferTrackImage {
  96. _bufferTrackImage = bufferTrackImage;
  97. self.bufferProgressView.image = bufferTrackImage;
  98. self.bufferTrackTintColor = [UIColor clearColor];
  99. }
  100. - (void)setValue:(float)value {
  101. _value = value;
  102. CGFloat finishValue = self.bgProgressView.width * value;
  103. self.sliderProgressView.width = finishValue;
  104. self.sliderBtn.left = (self.width - self.sliderBtn.width) * value;
  105. self.lastPoint = self.sliderBtn.center;
  106. }
  107. - (void)setBufferValue:(float)bufferValue {
  108. _bufferValue = bufferValue;
  109. CGFloat finishValue = self.bgProgressView.width * bufferValue;
  110. self.bufferProgressView.width = finishValue;
  111. }
  112. - (void)setBackgroundImage:(UIImage *)image forState:(UIControlState)state {
  113. [self.sliderBtn setBackgroundImage:image forState:state];
  114. [self.sliderBtn sizeToFit];
  115. }
  116. - (void)setThumbImage:(UIImage *)image forState:(UIControlState)state {
  117. [self.sliderBtn setImage:image forState:state];
  118. [self.sliderBtn sizeToFit];
  119. }
  120. - (void)showLoading {
  121. [self.sliderBtn showActivityAnim];
  122. }
  123. - (void)hideLoading {
  124. [self.sliderBtn hideActivityAnim];
  125. }
  126. - (void)setAllowTapped:(BOOL)allowTapped {
  127. _allowTapped = allowTapped;
  128. if (!allowTapped) {
  129. [self removeGestureRecognizer:self.tapGesture];
  130. }
  131. }
  132. - (void)setSliderHeight:(CGFloat)sliderHeight {
  133. _sliderHeight = sliderHeight;
  134. self.bgProgressView.height = sliderHeight;
  135. self.bufferProgressView.height = sliderHeight;
  136. self.sliderProgressView.height = sliderHeight;
  137. }
  138. - (void)setIsHideSliderBlock:(BOOL)isHideSliderBlock {
  139. _isHideSliderBlock = isHideSliderBlock;
  140. // 隐藏滑块,滑杆不可点击
  141. if (isHideSliderBlock) {
  142. self.sliderBtn.hidden = YES;
  143. self.bgProgressView.left = 0;
  144. self.bufferProgressView.left = 0;
  145. self.sliderProgressView.left = 0;
  146. self.allowTapped = NO;
  147. }
  148. }
  149. #pragma mark - User Action
  150. - (void)sliderBtnTouchBegin:(UIButton *)btn {
  151. if ([self.delegate respondsToSelector:@selector(sliderTouchBegan:)]) {
  152. [self.delegate sliderTouchBegan:self.value];
  153. }
  154. }
  155. - (void)sliderBtnTouchEnded:(UIButton *)btn {
  156. if ([self.delegate respondsToSelector:@selector(sliderTouchEnded:)]) {
  157. [self.delegate sliderTouchEnded:self.value];
  158. }
  159. }
  160. - (void)sliderBtnDragMoving:(UIButton *)btn event:(UIEvent *)event {
  161. // 点击的位置
  162. CGPoint point = [event.allTouches.anyObject locationInView:self];
  163. // 获取进度值 由于btn是从 0-(self.width - btn.width)
  164. float value = (point.x - btn.width * 0.5) / (self.width - btn.width);
  165. // value的值需在0-1之间
  166. value = value >= 1.0 ? 1.0 : value <= 0.0 ? 0.0 : value;
  167. [self setValue:value];
  168. if ([self.delegate respondsToSelector:@selector(sliderValueChanged:)]) {
  169. [self.delegate sliderValueChanged:value];
  170. }
  171. }
  172. - (void)tapped:(UITapGestureRecognizer *)tap {
  173. CGPoint point = [tap locationInView:self];
  174. // 获取进度
  175. float value = (point.x - self.bgProgressView.left) * 1.0 / self.bgProgressView.width;
  176. value = value >= 1.0 ? 1.0 : value <= 0 ? 0 : value;
  177. [self setValue:value];
  178. if ([self.delegate respondsToSelector:@selector(sliderTapped:)]) {
  179. [self.delegate sliderTapped:value];
  180. }
  181. }
  182. #pragma mark - 懒加载
  183. - (UIView *)bgProgressView {
  184. if (!_bgProgressView) {
  185. _bgProgressView = [UIImageView new];
  186. _bgProgressView.backgroundColor = [UIColor grayColor];
  187. _bgProgressView.contentMode = UIViewContentModeScaleAspectFill;
  188. _bgProgressView.clipsToBounds = YES;
  189. }
  190. return _bgProgressView;
  191. }
  192. - (UIView *)bufferProgressView {
  193. if (!_bufferProgressView) {
  194. _bufferProgressView = [UIImageView new];
  195. _bufferProgressView.backgroundColor = [UIColor whiteColor];
  196. _bufferProgressView.contentMode = UIViewContentModeScaleAspectFill;
  197. _bufferProgressView.clipsToBounds = YES;
  198. }
  199. return _bufferProgressView;
  200. }
  201. - (UIView *)sliderProgressView {
  202. if (!_sliderProgressView) {
  203. _sliderProgressView = [UIImageView new];
  204. _sliderProgressView.backgroundColor = [UIColor redColor];
  205. _sliderProgressView.contentMode = UIViewContentModeScaleAspectFill;
  206. _sliderProgressView.clipsToBounds = YES;
  207. }
  208. return _sliderProgressView;
  209. }
  210. - (HMSliderButton *)sliderBtn {
  211. if (!_sliderBtn) {
  212. _sliderBtn = [HMSliderButton new];
  213. // _sliderBtn.backgroundColor = [UIColor whiteColor];
  214. [_sliderBtn addTarget:self action:@selector(sliderBtnTouchBegin:) forControlEvents:UIControlEventTouchDown];
  215. [_sliderBtn addTarget:self action:@selector(sliderBtnTouchEnded:) forControlEvents:UIControlEventTouchCancel];
  216. [_sliderBtn addTarget:self action:@selector(sliderBtnTouchEnded:) forControlEvents:UIControlEventTouchUpInside];
  217. [_sliderBtn addTarget:self action:@selector(sliderBtnTouchEnded:) forControlEvents:UIControlEventTouchUpOutside];
  218. [_sliderBtn addTarget:self action:@selector(sliderBtnDragMoving:event:) forControlEvents:UIControlEventTouchDragInside];
  219. }
  220. return _sliderBtn;
  221. }
  222. /*
  223. // Only override drawRect: if you perform custom drawing.
  224. // An empty implementation adversely affects performance during animation.
  225. - (void)drawRect:(CGRect)rect {
  226. // Drawing code
  227. }
  228. */
  229. @end
  230. @interface HMSliderButton()
  231. @property (nonatomic, strong) UIActivityIndicatorView *indicatorView;
  232. @end
  233. @implementation HMSliderButton
  234. - (instancetype)initWithFrame:(CGRect)frame {
  235. if (self = [super initWithFrame:frame]) {
  236. self.indicatorView = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleGray];
  237. self.indicatorView.hidesWhenStopped = NO;
  238. self.indicatorView.userInteractionEnabled = NO;
  239. self.indicatorView.frame = CGRectMake(0, 0, 20, 20);
  240. self.indicatorView.transform = CGAffineTransformMakeScale(0.6, 0.6);
  241. [self addSubview:self.indicatorView];
  242. }
  243. return self;
  244. }
  245. - (void)layoutSubviews {
  246. [super layoutSubviews];
  247. self.indicatorView.center = CGPointMake(self.width / 2, self.height/ 2);
  248. self.indicatorView.transform = CGAffineTransformMakeScale(0.6, 0.6);
  249. }
  250. - (void)showActivityAnim {
  251. self.indicatorView.hidden = NO;
  252. [self.indicatorView startAnimating];
  253. }
  254. - (void)hideActivityAnim {
  255. self.indicatorView.hidden = YES;
  256. [self.indicatorView stopAnimating];
  257. }
  258. // 重写此方法将按钮的点击范围扩大
  259. - (BOOL)pointInside:(CGPoint)point withEvent:(UIEvent *)event {
  260. CGRect bounds = self.bounds;
  261. // 扩大点击区域
  262. bounds = CGRectInset(bounds, -20, -20);
  263. // 若点击的点在新的bounds里面。就返回yes
  264. return CGRectContainsPoint(bounds, point);
  265. }
  266. @end