123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426 |
- //
- // ZFSliderView.m
- // ZFPlayer
- //
- // Copyright (c) 2016年 任子丰 ( http://github.com/renzifeng )
- //
- // Permission is hereby granted, free of charge, to any person obtaining a copy
- // of this software and associated documentation files (the "Software"), to deal
- // in the Software without restriction, including without limitation the rights
- // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- // copies of the Software, and to permit persons to whom the Software is
- // furnished to do so, subject to the following conditions:
- //
- // The above copyright notice and this permission notice shall be included in
- // all copies or substantial portions of the Software.
- //
- // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- // THE SOFTWARE.
- #import "ZFSliderView.h"
- #import "UIView+ZFFrame.h"
- /** 滑块的大小 */
- static const CGFloat kSliderBtnWH = 19.0;
- /** 进度的高度 */
- static const CGFloat kProgressH = 1.0;
- /** 拖动slider动画的时间*/
- static const CGFloat kAnimate = 0.3;
- @implementation ZFSliderButton
- // 重写此方法将按钮的点击范围扩大
- - (BOOL)pointInside:(CGPoint)point withEvent:(UIEvent *)event {
- CGRect bounds = self.bounds;
- // 扩大点击区域
- bounds = CGRectInset(bounds, -20, -20);
- // 若点击的点在新的bounds里面。就返回yes
- return CGRectContainsPoint(bounds, point);
- }
- @end
- @interface ZFSliderView ()
- /** 进度背景 */
- @property (nonatomic, strong) UIImageView *bgProgressView;
- /** 缓存进度 */
- @property (nonatomic, strong) UIImageView *bufferProgressView;
- /** 滑动进度 */
- @property (nonatomic, strong) UIImageView *sliderProgressView;
- /** 滑块 */
- @property (nonatomic, strong) ZFSliderButton *sliderBtn;
- @property (nonatomic, strong) UIView *loadingBarView;
- @property (nonatomic, assign) BOOL isLoading;
- @property (nonatomic, strong) UITapGestureRecognizer *tapGesture;
- @end
- @implementation ZFSliderView
- - (instancetype)initWithFrame:(CGRect)frame {
- if (self = [super initWithFrame:frame]) {
- self.allowTapped = YES;
- self.animate = YES;
- [self addSubViews];
- }
- return self;
- }
- - (void)awakeFromNib {
- [super awakeFromNib];
- self.allowTapped = YES;
- self.animate = YES;
- [self addSubViews];
- }
- - (void)layoutSubviews {
- [super layoutSubviews];
- if (isnan(self.value) || isnan(self.bufferValue)) return;
- CGFloat min_x = 0;
- CGFloat min_y = 0;
- CGFloat min_w = 0;
- CGFloat min_h = 0;
- CGFloat min_view_w = self.bounds.size.width;
- CGFloat min_view_h = self.bounds.size.height;
-
- min_x = 0;
- min_w = min_view_w;
- min_y = 0;
- min_h = self.sliderHeight;
- self.bgProgressView.frame = CGRectMake(min_x, min_y, min_w, min_h);
-
- min_x = 0;
- min_y = 0;
- min_w = self.thumbSize.width;
- min_h = self.thumbSize.height;
- self.sliderBtn.frame = CGRectMake(min_x, min_y, min_w, min_h);
- self.sliderBtn.zf_centerX = self.bgProgressView.zf_width * self.value;
-
- min_x = 0;
- min_y = 0;
- if (self.sliderBtn.hidden) {
- min_w = self.bgProgressView.zf_width * self.value;
- } else {
- min_w = self.sliderBtn.zf_centerX;
- }
- min_h = self.sliderHeight;
- self.sliderProgressView.frame = CGRectMake(min_x, min_y, min_w, min_h);
-
- min_x = 0;
- min_y = 0;
- min_w = self.bgProgressView.zf_width * self.bufferValue;
- min_h = self.sliderHeight;
- self.bufferProgressView.frame = CGRectMake(min_x, min_y, min_w, min_h);
-
- min_w = 0.1;
- min_h = self.sliderHeight;
- min_x = (min_view_w - min_w)/2;
- min_y = (min_view_h - min_h)/2;
- self.loadingBarView.frame = CGRectMake(min_x, min_y, min_w, min_h);
-
- self.bgProgressView.zf_centerY = min_view_h * 0.5;
- self.bufferProgressView.zf_centerY = min_view_h * 0.5;
- self.sliderProgressView.zf_centerY = min_view_h * 0.5;
- self.sliderBtn.zf_centerY = min_view_h * 0.5;
- }
- /**
- 添加子视图
- */
- - (void)addSubViews {
- self.thumbSize = CGSizeMake(kSliderBtnWH, kSliderBtnWH);
- self.sliderHeight = kProgressH;
- self.backgroundColor = [UIColor clearColor];
- [self addSubview:self.bgProgressView];
- [self addSubview:self.bufferProgressView];
- [self addSubview:self.sliderProgressView];
- [self addSubview:self.sliderBtn];
- [self addSubview:self.loadingBarView];
-
- // 添加点击手势
- self.tapGesture = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(tapped:)];
- [self addGestureRecognizer:self.tapGesture];
-
- // 添加滑动手势
- UIPanGestureRecognizer *sliderGesture = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(sliderGesture:)];
- [self addGestureRecognizer:sliderGesture];
- }
- #pragma mark - Setter
- - (void)setMaximumTrackTintColor:(UIColor *)maximumTrackTintColor {
- _maximumTrackTintColor = maximumTrackTintColor;
- self.bgProgressView.backgroundColor = maximumTrackTintColor;
- }
- - (void)setMinimumTrackTintColor:(UIColor *)minimumTrackTintColor {
- _minimumTrackTintColor = minimumTrackTintColor;
- self.sliderProgressView.backgroundColor = minimumTrackTintColor;
- }
- - (void)setBufferTrackTintColor:(UIColor *)bufferTrackTintColor {
- _bufferTrackTintColor = bufferTrackTintColor;
- self.bufferProgressView.backgroundColor = bufferTrackTintColor;
- }
- - (void)setLoadingTintColor:(UIColor *)loadingTintColor {
- _loadingTintColor = loadingTintColor;
- self.loadingBarView.backgroundColor = loadingTintColor;
- }
- - (void)setMaximumTrackImage:(UIImage *)maximumTrackImage {
- _maximumTrackImage = maximumTrackImage;
- self.bgProgressView.image = maximumTrackImage;
- self.maximumTrackTintColor = [UIColor clearColor];
- }
- - (void)setMinimumTrackImage:(UIImage *)minimumTrackImage {
- _minimumTrackImage = minimumTrackImage;
- self.sliderProgressView.image = minimumTrackImage;
- self.minimumTrackTintColor = [UIColor clearColor];
- }
- - (void)setBufferTrackImage:(UIImage *)bufferTrackImage {
- _bufferTrackImage = bufferTrackImage;
- self.bufferProgressView.image = bufferTrackImage;
- self.bufferTrackTintColor = [UIColor clearColor];
- }
- - (void)setBackgroundImage:(UIImage *)image forState:(UIControlState)state {
- [self.sliderBtn setBackgroundImage:image forState:state];
- }
- - (void)setThumbImage:(UIImage *)image forState:(UIControlState)state {
- [self.sliderBtn setImage:image forState:state];
- }
- - (void)setValue:(float)value {
- if (isnan(value)) return;
- value = MIN(1.0, value);
- _value = value;
- if (self.sliderBtn.hidden) {
- self.sliderProgressView.zf_width = self.bgProgressView.zf_width * value;
- } else {
- self.sliderBtn.zf_centerX = self.bgProgressView.zf_width * value;
- self.sliderProgressView.zf_width = self.sliderBtn.zf_centerX;
- }
- }
- - (void)setBufferValue:(float)bufferValue {
- if (isnan(bufferValue)) return;
- bufferValue = MIN(1.0, bufferValue);
- _bufferValue = bufferValue;
- self.bufferProgressView.zf_width = self.bgProgressView.zf_width * bufferValue;
- }
- - (void)setAllowTapped:(BOOL)allowTapped {
- _allowTapped = allowTapped;
- if (!allowTapped) {
- [self removeGestureRecognizer:self.tapGesture];
- }
- }
- - (void)setSliderHeight:(CGFloat)sliderHeight {
- if (isnan(sliderHeight)) return;
- _sliderHeight = sliderHeight;
- self.bgProgressView.zf_height = sliderHeight;
- self.bufferProgressView.zf_height = sliderHeight;
- self.sliderProgressView.zf_height = sliderHeight;
- }
- - (void)setSliderRadius:(CGFloat)sliderRadius {
- if (isnan(sliderRadius)) return;
- _sliderRadius = sliderRadius;
- self.bgProgressView.layer.cornerRadius = sliderRadius;
- self.bufferProgressView.layer.cornerRadius = sliderRadius;
- self.sliderProgressView.layer.cornerRadius = sliderRadius;
- self.bgProgressView.layer.masksToBounds = YES;
- self.bufferProgressView.layer.masksToBounds = YES;
- self.sliderProgressView.layer.masksToBounds = YES;
- }
- - (void)setIsHideSliderBlock:(BOOL)isHideSliderBlock {
- _isHideSliderBlock = isHideSliderBlock;
- // 隐藏滑块,滑杆不可点击
- if (isHideSliderBlock) {
- self.sliderBtn.hidden = YES;
- self.bgProgressView.zf_left = 0;
- self.bufferProgressView.zf_left = 0;
- self.sliderProgressView.zf_left = 0;
- self.allowTapped = NO;
- }
- }
- /**
- * Starts animation of the spinner.
- */
- - (void)startAnimating {
- if (self.isLoading) return;
- self.isLoading = YES;
- self.bufferProgressView.hidden = YES;
- self.sliderProgressView.hidden = YES;
- self.sliderBtn.hidden = YES;
- self.loadingBarView.hidden = NO;
-
- [self.loadingBarView.layer removeAllAnimations];
- CAAnimationGroup *animationGroup = [[CAAnimationGroup alloc] init];
- animationGroup.duration = 0.4;
- animationGroup.beginTime = CACurrentMediaTime() + 0.4;
- animationGroup.repeatCount = MAXFLOAT;
- animationGroup.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionLinear];
-
- CABasicAnimation *scaleAnimation = [CABasicAnimation animation];
- scaleAnimation.keyPath = @"transform.scale.x";
- scaleAnimation.fromValue = @(1000.0f);
- scaleAnimation.toValue = @(self.zf_width * 10);
-
- CABasicAnimation *alphaAnimation = [CABasicAnimation animation];
- alphaAnimation.keyPath = @"opacity";
- alphaAnimation.fromValue = @(1.0f);
- alphaAnimation.toValue = @(0.0f);
-
- [animationGroup setAnimations:@[scaleAnimation, alphaAnimation]];
- [self.loadingBarView.layer addAnimation:animationGroup forKey:@"loading"];
- }
- /**
- * Stops animation of the spinnner.
- */
- - (void)stopAnimating {
- self.isLoading = NO;
- self.bufferProgressView.hidden = NO;
- self.sliderProgressView.hidden = NO;
- self.sliderBtn.hidden = self.isHideSliderBlock;
- self.loadingBarView.hidden = YES;
- [self.loadingBarView.layer removeAllAnimations];
- }
- #pragma mark - User Action
- - (void)sliderGesture:(UIGestureRecognizer *)gesture {
- switch (gesture.state) {
- case UIGestureRecognizerStateBegan: {
- [self sliderBtnTouchBegin:self.sliderBtn];
- }
- break;
- case UIGestureRecognizerStateChanged: {
- [self sliderBtnDragMoving:self.sliderBtn point:[gesture locationInView:self.bgProgressView]];
- }
- break;
- case UIGestureRecognizerStateEnded: {
- [self sliderBtnTouchEnded:self.sliderBtn];
- }
- break;
- default:
- break;
- }
- }
- - (void)sliderBtnTouchBegin:(UIButton *)btn {
- if ([self.delegate respondsToSelector:@selector(sliderTouchBegan:)]) {
- [self.delegate sliderTouchBegan:self.value];
- }
- if (self.animate) {
- [UIView animateWithDuration:kAnimate animations:^{
- btn.transform = CGAffineTransformMakeScale(1.2, 1.2);
- }];
- }
- }
- - (void)sliderBtnTouchEnded:(UIButton *)btn {
- if ([self.delegate respondsToSelector:@selector(sliderTouchEnded:)]) {
- [self.delegate sliderTouchEnded:self.value];
- }
- if (self.animate) {
- [UIView animateWithDuration:kAnimate animations:^{
- btn.transform = CGAffineTransformIdentity;
- }];
- }
- }
- - (void)sliderBtnDragMoving:(UIButton *)btn point:(CGPoint)touchPoint {
- // 点击的位置
- CGPoint point = touchPoint;
- // 获取进度值 由于btn是从 0-(self.width - btn.width)
- CGFloat value = (point.x - btn.zf_width * 0.5) / self.bgProgressView.zf_width;
- // value的值需在0-1之间
- value = value >= 1.0 ? 1.0 : value <= 0.0 ? 0.0 : value;
- if (self.value == value) return;
- self.isForward = self.value < value;
- self.value = value;
- if ([self.delegate respondsToSelector:@selector(sliderValueChanged:)]) {
- [self.delegate sliderValueChanged:value];
- }
- }
- - (void)tapped:(UITapGestureRecognizer *)tap {
- CGPoint point = [tap locationInView:self.bgProgressView];
- // 获取进度
- CGFloat value = (point.x - self.sliderBtn.zf_width * 0.5) * 1.0 / self.bgProgressView.zf_width;
- value = value >= 1.0 ? 1.0 : value <= 0 ? 0 : value;
- self.value = value;
- if ([self.delegate respondsToSelector:@selector(sliderTapped:)]) {
- [self.delegate sliderTapped:value];
- }
- }
- #pragma mark - getter
- - (UIView *)bgProgressView {
- if (!_bgProgressView) {
- _bgProgressView = [UIImageView new];
- _bgProgressView.backgroundColor = [UIColor grayColor];
- _bgProgressView.contentMode = UIViewContentModeScaleAspectFill;
- _bgProgressView.clipsToBounds = YES;
- }
- return _bgProgressView;
- }
- - (UIView *)bufferProgressView {
- if (!_bufferProgressView) {
- _bufferProgressView = [UIImageView new];
- _bufferProgressView.backgroundColor = [UIColor whiteColor];
- _bufferProgressView.contentMode = UIViewContentModeScaleAspectFill;
- _bufferProgressView.clipsToBounds = YES;
- }
- return _bufferProgressView;
- }
- - (UIView *)sliderProgressView {
- if (!_sliderProgressView) {
- _sliderProgressView = [UIImageView new];
- _sliderProgressView.backgroundColor = [UIColor redColor];
- _sliderProgressView.contentMode = UIViewContentModeScaleAspectFill;
- _sliderProgressView.clipsToBounds = YES;
- }
- return _sliderProgressView;
- }
- - (ZFSliderButton *)sliderBtn {
- if (!_sliderBtn) {
- _sliderBtn = [ZFSliderButton buttonWithType:UIButtonTypeCustom];
- [_sliderBtn setAdjustsImageWhenHighlighted:NO];
- }
- return _sliderBtn;
- }
- - (UIView *)loadingBarView {
- if (!_loadingBarView) {
- _loadingBarView = [[UIView alloc] init];
- _loadingBarView.backgroundColor = [UIColor whiteColor];
- _loadingBarView.hidden = YES;
- }
- return _loadingBarView;
- }
- @end
|