From 62f338683747628bebe40fd199bed65b3a4825de Mon Sep 17 00:00:00 2001 From: Mustafa Yusuf Date: Mon, 8 May 2017 18:54:16 +0300 Subject: [PATCH 1/5] fixes non-storyboard use issues --- ABVideoRangeSlider/Classes/ABVideoRangeSlider.swift | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/ABVideoRangeSlider/Classes/ABVideoRangeSlider.swift b/ABVideoRangeSlider/Classes/ABVideoRangeSlider.swift index 8cb9b76..75b5ab1 100644 --- a/ABVideoRangeSlider/Classes/ABVideoRangeSlider.swift +++ b/ABVideoRangeSlider/Classes/ABVideoRangeSlider.swift @@ -83,6 +83,7 @@ public class ABVideoRangeSlider: UIView, UIGestureRecognizerDelegate { let startDrag = UIPanGestureRecognizer(target:self, action: #selector(startDragged(recognizer:))) + startIndicator.removeFromSuperview() startIndicator = ABStartIndicator(frame: CGRect(x: 0, y: -topBorderHeight, width: 20, @@ -96,6 +97,7 @@ public class ABVideoRangeSlider: UIView, UIGestureRecognizerDelegate { let endDrag = UIPanGestureRecognizer(target:self, action: #selector(endDragged(recognizer:))) + endIndicator.removeFromSuperview() endIndicator = ABEndIndicator(frame: CGRect(x: 0, y: -topBorderHeight, width: indicatorWidth, @@ -106,13 +108,14 @@ public class ABVideoRangeSlider: UIView, UIGestureRecognizerDelegate { // Setup Top and bottom line - + topLine.removeFromSuperview() topLine = ABBorder(frame: CGRect(x: 0, y: -topBorderHeight, width: indicatorWidth, height: topBorderHeight)) self.addSubview(topLine) + bottomLine.removeFromSuperview() bottomLine = ABBorder(frame: CGRect(x: 0, y: self.frame.size.height, width: indicatorWidth, @@ -129,6 +132,7 @@ public class ABVideoRangeSlider: UIView, UIGestureRecognizerDelegate { let progressDrag = UIPanGestureRecognizer(target:self, action: #selector(progressDragged(recognizer:))) + progressIndicator.removeFromSuperview() progressIndicator = ABProgressIndicator(frame: CGRect(x: 0, y: -topBorderHeight, width: 10, @@ -148,10 +152,12 @@ public class ABVideoRangeSlider: UIView, UIGestureRecognizerDelegate { // Setup time labels + startTimeView.removeFromSuperview() startTimeView = ABTimeView(size: CGSize(width: 60, height: 30), position: 1) startTimeView.layer.anchorPoint = CGPoint(x: 0.5, y: 0.5) self.addSubview(startTimeView) + endTimeView.removeFromSuperview() endTimeView = ABTimeView(size: CGSize(width: 60, height: 30), position: 1) endTimeView.layer.anchorPoint = CGPoint(x: 0.5, y: 0.5) self.addSubview(endTimeView) @@ -159,6 +165,7 @@ public class ABVideoRangeSlider: UIView, UIGestureRecognizerDelegate { public override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) { if keyPath == "bounds"{ + self.setup() self.updateThumbnails() } } From a0c11832c9ba25d36f193d89a43bd9f7e3215a28 Mon Sep 17 00:00:00 2001 From: Mustafa Yusuf Date: Mon, 8 May 2017 19:05:24 +0300 Subject: [PATCH 2/5] fixes crash when height is 0 --- ABVideoRangeSlider/Classes/ABVideoRangeSlider.swift | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/ABVideoRangeSlider/Classes/ABVideoRangeSlider.swift b/ABVideoRangeSlider/Classes/ABVideoRangeSlider.swift index 75b5ab1..b4d662f 100644 --- a/ABVideoRangeSlider/Classes/ABVideoRangeSlider.swift +++ b/ABVideoRangeSlider/Classes/ABVideoRangeSlider.swift @@ -231,7 +231,9 @@ public class ABVideoRangeSlider: UIView, UIGestureRecognizerDelegate { self.duration = ABVideoHelper.videoDuration(videoURL: videoURL) self.videoURL = videoURL self.superview?.layoutSubviews() - self.updateThumbnails() + if self.bounds.height != 0 { + self.updateThumbnails() + } } public func updateThumbnails(){ From 21952e9ef32ee3178f8eb57158ea44e536e028fb Mon Sep 17 00:00:00 2001 From: Mustafa Yusuf Date: Mon, 8 May 2017 19:24:41 +0300 Subject: [PATCH 3/5] replaces kvo for bounds with didSet --- .../Classes/ABVideoRangeSlider.swift | 104 +++++++++--------- 1 file changed, 51 insertions(+), 53 deletions(-) diff --git a/ABVideoRangeSlider/Classes/ABVideoRangeSlider.swift b/ABVideoRangeSlider/Classes/ABVideoRangeSlider.swift index b4d662f..9066e6b 100644 --- a/ABVideoRangeSlider/Classes/ABVideoRangeSlider.swift +++ b/ABVideoRangeSlider/Classes/ABVideoRangeSlider.swift @@ -11,7 +11,7 @@ import UIKit @objc public protocol ABVideoRangeSliderDelegate: class { func didChangeValue(videoRangeSlider: ABVideoRangeSlider, startTime: Float64, endTime: Float64) func indicatorDidChangePosition(videoRangeSlider: ABVideoRangeSlider, position: Float64) - + @objc optional func sliderGesturesBegan() @objc optional func sliderGesturesEnded() } @@ -22,7 +22,14 @@ public class ABVideoRangeSlider: UIView, UIGestureRecognizerDelegate { case start case end } - + + public override var bounds: CGRect { + didSet { + self.setup() + self.updateThumbnails() + } + } + public weak var delegate: ABVideoRangeSliderDelegate? = nil var startIndicator = ABStartIndicator() @@ -50,13 +57,13 @@ public class ABVideoRangeSlider: UIView, UIGestureRecognizerDelegate { public var minSpace: Float = 1 // In Seconds public var maxSpace: Float = 0 // In Seconds - + public var isProgressIndicatorSticky: Bool = false public var isProgressIndicatorDraggable: Bool = true - + var isUpdatingThumbnails = false var isReceivingGesture: Bool = false - + public enum ABTimeViewPosition{ case top case bottom @@ -122,11 +129,6 @@ public class ABVideoRangeSlider: UIView, UIGestureRecognizerDelegate { height: bottomBorderHeight)) self.addSubview(bottomLine) - self.addObserver(self, - forKeyPath: "bounds", - options: NSKeyValueObservingOptions(rawValue: 0), - context: nil) - // Setup Progress Indicator let progressDrag = UIPanGestureRecognizer(target:self, @@ -187,7 +189,7 @@ public class ABVideoRangeSlider: UIView, UIGestureRecognizerDelegate { public func updateProgressIndicator(seconds: Float64){ if !isReceivingGesture { let endSeconds = secondsFromValue(value: self.endPercentage) - + if seconds >= endSeconds { self.resetProgressPosition() } else { @@ -272,7 +274,7 @@ public class ABVideoRangeSlider: UIView, UIGestureRecognizerDelegate { currentIndicator: self.startIndicator ) } - + @objc private func endDragged(recognizer: UIPanGestureRecognizer){ self.processHandleDrag( recognizer: recognizer, @@ -288,17 +290,17 @@ public class ABVideoRangeSlider: UIView, UIGestureRecognizerDelegate { currentPositionPercentage: CGFloat, currentIndicator: UIView ) { - + self.updateGestureStatus(recognizer: recognizer) - + let translation = recognizer.translation(in: self) - + var position: CGFloat = positionFromValue(value: currentPositionPercentage) // self.startPercentage or self.endPercentage - + position = position + translation.x - + if position < 0 { position = 0 } - + if position > self.frame.size.width { position = self.frame.size.width } @@ -317,29 +319,29 @@ public class ABVideoRangeSlider: UIView, UIGestureRecognizerDelegate { } } } - + recognizer.setTranslation(CGPoint.zero, in: self) - + currentIndicator.center = CGPoint(x: position , y: currentIndicator.center.y) - + var percentage = currentIndicator.center.x * 100 / self.frame.width - + let startSeconds = secondsFromValue(value: self.startPercentage) let endSeconds = secondsFromValue(value: self.endPercentage) - + self.delegate?.didChangeValue(videoRangeSlider: self, startTime: startSeconds, endTime: endSeconds) - + var progressPosition: CGFloat = 0.0 - + if drag == .start { self.startPercentage = percentage } else { self.endPercentage = percentage } - + if drag == .start { progressPosition = positionFromValue(value: self.startPercentage) - + } else { if recognizer.state != .ended { progressPosition = positionFromValue(value: self.endPercentage) @@ -347,27 +349,27 @@ public class ABVideoRangeSlider: UIView, UIGestureRecognizerDelegate { progressPosition = positionFromValue(value: self.startPercentage) } } - + progressIndicator.center = CGPoint(x: progressPosition , y: progressIndicator.center.y) let progressPercentage = progressIndicator.center.x * 100 / self.frame.width - + if self.progressPercentage != progressPercentage { let progressSeconds = secondsFromValue(value: progressPercentage) self.delegate?.indicatorDidChangePosition(videoRangeSlider: self, position: progressSeconds) } - + self.progressPercentage = progressPercentage - + layoutSubviews() } - + func progressDragged(recognizer: UIPanGestureRecognizer){ if !isProgressIndicatorDraggable { return } - + updateGestureStatus(recognizer: recognizer) - + let translation = recognizer.translation(in: self) let positionLimitStart = positionFromValue(value: self.startPercentage) @@ -401,7 +403,7 @@ public class ABVideoRangeSlider: UIView, UIGestureRecognizerDelegate { func viewDragged(recognizer: UIPanGestureRecognizer){ updateGestureStatus(recognizer: recognizer) - + let translation = recognizer.translation(in: self) var progressPosition = positionFromValue(value: self.progressPercentage) @@ -450,13 +452,13 @@ public class ABVideoRangeSlider: UIView, UIGestureRecognizerDelegate { layoutSubviews() } - + // MARK: - Drag Functions Helpers private func positionFromValue(value: CGFloat) -> CGFloat{ let position = value * self.frame.size.width / 100 return position } - + private func getPositionLimits(with drag: DragHandleChoice) -> (min: CGFloat, max: CGFloat) { if drag == .start { return ( @@ -470,7 +472,7 @@ public class ABVideoRangeSlider: UIView, UIGestureRecognizerDelegate { ) } } - + private func checkEdgeCasesForPosition(with position: CGFloat, and positionLimit: CGFloat, and drag: DragHandleChoice) -> CGFloat { if drag == .start { if Float(self.duration) < self.minSpace { @@ -489,10 +491,10 @@ public class ABVideoRangeSlider: UIView, UIGestureRecognizerDelegate { } } } - + return position } - + private func secondsFromValue(value: CGFloat) -> Float64{ return duration * Float64((value / 100)) } @@ -500,25 +502,25 @@ public class ABVideoRangeSlider: UIView, UIGestureRecognizerDelegate { private func valueFromSeconds(seconds: Float) -> CGFloat{ return CGFloat(seconds * 100) / CGFloat(duration) } - + private func updateGestureStatus(recognizer: UIGestureRecognizer) { if recognizer.state == .began { - + self.isReceivingGesture = true self.delegate?.sliderGesturesBegan?() - + } else if recognizer.state == .ended { - + self.isReceivingGesture = false self.delegate?.sliderGesturesEnded?() } } - + private func resetProgressPosition() { self.progressPercentage = self.startPercentage let progressPosition = positionFromValue(value: self.progressPercentage) progressIndicator.center = CGPoint(x: progressPosition , y: progressIndicator.center.y) - + let startSeconds = secondsFromValue(value: self.progressPercentage) self.delegate?.indicatorDidChangePosition(videoRangeSlider: self, position: startSeconds) } @@ -567,21 +569,17 @@ public class ABVideoRangeSlider: UIView, UIGestureRecognizerDelegate { height: self.frame.size.height + topLine.frame.size.height + bottomLine.frame.size.height) return extendedBounds.contains(point) } - - + + private func secondsToFormattedString(totalSeconds: Float64) -> String{ let hours:Int = Int(totalSeconds.truncatingRemainder(dividingBy: 86400) / 3600) let minutes:Int = Int(totalSeconds.truncatingRemainder(dividingBy: 3600) / 60) let seconds:Int = Int(totalSeconds.truncatingRemainder(dividingBy: 60)) - + if hours > 0 { return String(format: "%i:%02i:%02i", hours, minutes, seconds) } else { return String(format: "%02i:%02i", minutes, seconds) } } - - deinit { - removeObserver(self, forKeyPath: "bounds") - } } From cd470bea683529b096b8d09f42815f9d1d59048f Mon Sep 17 00:00:00 2001 From: Mustafa Yusuf Date: Mon, 8 May 2017 20:08:47 +0300 Subject: [PATCH 4/5] fixes issue with endpercantage --- ABVideoRangeSlider/Classes/ABVideoRangeSlider.swift | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/ABVideoRangeSlider/Classes/ABVideoRangeSlider.swift b/ABVideoRangeSlider/Classes/ABVideoRangeSlider.swift index 9066e6b..8c15232 100644 --- a/ABVideoRangeSlider/Classes/ABVideoRangeSlider.swift +++ b/ABVideoRangeSlider/Classes/ABVideoRangeSlider.swift @@ -56,7 +56,13 @@ public class ABVideoRangeSlider: UIView, UIGestureRecognizerDelegate { let indicatorWidth: CGFloat = 20.0 public var minSpace: Float = 1 // In Seconds - public var maxSpace: Float = 0 // In Seconds + public var maxSpace: Float = 0 { // In Seconds + didSet { + let percentage = maxSpace/Float(self.duration) * 100 + self.endPercentage = min(CGFloat(percentage), 100.0) + self.layoutIfNeeded() + } + } public var isProgressIndicatorSticky: Bool = false public var isProgressIndicatorDraggable: Bool = true From 209db9c690d4f964fde763292e808da89dbfb18f Mon Sep 17 00:00:00 2001 From: Mustafa Yusuf Date: Mon, 8 May 2017 21:23:27 +0300 Subject: [PATCH 5/5] adds property hidesTimeViews --- ABVideoRangeSlider/Classes/ABVideoRangeSlider.swift | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/ABVideoRangeSlider/Classes/ABVideoRangeSlider.swift b/ABVideoRangeSlider/Classes/ABVideoRangeSlider.swift index 8c15232..ff6a5c4 100644 --- a/ABVideoRangeSlider/Classes/ABVideoRangeSlider.swift +++ b/ABVideoRangeSlider/Classes/ABVideoRangeSlider.swift @@ -30,6 +30,8 @@ public class ABVideoRangeSlider: UIView, UIGestureRecognizerDelegate { } } + public var hidesTimeViews = true + public weak var delegate: ABVideoRangeSliderDelegate? = nil var startIndicator = ABStartIndicator() @@ -163,11 +165,13 @@ public class ABVideoRangeSlider: UIView, UIGestureRecognizerDelegate { startTimeView.removeFromSuperview() startTimeView = ABTimeView(size: CGSize(width: 60, height: 30), position: 1) startTimeView.layer.anchorPoint = CGPoint(x: 0.5, y: 0.5) + startTimeView.isHidden = hidesTimeViews self.addSubview(startTimeView) endTimeView.removeFromSuperview() endTimeView = ABTimeView(size: CGSize(width: 60, height: 30), position: 1) endTimeView.layer.anchorPoint = CGPoint(x: 0.5, y: 0.5) + endTimeView.isHidden = hidesTimeViews self.addSubview(endTimeView) }