diff --git a/VDS/Components/CarouselScrollbar/CarouselScrollbar.swift b/VDS/Components/CarouselScrollbar/CarouselScrollbar.swift index 918c4864..8ed8cfde 100644 --- a/VDS/Components/CarouselScrollbar/CarouselScrollbar.swift +++ b/VDS/Components/CarouselScrollbar/CarouselScrollbar.swift @@ -44,11 +44,12 @@ open class CarouselScrollbar: View { _numberOfSlides = 1 } setThumbWidth() + setThumb(position) setNeedsUpdate() } } - /// The amount of slides visible in the carousel container at one time. + /// The number of slides that can appear at once in a set in a carousel container. open var selectedLayout: Layout? { get { return _selectedLayout } set { @@ -58,11 +59,12 @@ open class CarouselScrollbar: View { _selectedLayout = .oneUP } setThumbWidth() + setThumb(position) setNeedsUpdate() } } - /// Enum used to describe the amount of slides visible in the carousel container at one time. + /// Enum used to describe the number of slides that can appear at once in a set in a carousel container. public enum Layout: String, CaseIterable { case oneUP = "1UP" case twoUP = "2UP" @@ -93,7 +95,19 @@ open class CarouselScrollbar: View { } /// Used to set the position of the thumb(scrubber). This is used when the carousel container changes position, it will align the position of thumb(scrubber). - open var position: Int? { didSet { setNeedsUpdate() } } + open var position: Int? { + get { return _position } + set { + if let newValue { + checkPositions() + _position = (newValue > totalPositions ?? 1) ? totalPositions : newValue + } else { + _position = 1 + } + setThumb(position) + setNeedsUpdate() + } + } /// Allows a unique id to be passed into the thumb and track of the thumb(scrubber). open var scrubberId: Int? { didSet { setNeedsUpdate() } } @@ -107,7 +121,9 @@ open class CarouselScrollbar: View { internal var _selectedLayout: Layout = .oneUP internal var _numberOfSlides: Int? = 1 internal var heightConstraint: NSLayoutConstraint? - + internal var totalPositions: Int? = 1 + internal var _position: Int? = 1 + private let trackViewWidth = 96 private let trackViewHeight: CGFloat = 4 private let minThumbWidth: Float = 16.0 @@ -179,7 +195,7 @@ open class CarouselScrollbar: View { leftActiveOverlay.frame = CGRectMake(trackView.frame.origin.x, 20, CGFloat(trackViewWidth), trackViewHeight) leftActiveOverlay.isUserInteractionEnabled = true leftActiveOverlay.layer.cornerRadius = cornerRadius - let leftPressRecognizer = UILongPressGestureRecognizer(target: self, action: #selector(self.leftLongPressed(_:))) + let leftPressRecognizer = UILongPressGestureRecognizer(target: self, action: #selector(self.onThumbTouchStart(_:))) leftPressRecognizer.minimumPressDuration = 0 leftActiveOverlay.addGestureRecognizer(leftPressRecognizer) addSubview(leftActiveOverlay) @@ -188,7 +204,7 @@ open class CarouselScrollbar: View { rightActiveOverlay.frame = CGRectMake(thumbView.frame.origin.x + thumbView.frame.size.width, 20, CGFloat(trackViewWidth), trackViewHeight) rightActiveOverlay.isUserInteractionEnabled = true rightActiveOverlay.layer.cornerRadius = cornerRadius - let rightPressRecognizer = UILongPressGestureRecognizer(target: self, action: #selector(self.rightLongPressed(_:))) + let rightPressRecognizer = UILongPressGestureRecognizer(target: self, action: #selector(self.onThumbTouchEnd(_:))) rightPressRecognizer.minimumPressDuration = 0 rightActiveOverlay.addGestureRecognizer(rightPressRecognizer) addSubview(rightActiveOverlay) @@ -198,7 +214,7 @@ open class CarouselScrollbar: View { thumbView.layer.cornerRadius = cornerRadius thumbView.addGestureRecognizer(UIPanGestureRecognizer(target: self, action:(#selector(self.handleGesture(_:))))) addSubview(thumbView) - updateActiveOverlayFrames() + updateActiveOverlays() } open override func updateView() { @@ -223,17 +239,16 @@ open class CarouselScrollbar: View { //-------------------------------------------------- // MARK: - Private Methods //-------------------------------------------------- - func updateThumbViewToLeft() { + func onMoveBackward() { thumbView.frame.origin.x = thumbView.frame.origin.x - CGFloat(actualThumbWidth) - updateActiveOverlayFrames() + updateActiveOverlays() } - func updateThumbViewToRight() { + func onMoveForward() { thumbView.frame.origin.x = thumbView.frame.origin.x + CGFloat(actualThumbWidth) - updateActiveOverlayFrames() + updateActiveOverlays() } - - //TO DO: Drag functionality pending + @objc func handleGesture(_ sender: UIPanGestureRecognizer) { switch sender.state { @@ -254,7 +269,7 @@ open class CarouselScrollbar: View { } } - @objc func leftLongPressed(_ gesture: UILongPressGestureRecognizer) { + @objc func onThumbTouchStart(_ gesture: UILongPressGestureRecognizer) { if gesture.state == .began { leftActiveOverlay.backgroundColor = activeOverlayColorConfiguration.getColor(self) leftActiveOverlay.layer.opacity = activeOpacity @@ -265,12 +280,12 @@ open class CarouselScrollbar: View { leftActiveOverlay.backgroundColor = .clear leftActiveOverlay.layer.opacity = defaultOpacity DispatchQueue.main.asyncAfter(deadline: .now() + .milliseconds(100)) { [weak self] in - self?.updateThumbViewToLeft() + self?.onMoveBackward() } } } - @objc func rightLongPressed(_ gesture: UILongPressGestureRecognizer) { + @objc func onThumbTouchEnd(_ gesture: UILongPressGestureRecognizer) { if gesture.state == .began { rightActiveOverlay.backgroundColor = activeOverlayColorConfiguration.getColor(self) rightActiveOverlay.layer.opacity = activeOpacity @@ -281,21 +296,22 @@ open class CarouselScrollbar: View { rightActiveOverlay.backgroundColor = .clear rightActiveOverlay.layer.opacity = defaultOpacity DispatchQueue.main.asyncAfter(deadline: .now() + .milliseconds(100)) { [weak self] in - self?.updateThumbViewToRight() + self?.onMoveForward() } } } private func setThumbWidth() { - let width = Float (trackViewWidth / (numberOfSlides ?? 1) * _selectedLayout.value) + let width = (Float(trackViewWidth) / Float(numberOfSlides ?? 1)) * Float(_selectedLayout.value) actualThumbWidth = (width > Float(trackViewWidth)) ? Float(trackViewWidth) : width thumbWidth = (width <= Float(trackViewWidth) && width > minThumbWidth) ? width : ((width > Float(trackViewWidth)) ? Float(trackViewWidth) : minThumbWidth) thumbView.frame.size.width = CGFloat(thumbWidth) thumbView.frame.origin.x = trackView.frame.origin.x - updateActiveOverlayFrames() + checkPositions() + updateActiveOverlays() } - private func updateActiveOverlayFrames() { + private func updateActiveOverlays() { // adjusting thumb position if it goes beyond trackView. let thumbPosition = thumbView.frame.origin.x + thumbView.frame.size.width let trackPosition = trackView.frame.origin.x + trackView.frame.size.width @@ -303,7 +319,7 @@ open class CarouselScrollbar: View { thumbView.frame.origin.x = trackPosition - thumbView.frame.size.width } else if thumbView.frame.origin.x < trackView.frame.origin.x { thumbView.frame.origin.x = trackView.frame.origin.x - } + } //left active overlay position update leftActiveOverlay.frame.size.width = thumbView.frame.origin.x - trackView.frame.origin.x + cornerRadius @@ -312,6 +328,15 @@ open class CarouselScrollbar: View { rightActiveOverlay.frame.origin.x = thumbView.frame.origin.x + thumbView.frame.size.width - cornerRadius rightActiveOverlay.frame.size.width = (trackView.frame.origin.x + trackView.frame.size.width) - (thumbView.frame.origin.x + thumbView.frame.size.width) + cornerRadius } + + private func checkPositions() { + totalPositions = Int (ceil (Double(numberOfSlides ?? 1) / Double(_selectedLayout.value))) + } + + private func setThumb(_ position: Int?) { + thumbView.frame.origin.x = CGFloat(Float((position ?? 1) - 1) * actualThumbWidth) + trackView.frame.origin.x + updateActiveOverlays() + } }