From 70708ad33700258463118812e0118d6f3b89dc33 Mon Sep 17 00:00:00 2001 From: Vislov Ivan Date: Tue, 4 Feb 2025 18:45:41 +0300 Subject: [PATCH 01/25] UKCircularProgress --- .../CircularProgressPreview.swift | 23 +- .../Models/CircularProgressVM.swift | 8 + .../CircularProgress/UKCircularProgress.swift | 260 ++++++++++++++++++ 3 files changed, 290 insertions(+), 1 deletion(-) create mode 100644 Sources/ComponentsKit/Components/CircularProgress/UKCircularProgress.swift diff --git a/Examples/DemosApp/DemosApp/ComponentsPreview/PreviewPages/CircularProgressPreview.swift b/Examples/DemosApp/DemosApp/ComponentsPreview/PreviewPages/CircularProgressPreview.swift index caff98de..9b4ca6e5 100644 --- a/Examples/DemosApp/DemosApp/ComponentsPreview/PreviewPages/CircularProgressPreview.swift +++ b/Examples/DemosApp/DemosApp/ComponentsPreview/PreviewPages/CircularProgressPreview.swift @@ -6,17 +6,37 @@ struct CircularProgressPreview: View { @State private var model = Self.initialModel @State private var currentValue: CGFloat = Self.initialValue + private let circularProgress = UKCircularProgress( + model: Self.initialModel + ) + private let timer = Timer .publish(every: 0.5, on: .main, in: .common) .autoconnect() - + var body: some View { VStack { + PreviewWrapper(title: "UIKit") { + circularProgress + .preview + .onAppear { + circularProgress.currentValue = currentValue + circularProgress.model = model + } + .onChange(of: model) { newModel in + circularProgress.model = newModel + } + .onChange(of: currentValue) { newValue in + circularProgress.currentValue = newValue + model.label = "\(Int(newValue))%" + } + } PreviewWrapper(title: "SwiftUI") { SUCircularProgress(currentValue: self.currentValue, model: self.model) } Form { ComponentColorPicker(selection: self.$model.color) + Picker("Font", selection: self.$model.font) { Text("Default").tag(Optional.none) Text("Small").tag(UniversalFont.smButton) @@ -56,6 +76,7 @@ struct CircularProgressPreview: View { private static var initialValue: Double { return 0.0 } + private static var initialModel = CircularProgressVM { $0.label = "0" $0.style = .light diff --git a/Sources/ComponentsKit/Components/CircularProgress/Models/CircularProgressVM.swift b/Sources/ComponentsKit/Components/CircularProgress/Models/CircularProgressVM.swift index 194dd8ad..0aeda0a8 100644 --- a/Sources/ComponentsKit/Components/CircularProgress/Models/CircularProgressVM.swift +++ b/Sources/ComponentsKit/Components/CircularProgress/Models/CircularProgressVM.swift @@ -138,6 +138,14 @@ extension CircularProgressVM { } } +// MARK: - UIKit Helpers + +extension CircularProgressVM { + func stripesBezierPath(in rect: CGRect) -> UIBezierPath { + return UIBezierPath(cgPath: self.stripesCGPath(in: rect)) + } +} + // MARK: - SwiftUI Helpers extension CircularProgressVM { diff --git a/Sources/ComponentsKit/Components/CircularProgress/UKCircularProgress.swift b/Sources/ComponentsKit/Components/CircularProgress/UKCircularProgress.swift new file mode 100644 index 00000000..9906f029 --- /dev/null +++ b/Sources/ComponentsKit/Components/CircularProgress/UKCircularProgress.swift @@ -0,0 +1,260 @@ +import AutoLayout +import UIKit + +/// A UIKit component that displays a circular progress indicator. +open class UKCircularProgress: UIView, UKComponent { + // MARK: - Properties + + /// A closure that is triggered when the `currentValue` changes. + public var onValueChange: (CGFloat) -> Void + + /// A model that defines the appearance properties for the circular progress. + public var model: CircularProgressVM { + didSet { + self.update(oldValue) + } + } + + /// The current progress value. + public var currentValue: CGFloat { + didSet { + self.updateProgress() + self.onValueChange(self.currentValue) + } + } + + // MARK: - Subviews + + private let backgroundLayer = CAShapeLayer() + private let progressLayer = CAShapeLayer() + private let stripesLayer = CAShapeLayer() + + private let progressLabel: UILabel = { + let label = UILabel() + label.textAlignment = .center + label.adjustsFontSizeToFitWidth = true + label.minimumScaleFactor = 0.5 + return label + }() + + // MARK: - Layout Constraints + + private var labelConstraints = LayoutConstraints() + + // MARK: - UIView Properties + + open override var intrinsicContentSize: CGSize { + return self.model.preferredSize + } + + open override func sizeThatFits(_ size: CGSize) -> CGSize { + let preferred = self.model.preferredSize + return CGSize( + width: min(size.width, preferred.width), + height: min(size.height, preferred.height) + ) + } + + // MARK: - Initialization + /// Initializes a new UKCircularProgress with a given model and initial progress value. + /// + /// - Parameters: + /// - model: The model that defines the appearance properties. + /// - currentValue: The initial progress value. Defaults to 0. + public init( + model: CircularProgressVM = .init(), + currentValue: CGFloat = 0, + onValueChange: @escaping (CGFloat) -> Void = { _ in } + ) { + self.model = model + self.currentValue = currentValue + self.onValueChange = onValueChange + super.init(frame: .zero) + + self.setup() + self.style() + self.layout() + + self.updateProgress() + } + + public required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + // MARK: - Setup + + private func setup() { + self.layer.addSublayer(self.backgroundLayer) + self.layer.addSublayer(self.stripesLayer) + self.layer.addSublayer(self.progressLayer) + + self.addSubview(self.progressLabel) + } + + // MARK: - Style + + private func style() { + Self.Style.backgroundLayer(self.backgroundLayer, model: self.model) + Self.Style.progressLayer(self.progressLayer, model: self.model) + Self.Style.progressLabel(self.progressLabel, model: self.model) + Self.Style.stripesLayer(self.stripesLayer, backgroundLayer: self.backgroundLayer, model: self.model) + } + + // MARK: - Update + + public func update(_ oldModel: CircularProgressVM) { + guard self.model != oldModel else { return } + self.style() + self.updateShapePaths() + self.updateProgress() + + self.invalidateIntrinsicContentSize() + self.setNeedsLayout() + } + + private func updateShapePaths() { + let circlePath = UIBezierPath( + arcCenter: self.model.center, + radius: self.model.radius, + startAngle: -CGFloat.pi / 2, + endAngle: -CGFloat.pi / 2 + 2 * .pi, + clockwise: true + ) + + self.backgroundLayer.path = circlePath.cgPath + self.progressLayer.path = circlePath.cgPath + } + + private func updateProgress() { + let normalized = self.model.progress(for: self.currentValue) + + CATransaction.begin() + CATransaction.setAnimationDuration(self.model.animationDuration) + CATransaction.setAnimationTimingFunction(CAMediaTimingFunction(name: .linear)) + self.progressLayer.strokeEnd = normalized + CATransaction.commit() + + switch self.model.style { + case .light: + self.backgroundLayer.strokeStart = 0 + self.backgroundLayer.strokeEnd = 1 + + case .striped: + let bgStart = self.model.backgroundArcStart(for: normalized) + let bgEnd = self.model.backgroundArcEnd(for: normalized) + CATransaction.begin() + CATransaction.setAnimationDuration(self.model.animationDuration) + CATransaction.setAnimationTimingFunction(CAMediaTimingFunction(name: .linear)) + self.backgroundLayer.strokeStart = bgStart + self.backgroundLayer.strokeEnd = bgEnd + CATransaction.commit() + } + + if let labelText = self.model.label { + UIView.transition( + with: self.progressLabel, + duration: self.model.animationDuration, + options: .transitionCrossDissolve, + animations: { + self.progressLabel.text = labelText + }, + completion: nil + ) + } else { + self.progressLabel.text = nil + } + } + + // MARK: - Layout + + private func layout() { + self.labelConstraints = .merged { + self.progressLabel.center() + } + } + + open override func layoutSubviews() { + super.layoutSubviews() + + self.backgroundLayer.frame = self.bounds + self.progressLayer.frame = self.bounds + self.stripesLayer.frame = self.bounds + + self.updateShapePaths() + + if case .striped = self.model.style { + Self.Style.updateStripesPath(in: self.stripesLayer, model: self.model, bounds: self.bounds) + } + } +} + +// MARK: - Style Helpers + +extension UKCircularProgress { + fileprivate enum Style { + static func backgroundLayer(_ layer: CAShapeLayer, model: CircularProgressVM) { + layer.fillColor = UIColor.clear.cgColor + + switch model.style { + case .light: + layer.strokeColor = model.color.background.uiColor.cgColor + + case .striped: + layer.strokeColor = UIColor.white.cgColor + } + + layer.lineCap = .round + layer.lineWidth = model.circularLineWidth + } + + static func progressLayer(_ layer: CAShapeLayer, model: CircularProgressVM) { + layer.fillColor = UIColor.clear.cgColor + layer.strokeColor = model.color.main.uiColor.cgColor + layer.lineCap = .round + layer.lineWidth = model.circularLineWidth + } + + static func progressLabel(_ label: UILabel, model: CircularProgressVM) { + label.font = model.titleFont.uiFont + label.textColor = model.color.main.uiColor + } + + static func stripesLayer( + _ stripesLayer: CAShapeLayer, + backgroundLayer: CAShapeLayer, + model: CircularProgressVM + ) { + switch model.style { + case .light: + stripesLayer.isHidden = true + stripesLayer.mask = nil + if backgroundLayer.superlayer == nil, let parentLayer = stripesLayer.superlayer { + parentLayer.insertSublayer(backgroundLayer, below: stripesLayer) + } + + case .striped: + stripesLayer.isHidden = false + stripesLayer.fillColor = model.color.main.uiColor.cgColor + + stripesLayer.mask = backgroundLayer + } + } + + // Stripes Angle + static func updateStripesPath(in layer: CAShapeLayer, model: CircularProgressVM, bounds: CGRect) { + let stripesPath = model.stripesBezierPath(in: bounds) + + let center = CGPoint(x: bounds.midX, y: bounds.midY) + + var transform = CGAffineTransform.identity + transform = transform.translatedBy(x: center.x, y: center.y) + transform = transform.rotated(by: -CGFloat.pi / 2) + transform = transform.translatedBy(x: -center.x, y: -center.y) + + stripesPath.apply(transform) + + layer.path = stripesPath.cgPath + } + } +} From 3c372e9af387fa55b518b6e360d6314bbdfce6b9 Mon Sep 17 00:00:00 2001 From: Vislov Ivan Date: Tue, 4 Feb 2025 19:08:06 +0300 Subject: [PATCH 02/25] documentation fix --- .../Components/CircularProgress/UKCircularProgress.swift | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/Sources/ComponentsKit/Components/CircularProgress/UKCircularProgress.swift b/Sources/ComponentsKit/Components/CircularProgress/UKCircularProgress.swift index 9906f029..f6559cb3 100644 --- a/Sources/ComponentsKit/Components/CircularProgress/UKCircularProgress.swift +++ b/Sources/ComponentsKit/Components/CircularProgress/UKCircularProgress.swift @@ -56,11 +56,12 @@ open class UKCircularProgress: UIView, UKComponent { } // MARK: - Initialization - /// Initializes a new UKCircularProgress with a given model and initial progress value. - /// + + /// Initializer. /// - Parameters: /// - model: The model that defines the appearance properties. - /// - currentValue: The initial progress value. Defaults to 0. + /// - currentValue: The initial progress value. Defaults to `0`. + /// - onValueChange: A closure triggered whenever `currentValue` changes. public init( model: CircularProgressVM = .init(), currentValue: CGFloat = 0, From 8177801b069c0ec5a9199009f1476624655f8e2c Mon Sep 17 00:00:00 2001 From: Vislov Ivan Date: Wed, 5 Feb 2025 15:23:30 +0300 Subject: [PATCH 03/25] unused code deleted - onValueChange deleted - labelConstraints deleted --- .../CircularProgress/UKCircularProgress.swift | 26 ++++--------------- 1 file changed, 5 insertions(+), 21 deletions(-) diff --git a/Sources/ComponentsKit/Components/CircularProgress/UKCircularProgress.swift b/Sources/ComponentsKit/Components/CircularProgress/UKCircularProgress.swift index f6559cb3..755599bb 100644 --- a/Sources/ComponentsKit/Components/CircularProgress/UKCircularProgress.swift +++ b/Sources/ComponentsKit/Components/CircularProgress/UKCircularProgress.swift @@ -5,9 +5,6 @@ import UIKit open class UKCircularProgress: UIView, UKComponent { // MARK: - Properties - /// A closure that is triggered when the `currentValue` changes. - public var onValueChange: (CGFloat) -> Void - /// A model that defines the appearance properties for the circular progress. public var model: CircularProgressVM { didSet { @@ -19,7 +16,6 @@ open class UKCircularProgress: UIView, UKComponent { public var currentValue: CGFloat { didSet { self.updateProgress() - self.onValueChange(self.currentValue) } } @@ -37,10 +33,6 @@ open class UKCircularProgress: UIView, UKComponent { return label }() - // MARK: - Layout Constraints - - private var labelConstraints = LayoutConstraints() - // MARK: - UIView Properties open override var intrinsicContentSize: CGSize { @@ -59,17 +51,14 @@ open class UKCircularProgress: UIView, UKComponent { /// Initializer. /// - Parameters: + /// - initialValue: The initial progress value. Defaults to `0`. /// - model: The model that defines the appearance properties. - /// - currentValue: The initial progress value. Defaults to `0`. - /// - onValueChange: A closure triggered whenever `currentValue` changes. public init( - model: CircularProgressVM = .init(), - currentValue: CGFloat = 0, - onValueChange: @escaping (CGFloat) -> Void = { _ in } + initialValue: CGFloat = 0, + model: CircularProgressVM = .init() ) { self.model = model - self.currentValue = currentValue - self.onValueChange = onValueChange + self.currentValue = initialValue super.init(frame: .zero) self.setup() @@ -109,9 +98,6 @@ open class UKCircularProgress: UIView, UKComponent { self.style() self.updateShapePaths() self.updateProgress() - - self.invalidateIntrinsicContentSize() - self.setNeedsLayout() } private func updateShapePaths() { @@ -170,9 +156,7 @@ open class UKCircularProgress: UIView, UKComponent { // MARK: - Layout private func layout() { - self.labelConstraints = .merged { - self.progressLabel.center() - } + self.progressLabel.center() } open override func layoutSubviews() { From b7b0625ccbaee7d88b60a899c6b50b18459db81f Mon Sep 17 00:00:00 2001 From: Vislov Ivan Date: Wed, 5 Feb 2025 15:28:07 +0300 Subject: [PATCH 04/25] fix shape layer to public and added docs --- .../CircularProgress/UKCircularProgress.swift | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/Sources/ComponentsKit/Components/CircularProgress/UKCircularProgress.swift b/Sources/ComponentsKit/Components/CircularProgress/UKCircularProgress.swift index 755599bb..fd9d50e8 100644 --- a/Sources/ComponentsKit/Components/CircularProgress/UKCircularProgress.swift +++ b/Sources/ComponentsKit/Components/CircularProgress/UKCircularProgress.swift @@ -21,9 +21,14 @@ open class UKCircularProgress: UIView, UKComponent { // MARK: - Subviews - private let backgroundLayer = CAShapeLayer() - private let progressLayer = CAShapeLayer() - private let stripesLayer = CAShapeLayer() + /// The Shape Layer used to render the background of the circular progress indicator. + public let backgroundLayer = CAShapeLayer() + + /// The Shape Layer used to render the progress arc of the circular progress indicator. + public let progressLayer = CAShapeLayer() + + /// The Shape Layer used to render the stripes effect in the circular progress indicator. + public let stripesLayer = CAShapeLayer() private let progressLabel: UILabel = { let label = UILabel() From 7a6dc23f50741c0be71a3955ac3f599ab03d47f4 Mon Sep 17 00:00:00 2001 From: Vislov Ivan Date: Wed, 5 Feb 2025 15:32:19 +0300 Subject: [PATCH 05/25] moved sizeThatFits below other methods --- .../CircularProgress/UKCircularProgress.swift | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/Sources/ComponentsKit/Components/CircularProgress/UKCircularProgress.swift b/Sources/ComponentsKit/Components/CircularProgress/UKCircularProgress.swift index fd9d50e8..10639d82 100644 --- a/Sources/ComponentsKit/Components/CircularProgress/UKCircularProgress.swift +++ b/Sources/ComponentsKit/Components/CircularProgress/UKCircularProgress.swift @@ -44,14 +44,6 @@ open class UKCircularProgress: UIView, UKComponent { return self.model.preferredSize } - open override func sizeThatFits(_ size: CGSize) -> CGSize { - let preferred = self.model.preferredSize - return CGSize( - width: min(size.width, preferred.width), - height: min(size.height, preferred.height) - ) - } - // MARK: - Initialization /// Initializer. @@ -177,6 +169,16 @@ open class UKCircularProgress: UIView, UKComponent { Self.Style.updateStripesPath(in: self.stripesLayer, model: self.model, bounds: self.bounds) } } + + // MARK: - UIView Methods + + open override func sizeThatFits(_ size: CGSize) -> CGSize { + let preferred = self.model.preferredSize + return CGSize( + width: min(size.width, preferred.width), + height: min(size.height, preferred.height) + ) + } } // MARK: - Style Helpers From ad1175aead7ed2f2510b5afcb4a9318cbeca64d4 Mon Sep 17 00:00:00 2001 From: Vislov Ivan Date: Wed, 5 Feb 2025 15:36:41 +0300 Subject: [PATCH 06/25] progressLabel fix - progressLabel renamed to label - style extracted into style helper --- .../CircularProgress/UKCircularProgress.swift | 26 +++++++++---------- 1 file changed, 12 insertions(+), 14 deletions(-) diff --git a/Sources/ComponentsKit/Components/CircularProgress/UKCircularProgress.swift b/Sources/ComponentsKit/Components/CircularProgress/UKCircularProgress.swift index 10639d82..bf40e921 100644 --- a/Sources/ComponentsKit/Components/CircularProgress/UKCircularProgress.swift +++ b/Sources/ComponentsKit/Components/CircularProgress/UKCircularProgress.swift @@ -30,13 +30,8 @@ open class UKCircularProgress: UIView, UKComponent { /// The Shape Layer used to render the stripes effect in the circular progress indicator. public let stripesLayer = CAShapeLayer() - private let progressLabel: UILabel = { - let label = UILabel() - label.textAlignment = .center - label.adjustsFontSizeToFitWidth = true - label.minimumScaleFactor = 0.5 - return label - }() + /// The Label used to display progress text. + public let label = UILabel() // MARK: - UIView Properties @@ -76,7 +71,7 @@ open class UKCircularProgress: UIView, UKComponent { self.layer.addSublayer(self.stripesLayer) self.layer.addSublayer(self.progressLayer) - self.addSubview(self.progressLabel) + self.addSubview(self.label) } // MARK: - Style @@ -84,7 +79,7 @@ open class UKCircularProgress: UIView, UKComponent { private func style() { Self.Style.backgroundLayer(self.backgroundLayer, model: self.model) Self.Style.progressLayer(self.progressLayer, model: self.model) - Self.Style.progressLabel(self.progressLabel, model: self.model) + Self.Style.label(self.label, model: self.model) Self.Style.stripesLayer(self.stripesLayer, backgroundLayer: self.backgroundLayer, model: self.model) } @@ -137,23 +132,23 @@ open class UKCircularProgress: UIView, UKComponent { if let labelText = self.model.label { UIView.transition( - with: self.progressLabel, + with: self.label, duration: self.model.animationDuration, options: .transitionCrossDissolve, animations: { - self.progressLabel.text = labelText + self.label.text = labelText }, completion: nil ) } else { - self.progressLabel.text = nil + self.label.text = nil } } // MARK: - Layout private func layout() { - self.progressLabel.center() + self.label.center() } open override func layoutSubviews() { @@ -207,7 +202,10 @@ extension UKCircularProgress { layer.lineWidth = model.circularLineWidth } - static func progressLabel(_ label: UILabel, model: CircularProgressVM) { + static func label(_ label: UILabel, model: CircularProgressVM) { + label.textAlignment = .center + label.adjustsFontSizeToFitWidth = true + label.minimumScaleFactor = 0.5 label.font = model.titleFont.uiFont label.textColor = model.color.main.uiColor } From 1d908c3423afc0b5a7591aa39a514bd4bc3bfc35 Mon Sep 17 00:00:00 2001 From: Vislov Ivan Date: Wed, 5 Feb 2025 15:37:41 +0300 Subject: [PATCH 07/25] preview fix --- .../PreviewPages/CircularProgressPreview.swift | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/Examples/DemosApp/DemosApp/ComponentsPreview/PreviewPages/CircularProgressPreview.swift b/Examples/DemosApp/DemosApp/ComponentsPreview/PreviewPages/CircularProgressPreview.swift index 9b4ca6e5..bb4e76ac 100644 --- a/Examples/DemosApp/DemosApp/ComponentsPreview/PreviewPages/CircularProgressPreview.swift +++ b/Examples/DemosApp/DemosApp/ComponentsPreview/PreviewPages/CircularProgressPreview.swift @@ -17,18 +17,17 @@ struct CircularProgressPreview: View { var body: some View { VStack { PreviewWrapper(title: "UIKit") { - circularProgress + self.circularProgress .preview .onAppear { - circularProgress.currentValue = currentValue - circularProgress.model = model + self.circularProgress.currentValue = Self.initialValue + self.circularProgress.model = Self.initialModel } .onChange(of: model) { newModel in - circularProgress.model = newModel + self.circularProgress.model = newModel } - .onChange(of: currentValue) { newValue in - circularProgress.currentValue = newValue - model.label = "\(Int(newValue))%" + .onChange(of: self.currentValue) { newValue in + self.circularProgress.currentValue = newValue } } PreviewWrapper(title: "SwiftUI") { From 37222c7dd8661c72ff0e0299d13792ad5317cc94 Mon Sep 17 00:00:00 2001 From: Vislov Ivan Date: Wed, 5 Feb 2025 15:46:19 +0300 Subject: [PATCH 08/25] fix stroke in 1 transaction --- .../CircularProgress/UKCircularProgress.swift | 19 ++++++++----------- 1 file changed, 8 insertions(+), 11 deletions(-) diff --git a/Sources/ComponentsKit/Components/CircularProgress/UKCircularProgress.swift b/Sources/ComponentsKit/Components/CircularProgress/UKCircularProgress.swift index bf40e921..0fc8129c 100644 --- a/Sources/ComponentsKit/Components/CircularProgress/UKCircularProgress.swift +++ b/Sources/ComponentsKit/Components/CircularProgress/UKCircularProgress.swift @@ -106,30 +106,27 @@ open class UKCircularProgress: UIView, UKComponent { } private func updateProgress() { - let normalized = self.model.progress(for: self.currentValue) + let progress = self.model.progress(for: self.currentValue) CATransaction.begin() CATransaction.setAnimationDuration(self.model.animationDuration) CATransaction.setAnimationTimingFunction(CAMediaTimingFunction(name: .linear)) - self.progressLayer.strokeEnd = normalized - CATransaction.commit() + + self.progressLayer.strokeEnd = progress switch self.model.style { case .light: self.backgroundLayer.strokeStart = 0 self.backgroundLayer.strokeEnd = 1 - case .striped: - let bgStart = self.model.backgroundArcStart(for: normalized) - let bgEnd = self.model.backgroundArcEnd(for: normalized) - CATransaction.begin() - CATransaction.setAnimationDuration(self.model.animationDuration) - CATransaction.setAnimationTimingFunction(CAMediaTimingFunction(name: .linear)) + let bgStart = self.model.backgroundArcStart(for: progress) + let bgEnd = self.model.backgroundArcEnd(for: progress) self.backgroundLayer.strokeStart = bgStart - self.backgroundLayer.strokeEnd = bgEnd - CATransaction.commit() + self.backgroundLayer.strokeEnd = bgEnd } + CATransaction.commit() + if let labelText = self.model.label { UIView.transition( with: self.label, From b6fc139c54820ac205d52f58ceacc071cbb3516f Mon Sep 17 00:00:00 2001 From: Vislov Ivan Date: Wed, 5 Feb 2025 18:02:30 +0300 Subject: [PATCH 09/25] swiftlint fix --- .../Components/CircularProgress/UKCircularProgress.swift | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Sources/ComponentsKit/Components/CircularProgress/UKCircularProgress.swift b/Sources/ComponentsKit/Components/CircularProgress/UKCircularProgress.swift index 0fc8129c..6a5d0696 100644 --- a/Sources/ComponentsKit/Components/CircularProgress/UKCircularProgress.swift +++ b/Sources/ComponentsKit/Components/CircularProgress/UKCircularProgress.swift @@ -23,10 +23,10 @@ open class UKCircularProgress: UIView, UKComponent { /// The Shape Layer used to render the background of the circular progress indicator. public let backgroundLayer = CAShapeLayer() - + /// The Shape Layer used to render the progress arc of the circular progress indicator. public let progressLayer = CAShapeLayer() - + /// The Shape Layer used to render the stripes effect in the circular progress indicator. public let stripesLayer = CAShapeLayer() @@ -161,9 +161,9 @@ open class UKCircularProgress: UIView, UKComponent { Self.Style.updateStripesPath(in: self.stripesLayer, model: self.model, bounds: self.bounds) } } - + // MARK: - UIView Methods - + open override func sizeThatFits(_ size: CGSize) -> CGSize { let preferred = self.model.preferredSize return CGSize( From 1e065c037ad7af588eab2fc8c3e8b10d1ef86eab Mon Sep 17 00:00:00 2001 From: Mikhail Date: Wed, 5 Feb 2025 16:46:07 +0100 Subject: [PATCH 10/25] improve code --- .../CircularProgressPreview.swift | 2 +- .../Models/CircularProgressVM.swift | 4 ++-- .../CircularProgress/SUCircularProgress.swift | 8 +++---- .../CircularProgress/UKCircularProgress.swift | 24 +++++++++---------- 4 files changed, 19 insertions(+), 19 deletions(-) diff --git a/Examples/DemosApp/DemosApp/ComponentsPreview/PreviewPages/CircularProgressPreview.swift b/Examples/DemosApp/DemosApp/ComponentsPreview/PreviewPages/CircularProgressPreview.swift index bb4e76ac..1feb9271 100644 --- a/Examples/DemosApp/DemosApp/ComponentsPreview/PreviewPages/CircularProgressPreview.swift +++ b/Examples/DemosApp/DemosApp/ComponentsPreview/PreviewPages/CircularProgressPreview.swift @@ -77,7 +77,7 @@ struct CircularProgressPreview: View { } private static var initialModel = CircularProgressVM { - $0.label = "0" + $0.label = "0%" $0.style = .light } } diff --git a/Sources/ComponentsKit/Components/CircularProgress/Models/CircularProgressVM.swift b/Sources/ComponentsKit/Components/CircularProgress/Models/CircularProgressVM.swift index 0aeda0a8..b0622e32 100644 --- a/Sources/ComponentsKit/Components/CircularProgress/Models/CircularProgressVM.swift +++ b/Sources/ComponentsKit/Components/CircularProgress/Models/CircularProgressVM.swift @@ -118,12 +118,12 @@ extension CircularProgressVM { return max(0, min(1, normalized)) } - func backgroundArcStart(for normalized: CGFloat) -> CGFloat { + func stripedArcStart(for normalized: CGFloat) -> CGFloat { let gapValue = self.gap(for: normalized) return max(0, min(1, normalized + gapValue)) } - func backgroundArcEnd(for normalized: CGFloat) -> CGFloat { + func stripedArcEnd(for normalized: CGFloat) -> CGFloat { let gapValue = self.gap(for: normalized) return 1 - gapValue } diff --git a/Sources/ComponentsKit/Components/CircularProgress/SUCircularProgress.swift b/Sources/ComponentsKit/Components/CircularProgress/SUCircularProgress.swift index 96ebcc5d..cfae7e9a 100644 --- a/Sources/ComponentsKit/Components/CircularProgress/SUCircularProgress.swift +++ b/Sources/ComponentsKit/Components/CircularProgress/SUCircularProgress.swift @@ -112,8 +112,8 @@ public struct SUCircularProgress: View { ) } .trim( - from: self.model.backgroundArcStart(for: self.progress), - to: self.model.backgroundArcEnd(for: self.progress) + from: self.model.stripedArcStart(for: self.progress), + to: self.model.stripedArcEnd(for: self.progress) ) .stroke( .clear, @@ -136,8 +136,8 @@ public struct SUCircularProgress: View { ) } .trim( - from: self.model.backgroundArcStart(for: self.progress), - to: self.model.backgroundArcEnd(for: self.progress) + from: self.model.stripedArcStart(for: self.progress), + to: self.model.stripedArcEnd(for: self.progress) ) .stroke( style: StrokeStyle( diff --git a/Sources/ComponentsKit/Components/CircularProgress/UKCircularProgress.swift b/Sources/ComponentsKit/Components/CircularProgress/UKCircularProgress.swift index 6a5d0696..cb23220d 100644 --- a/Sources/ComponentsKit/Components/CircularProgress/UKCircularProgress.swift +++ b/Sources/ComponentsKit/Components/CircularProgress/UKCircularProgress.swift @@ -108,23 +108,23 @@ open class UKCircularProgress: UIView, UKComponent { private func updateProgress() { let progress = self.model.progress(for: self.currentValue) - CATransaction.begin() - CATransaction.setAnimationDuration(self.model.animationDuration) - CATransaction.setAnimationTimingFunction(CAMediaTimingFunction(name: .linear)) - - self.progressLayer.strokeEnd = progress - + let backgroundLayerStart: CGFloat + let backgroundLayerEnd: CGFloat switch self.model.style { case .light: - self.backgroundLayer.strokeStart = 0 - self.backgroundLayer.strokeEnd = 1 + backgroundLayerStart = 0 + backgroundLayerEnd = 1 case .striped: - let bgStart = self.model.backgroundArcStart(for: progress) - let bgEnd = self.model.backgroundArcEnd(for: progress) - self.backgroundLayer.strokeStart = bgStart - self.backgroundLayer.strokeEnd = bgEnd + backgroundLayerStart = self.model.stripedArcStart(for: progress) + backgroundLayerEnd = self.model.stripedArcEnd(for: progress) } + CATransaction.begin() + CATransaction.setAnimationDuration(self.model.animationDuration) + CATransaction.setAnimationTimingFunction(CAMediaTimingFunction(name: .linear)) + self.progressLayer.strokeEnd = progress + self.backgroundLayer.strokeStart = backgroundLayerStart + self.backgroundLayer.strokeEnd = backgroundLayerEnd CATransaction.commit() if let labelText = self.model.label { From fdf850e6965e80733d09642f77add5b5211e105d Mon Sep 17 00:00:00 2001 From: Mikhail Date: Wed, 5 Feb 2025 16:56:52 +0100 Subject: [PATCH 11/25] fix layout when size changes --- .../CircularProgress/Models/CircularProgressVM.swift | 5 ++++- .../Components/CircularProgress/UKCircularProgress.swift | 4 ++++ 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/Sources/ComponentsKit/Components/CircularProgress/Models/CircularProgressVM.swift b/Sources/ComponentsKit/Components/CircularProgress/Models/CircularProgressVM.swift index b0622e32..d986e47f 100644 --- a/Sources/ComponentsKit/Components/CircularProgress/Models/CircularProgressVM.swift +++ b/Sources/ComponentsKit/Components/CircularProgress/Models/CircularProgressVM.swift @@ -130,7 +130,7 @@ extension CircularProgressVM { } extension CircularProgressVM { - public func progress(for currentValue: CGFloat) -> CGFloat { + func progress(for currentValue: CGFloat) -> CGFloat { let range = self.maxValue - self.minValue guard range > 0 else { return 0 } let normalized = (currentValue - self.minValue) / range @@ -144,6 +144,9 @@ extension CircularProgressVM { func stripesBezierPath(in rect: CGRect) -> UIBezierPath { return UIBezierPath(cgPath: self.stripesCGPath(in: rect)) } + func shouldInvalidateIntrinsicContentSize(_ oldValue: Self) -> Bool { + return self.preferredSize != oldValue.preferredSize + } } // MARK: - SwiftUI Helpers diff --git a/Sources/ComponentsKit/Components/CircularProgress/UKCircularProgress.swift b/Sources/ComponentsKit/Components/CircularProgress/UKCircularProgress.swift index cb23220d..9fa9800c 100644 --- a/Sources/ComponentsKit/Components/CircularProgress/UKCircularProgress.swift +++ b/Sources/ComponentsKit/Components/CircularProgress/UKCircularProgress.swift @@ -90,6 +90,10 @@ open class UKCircularProgress: UIView, UKComponent { self.style() self.updateShapePaths() self.updateProgress() + + if self.model.shouldInvalidateIntrinsicContentSize(oldModel) { + self.invalidateIntrinsicContentSize() + } } private func updateShapePaths() { From e8ce3e443bf7389fa779f8f65079657fd5a60d37 Mon Sep 17 00:00:00 2001 From: Vislov Ivan Date: Wed, 5 Feb 2025 20:22:57 +0300 Subject: [PATCH 12/25] fix shape path center --- .../Components/CircularProgress/UKCircularProgress.swift | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Sources/ComponentsKit/Components/CircularProgress/UKCircularProgress.swift b/Sources/ComponentsKit/Components/CircularProgress/UKCircularProgress.swift index 9fa9800c..69b69b80 100644 --- a/Sources/ComponentsKit/Components/CircularProgress/UKCircularProgress.swift +++ b/Sources/ComponentsKit/Components/CircularProgress/UKCircularProgress.swift @@ -97,8 +97,9 @@ open class UKCircularProgress: UIView, UKComponent { } private func updateShapePaths() { + let center = CGPoint(x: self.bounds.midX, y: self.bounds.midY) let circlePath = UIBezierPath( - arcCenter: self.model.center, + arcCenter: center, radius: self.model.radius, startAngle: -CGFloat.pi / 2, endAngle: -CGFloat.pi / 2 + 2 * .pi, From 51cb707016dda8649eecfc68b3c1eef0b992e0b9 Mon Sep 17 00:00:00 2001 From: Vislov Ivan Date: Wed, 5 Feb 2025 20:41:49 +0300 Subject: [PATCH 13/25] added UITraitCollection --- .../CircularProgress/UKCircularProgress.swift | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/Sources/ComponentsKit/Components/CircularProgress/UKCircularProgress.swift b/Sources/ComponentsKit/Components/CircularProgress/UKCircularProgress.swift index 69b69b80..e548a8c4 100644 --- a/Sources/ComponentsKit/Components/CircularProgress/UKCircularProgress.swift +++ b/Sources/ComponentsKit/Components/CircularProgress/UKCircularProgress.swift @@ -70,8 +70,13 @@ open class UKCircularProgress: UIView, UKComponent { self.layer.addSublayer(self.backgroundLayer) self.layer.addSublayer(self.stripesLayer) self.layer.addSublayer(self.progressLayer) - self.addSubview(self.label) + + if #available(iOS 17.0, *) { + self.registerForTraitChanges([UITraitUserInterfaceStyle.self]) { (view: Self, _: UITraitCollection) in + view.handleTraitChanges() + } + } } // MARK: - Style @@ -176,6 +181,11 @@ open class UKCircularProgress: UIView, UKComponent { height: min(size.height, preferred.height) ) } + + open override func traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?) { + super.traitCollectionDidChange(previousTraitCollection) + self.handleTraitChanges() + } } // MARK: - Style Helpers @@ -249,4 +259,11 @@ extension UKCircularProgress { layer.path = stripesPath.cgPath } } + + private func handleTraitChanges() { + Self.Style.backgroundLayer(self.backgroundLayer, model: self.model) + Self.Style.progressLayer(self.progressLayer, model: self.model) + Self.Style.label(self.label, model: self.model) + Self.Style.stripesLayer(self.stripesLayer, backgroundLayer: self.backgroundLayer, model: self.model) + } } From 03f51cd00c6621baffb73efc9019edec221b591c Mon Sep 17 00:00:00 2001 From: Vislov Ivan Date: Thu, 6 Feb 2025 17:15:03 +0300 Subject: [PATCH 14/25] layers fix - added stripesMaskLayer - func updateStripesPath deleted, logic extracted into updateShapePaths --- .../Models/CircularProgressVM.swift | 17 ++-- .../CircularProgress/UKCircularProgress.swift | 99 ++++++++++++------- 2 files changed, 76 insertions(+), 40 deletions(-) diff --git a/Sources/ComponentsKit/Components/CircularProgress/Models/CircularProgressVM.swift b/Sources/ComponentsKit/Components/CircularProgress/Models/CircularProgressVM.swift index d986e47f..5ec37337 100644 --- a/Sources/ComponentsKit/Components/CircularProgress/Models/CircularProgressVM.swift +++ b/Sources/ComponentsKit/Components/CircularProgress/Models/CircularProgressVM.swift @@ -89,12 +89,17 @@ extension CircularProgressVM { let path = CGMutablePath() let step = stripeWidth + stripeSpacing let radians = stripeAngle.radians - let dx = rect.height * tan(radians) - for x in stride(from: dx, through: rect.width + rect.height, by: step) { - let topLeft = CGPoint(x: x, y: 0) - let topRight = CGPoint(x: x + stripeWidth, y: 0) - let bottomLeft = CGPoint(x: x + dx, y: rect.height) - let bottomRight = CGPoint(x: x + stripeWidth + dx, y: rect.height) + + let startY = -rect.width + let endY = rect.height + rect.width + + for y in stride(from: startY, through: endY, by: step) { + let topLeft = CGPoint(x: 0, y: y) + let topRight = CGPoint(x: 0, y: y + stripeWidth) + + let bottomLeft = CGPoint(x: rect.width, y: y + tan(radians) * rect.width) + let bottomRight = CGPoint(x: rect.width, y: (y + stripeWidth) + tan(radians) * rect.width) + path.move(to: topLeft) path.addLine(to: topRight) path.addLine(to: bottomRight) diff --git a/Sources/ComponentsKit/Components/CircularProgress/UKCircularProgress.swift b/Sources/ComponentsKit/Components/CircularProgress/UKCircularProgress.swift index e548a8c4..650d77e8 100644 --- a/Sources/ComponentsKit/Components/CircularProgress/UKCircularProgress.swift +++ b/Sources/ComponentsKit/Components/CircularProgress/UKCircularProgress.swift @@ -30,6 +30,9 @@ open class UKCircularProgress: UIView, UKComponent { /// The Shape Layer used to render the stripes effect in the circular progress indicator. public let stripesLayer = CAShapeLayer() + /// The Mask Layer used for the stripesLayer. + public let stripesMaskLayer = CAShapeLayer() + /// The Label used to display progress text. public let label = UILabel() @@ -85,7 +88,7 @@ open class UKCircularProgress: UIView, UKComponent { Self.Style.backgroundLayer(self.backgroundLayer, model: self.model) Self.Style.progressLayer(self.progressLayer, model: self.model) Self.Style.label(self.label, model: self.model) - Self.Style.stripesLayer(self.stripesLayer, backgroundLayer: self.backgroundLayer, model: self.model) + Self.Style.stripesLayer(self.stripesLayer, backgroundLayer: self.backgroundLayer, maskLayer: self.stripesMaskLayer, model: self.model) } // MARK: - Update @@ -113,6 +116,28 @@ open class UKCircularProgress: UIView, UKComponent { self.backgroundLayer.path = circlePath.cgPath self.progressLayer.path = circlePath.cgPath + self.stripesMaskLayer.path = circlePath.cgPath + + if case .striped = self.model.style { + let stripesPath = self.model.stripesBezierPath(in: self.bounds) + + var transform = CGAffineTransform.identity + transform = transform + .translatedBy(x: center.x, y: center.y) + .rotated(by: -CGFloat.pi / 2) + .translatedBy(x: -center.x, y: -center.y) + + stripesPath.apply(transform) + + self.stripesLayer.path = stripesPath.cgPath + } else { + CATransaction.begin() + CATransaction.setDisableActions(true) + self.stripesLayer.path = nil + self.stripesLayer.removeAllAnimations() + self.stripesMaskLayer.removeAllAnimations() + CATransaction.commit() + } } private func updateProgress() { @@ -123,18 +148,30 @@ open class UKCircularProgress: UIView, UKComponent { switch self.model.style { case .light: backgroundLayerStart = 0 - backgroundLayerEnd = 1 + backgroundLayerEnd = 1 + case .striped: backgroundLayerStart = self.model.stripedArcStart(for: progress) - backgroundLayerEnd = self.model.stripedArcEnd(for: progress) + backgroundLayerEnd = self.model.stripedArcEnd(for: progress) } CATransaction.begin() CATransaction.setAnimationDuration(self.model.animationDuration) CATransaction.setAnimationTimingFunction(CAMediaTimingFunction(name: .linear)) + self.progressLayer.strokeEnd = progress + self.backgroundLayer.strokeStart = backgroundLayerStart self.backgroundLayer.strokeEnd = backgroundLayerEnd + + if case .striped = self.model.style { + self.stripesMaskLayer.strokeStart = backgroundLayerStart + self.stripesMaskLayer.strokeEnd = backgroundLayerEnd + } else { + self.stripesMaskLayer.strokeStart = 0 + self.stripesMaskLayer.strokeEnd = 1 + } + CATransaction.commit() if let labelText = self.model.label { @@ -165,11 +202,9 @@ open class UKCircularProgress: UIView, UKComponent { self.progressLayer.frame = self.bounds self.stripesLayer.frame = self.bounds - self.updateShapePaths() + self.stripesMaskLayer.frame = self.bounds - if case .striped = self.model.style { - Self.Style.updateStripesPath(in: self.stripesLayer, model: self.model, bounds: self.bounds) - } + self.updateShapePaths() } // MARK: - UIView Methods @@ -186,6 +221,18 @@ open class UKCircularProgress: UIView, UKComponent { super.traitCollectionDidChange(previousTraitCollection) self.handleTraitChanges() } + + private func handleTraitChanges() { + Self.Style.backgroundLayer(self.backgroundLayer, model: self.model) + Self.Style.progressLayer(self.progressLayer, model: self.model) + Self.Style.label(self.label, model: self.model) + Self.Style.stripesLayer( + self.stripesLayer, + backgroundLayer: self.backgroundLayer, + maskLayer: self.stripesMaskLayer, + model: self.model + ) + } } // MARK: - Style Helpers @@ -198,9 +245,8 @@ extension UKCircularProgress { switch model.style { case .light: layer.strokeColor = model.color.background.uiColor.cgColor - case .striped: - layer.strokeColor = UIColor.white.cgColor + layer.strokeColor = UIColor.clear.cgColor } layer.lineCap = .round @@ -225,13 +271,16 @@ extension UKCircularProgress { static func stripesLayer( _ stripesLayer: CAShapeLayer, backgroundLayer: CAShapeLayer, + maskLayer: CAShapeLayer, model: CircularProgressVM ) { switch model.style { case .light: stripesLayer.isHidden = true stripesLayer.mask = nil - if backgroundLayer.superlayer == nil, let parentLayer = stripesLayer.superlayer { + + if backgroundLayer.superlayer == nil, + let parentLayer = stripesLayer.superlayer { parentLayer.insertSublayer(backgroundLayer, below: stripesLayer) } @@ -239,31 +288,13 @@ extension UKCircularProgress { stripesLayer.isHidden = false stripesLayer.fillColor = model.color.main.uiColor.cgColor - stripesLayer.mask = backgroundLayer - } - } - - // Stripes Angle - static func updateStripesPath(in layer: CAShapeLayer, model: CircularProgressVM, bounds: CGRect) { - let stripesPath = model.stripesBezierPath(in: bounds) - - let center = CGPoint(x: bounds.midX, y: bounds.midY) + maskLayer.fillColor = UIColor.clear.cgColor + maskLayer.strokeColor = UIColor.white.cgColor + maskLayer.lineCap = .round + maskLayer.lineWidth = model.circularLineWidth - var transform = CGAffineTransform.identity - transform = transform.translatedBy(x: center.x, y: center.y) - transform = transform.rotated(by: -CGFloat.pi / 2) - transform = transform.translatedBy(x: -center.x, y: -center.y) - - stripesPath.apply(transform) - - layer.path = stripesPath.cgPath + stripesLayer.mask = maskLayer + } } } - - private func handleTraitChanges() { - Self.Style.backgroundLayer(self.backgroundLayer, model: self.model) - Self.Style.progressLayer(self.progressLayer, model: self.model) - Self.Style.label(self.label, model: self.model) - Self.Style.stripesLayer(self.stripesLayer, backgroundLayer: self.backgroundLayer, model: self.model) - } } From a8082585633c781e8855e27faa042f9416288ea8 Mon Sep 17 00:00:00 2001 From: Vislov Ivan Date: Fri, 7 Feb 2025 16:04:07 +0300 Subject: [PATCH 15/25] documentation fix --- .../CircularProgress/UKCircularProgress.swift | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/Sources/ComponentsKit/Components/CircularProgress/UKCircularProgress.swift b/Sources/ComponentsKit/Components/CircularProgress/UKCircularProgress.swift index 650d77e8..c857f55a 100644 --- a/Sources/ComponentsKit/Components/CircularProgress/UKCircularProgress.swift +++ b/Sources/ComponentsKit/Components/CircularProgress/UKCircularProgress.swift @@ -21,19 +21,19 @@ open class UKCircularProgress: UIView, UKComponent { // MARK: - Subviews - /// The Shape Layer used to render the background of the circular progress indicator. + /// The shape layer responsible for rendering the background of the circular progress indicator in a light style. public let backgroundLayer = CAShapeLayer() - /// The Shape Layer used to render the progress arc of the circular progress indicator. + /// The shape layer responsible for rendering the progress arc of the circular progress indicator. public let progressLayer = CAShapeLayer() - /// The Shape Layer used to render the stripes effect in the circular progress indicator. + /// The shape layer responsible for rendering the striped effect in the circular progress indicator. public let stripesLayer = CAShapeLayer() - /// The Mask Layer used for the stripesLayer. + /// The shape layer that acts as a mask for `stripesLayer`, ensuring it has the intended shape. public let stripesMaskLayer = CAShapeLayer() - /// The Label used to display progress text. + /// The label used to display text inside the circular progress indicator. public let label = UILabel() // MARK: - UIView Properties From 169973d49ad15e81e5a8c6d445462310e57b0c92 Mon Sep 17 00:00:00 2001 From: Vislov Ivan Date: Fri, 7 Feb 2025 17:01:49 +0300 Subject: [PATCH 16/25] fix stripes angle drawing --- .../Models/CircularProgressVM.swift | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/Sources/ComponentsKit/Components/CircularProgress/Models/CircularProgressVM.swift b/Sources/ComponentsKit/Components/CircularProgress/Models/CircularProgressVM.swift index 5ec37337..a4072feb 100644 --- a/Sources/ComponentsKit/Components/CircularProgress/Models/CircularProgressVM.swift +++ b/Sources/ComponentsKit/Components/CircularProgress/Models/CircularProgressVM.swift @@ -90,15 +90,12 @@ extension CircularProgressVM { let step = stripeWidth + stripeSpacing let radians = stripeAngle.radians - let startY = -rect.width - let endY = rect.height + rect.width - - for y in stride(from: startY, through: endY, by: step) { - let topLeft = CGPoint(x: 0, y: y) - let topRight = CGPoint(x: 0, y: y + stripeWidth) - - let bottomLeft = CGPoint(x: rect.width, y: y + tan(radians) * rect.width) - let bottomRight = CGPoint(x: rect.width, y: (y + stripeWidth) + tan(radians) * rect.width) + let dx: CGFloat = rect.height * tan(radians) + for x in stride(from: 0, through: rect.width + rect.height, by: step) { + let topLeft = CGPoint(x: x, y: 0) + let topRight = CGPoint(x: x + stripeWidth, y: 0) + let bottomLeft = CGPoint(x: x + dx, y: rect.height) + let bottomRight = CGPoint(x: x + stripeWidth + dx, y: rect.height) path.move(to: topLeft) path.addLine(to: topRight) From b319d38607603b3ed745df9c3777a2cc1ac2d602 Mon Sep 17 00:00:00 2001 From: Vislov Ivan Date: Fri, 7 Feb 2025 17:03:50 +0300 Subject: [PATCH 17/25] fix stripesPath logic in func updateShapePaths --- .../CircularProgress/UKCircularProgress.swift | 28 ++++++------------- 1 file changed, 8 insertions(+), 20 deletions(-) diff --git a/Sources/ComponentsKit/Components/CircularProgress/UKCircularProgress.swift b/Sources/ComponentsKit/Components/CircularProgress/UKCircularProgress.swift index c857f55a..df6aaf85 100644 --- a/Sources/ComponentsKit/Components/CircularProgress/UKCircularProgress.swift +++ b/Sources/ComponentsKit/Components/CircularProgress/UKCircularProgress.swift @@ -118,26 +118,14 @@ open class UKCircularProgress: UIView, UKComponent { self.progressLayer.path = circlePath.cgPath self.stripesMaskLayer.path = circlePath.cgPath - if case .striped = self.model.style { - let stripesPath = self.model.stripesBezierPath(in: self.bounds) - - var transform = CGAffineTransform.identity - transform = transform - .translatedBy(x: center.x, y: center.y) - .rotated(by: -CGFloat.pi / 2) - .translatedBy(x: -center.x, y: -center.y) - - stripesPath.apply(transform) - - self.stripesLayer.path = stripesPath.cgPath - } else { - CATransaction.begin() - CATransaction.setDisableActions(true) - self.stripesLayer.path = nil - self.stripesLayer.removeAllAnimations() - self.stripesMaskLayer.removeAllAnimations() - CATransaction.commit() - } + let stripesPath = self.model.stripesBezierPath(in: self.bounds) + var transform = CGAffineTransform.identity + transform = transform + .translatedBy(x: center.x, y: center.y) + .rotated(by: -CGFloat.pi / 2) + .translatedBy(x: -center.x, y: -center.y) + stripesPath.apply(transform) + self.stripesLayer.path = stripesPath.cgPath } private func updateProgress() { From a0e31fadde66955d529f55945c601d133917e217 Mon Sep 17 00:00:00 2001 From: Vislov Ivan Date: Fri, 7 Feb 2025 17:07:01 +0300 Subject: [PATCH 18/25] fix update stripesMaskLayer in updateProgress - update only stripesMaskLayer - added isStripesLayerHidden --- .../Models/CircularProgressVM.swift | 8 ++++++ .../CircularProgress/UKCircularProgress.swift | 27 +++---------------- 2 files changed, 11 insertions(+), 24 deletions(-) diff --git a/Sources/ComponentsKit/Components/CircularProgress/Models/CircularProgressVM.swift b/Sources/ComponentsKit/Components/CircularProgress/Models/CircularProgressVM.swift index a4072feb..2580f3a7 100644 --- a/Sources/ComponentsKit/Components/CircularProgress/Models/CircularProgressVM.swift +++ b/Sources/ComponentsKit/Components/CircularProgress/Models/CircularProgressVM.swift @@ -143,6 +143,14 @@ extension CircularProgressVM { // MARK: - UIKit Helpers extension CircularProgressVM { + var isStripesLayerHidden: Bool { + switch self.style { + case .light: + return true + case .striped: + return false + } + } func stripesBezierPath(in rect: CGRect) -> UIBezierPath { return UIBezierPath(cgPath: self.stripesCGPath(in: rect)) } diff --git a/Sources/ComponentsKit/Components/CircularProgress/UKCircularProgress.swift b/Sources/ComponentsKit/Components/CircularProgress/UKCircularProgress.swift index df6aaf85..9a742f3e 100644 --- a/Sources/ComponentsKit/Components/CircularProgress/UKCircularProgress.swift +++ b/Sources/ComponentsKit/Components/CircularProgress/UKCircularProgress.swift @@ -131,35 +131,14 @@ open class UKCircularProgress: UIView, UKComponent { private func updateProgress() { let progress = self.model.progress(for: self.currentValue) - let backgroundLayerStart: CGFloat - let backgroundLayerEnd: CGFloat - switch self.model.style { - case .light: - backgroundLayerStart = 0 - backgroundLayerEnd = 1 - - case .striped: - backgroundLayerStart = self.model.stripedArcStart(for: progress) - backgroundLayerEnd = self.model.stripedArcEnd(for: progress) - } - CATransaction.begin() CATransaction.setAnimationDuration(self.model.animationDuration) CATransaction.setAnimationTimingFunction(CAMediaTimingFunction(name: .linear)) - self.progressLayer.strokeEnd = progress - - self.backgroundLayer.strokeStart = backgroundLayerStart - self.backgroundLayer.strokeEnd = backgroundLayerEnd - - if case .striped = self.model.style { - self.stripesMaskLayer.strokeStart = backgroundLayerStart - self.stripesMaskLayer.strokeEnd = backgroundLayerEnd - } else { - self.stripesMaskLayer.strokeStart = 0 - self.stripesMaskLayer.strokeEnd = 1 + if !self.model.isStripesLayerHidden { + self.stripesMaskLayer.strokeStart = self.model.stripedArcStart(for: progress) + self.stripesMaskLayer.strokeEnd = self.model.stripedArcEnd(for: progress) } - CATransaction.commit() if let labelText = self.model.label { From 463c3cb2fb008795563f93fba37ab2e3cc39d716 Mon Sep 17 00:00:00 2001 From: Vislov Ivan Date: Fri, 7 Feb 2025 17:09:32 +0300 Subject: [PATCH 19/25] fix backgroundLayer logic - added isBackgroundLayerHidden --- .../Models/CircularProgressVM.swift | 8 ++++++++ .../CircularProgress/UKCircularProgress.swift | 16 ++++++---------- 2 files changed, 14 insertions(+), 10 deletions(-) diff --git a/Sources/ComponentsKit/Components/CircularProgress/Models/CircularProgressVM.swift b/Sources/ComponentsKit/Components/CircularProgress/Models/CircularProgressVM.swift index 2580f3a7..ab569ec7 100644 --- a/Sources/ComponentsKit/Components/CircularProgress/Models/CircularProgressVM.swift +++ b/Sources/ComponentsKit/Components/CircularProgress/Models/CircularProgressVM.swift @@ -151,6 +151,14 @@ extension CircularProgressVM { return false } } + var isBackgroundLayerHidden: Bool { + switch self.style { + case .light: + return false + case .striped: + return true + } + } func stripesBezierPath(in rect: CGRect) -> UIBezierPath { return UIBezierPath(cgPath: self.stripesCGPath(in: rect)) } diff --git a/Sources/ComponentsKit/Components/CircularProgress/UKCircularProgress.swift b/Sources/ComponentsKit/Components/CircularProgress/UKCircularProgress.swift index 9a742f3e..d01a059e 100644 --- a/Sources/ComponentsKit/Components/CircularProgress/UKCircularProgress.swift +++ b/Sources/ComponentsKit/Components/CircularProgress/UKCircularProgress.swift @@ -168,7 +168,6 @@ open class UKCircularProgress: UIView, UKComponent { self.backgroundLayer.frame = self.bounds self.progressLayer.frame = self.bounds self.stripesLayer.frame = self.bounds - self.stripesMaskLayer.frame = self.bounds self.updateShapePaths() @@ -206,18 +205,15 @@ open class UKCircularProgress: UIView, UKComponent { extension UKCircularProgress { fileprivate enum Style { - static func backgroundLayer(_ layer: CAShapeLayer, model: CircularProgressVM) { + static func backgroundLayer( + _ layer: CAShapeLayer, + model: CircularProgressVM + ) { layer.fillColor = UIColor.clear.cgColor - - switch model.style { - case .light: - layer.strokeColor = model.color.background.uiColor.cgColor - case .striped: - layer.strokeColor = UIColor.clear.cgColor - } - + layer.strokeColor = model.color.background.uiColor.cgColor layer.lineCap = .round layer.lineWidth = model.circularLineWidth + layer.isHidden = model.isBackgroundLayerHidden } static func progressLayer(_ layer: CAShapeLayer, model: CircularProgressVM) { From 44ed15758a872e024ed7109fc3539733a6f6d404 Mon Sep 17 00:00:00 2001 From: Vislov Ivan Date: Fri, 7 Feb 2025 17:31:29 +0300 Subject: [PATCH 20/25] fix func stripesLayer --- .../CircularProgress/UKCircularProgress.swift | 51 ++++++++----------- 1 file changed, 20 insertions(+), 31 deletions(-) diff --git a/Sources/ComponentsKit/Components/CircularProgress/UKCircularProgress.swift b/Sources/ComponentsKit/Components/CircularProgress/UKCircularProgress.swift index d01a059e..dde74802 100644 --- a/Sources/ComponentsKit/Components/CircularProgress/UKCircularProgress.swift +++ b/Sources/ComponentsKit/Components/CircularProgress/UKCircularProgress.swift @@ -75,6 +75,8 @@ open class UKCircularProgress: UIView, UKComponent { self.layer.addSublayer(self.progressLayer) self.addSubview(self.label) + self.stripesLayer.mask = self.stripesMaskLayer + if #available(iOS 17.0, *) { self.registerForTraitChanges([UITraitUserInterfaceStyle.self]) { (view: Self, _: UITraitCollection) in view.handleTraitChanges() @@ -88,7 +90,7 @@ open class UKCircularProgress: UIView, UKComponent { Self.Style.backgroundLayer(self.backgroundLayer, model: self.model) Self.Style.progressLayer(self.progressLayer, model: self.model) Self.Style.label(self.label, model: self.model) - Self.Style.stripesLayer(self.stripesLayer, backgroundLayer: self.backgroundLayer, maskLayer: self.stripesMaskLayer, model: self.model) + Self.Style.stripesLayer(self.stripesLayer, model: self.model) } // MARK: - Update @@ -192,12 +194,10 @@ open class UKCircularProgress: UIView, UKComponent { Self.Style.backgroundLayer(self.backgroundLayer, model: self.model) Self.Style.progressLayer(self.progressLayer, model: self.model) Self.Style.label(self.label, model: self.model) - Self.Style.stripesLayer( - self.stripesLayer, - backgroundLayer: self.backgroundLayer, - maskLayer: self.stripesMaskLayer, - model: self.model - ) + Self.Style.backgroundLayer(self.backgroundLayer, model: self.model) + Self.Style.progressLayer(self.progressLayer, model: self.model) + Self.Style.stripesLayer(self.stripesLayer, model: self.model) + Self.Style.stripesMaskLayer(self.stripesMaskLayer, model: self.model) } } @@ -232,32 +232,21 @@ extension UKCircularProgress { } static func stripesLayer( - _ stripesLayer: CAShapeLayer, - backgroundLayer: CAShapeLayer, - maskLayer: CAShapeLayer, + _ layer: CAShapeLayer, model: CircularProgressVM ) { - switch model.style { - case .light: - stripesLayer.isHidden = true - stripesLayer.mask = nil - - if backgroundLayer.superlayer == nil, - let parentLayer = stripesLayer.superlayer { - parentLayer.insertSublayer(backgroundLayer, below: stripesLayer) - } - - case .striped: - stripesLayer.isHidden = false - stripesLayer.fillColor = model.color.main.uiColor.cgColor - - maskLayer.fillColor = UIColor.clear.cgColor - maskLayer.strokeColor = UIColor.white.cgColor - maskLayer.lineCap = .round - maskLayer.lineWidth = model.circularLineWidth - - stripesLayer.mask = maskLayer - } + layer.isHidden = model.isStripesLayerHidden + layer.fillColor = model.color.main.uiColor.cgColor + } + + static func stripesMaskLayer( + _ layer: CAShapeLayer, + model: CircularProgressVM + ) { + layer.fillColor = UIColor.clear.cgColor + layer.strokeColor = model.color.background.uiColor.cgColor + layer.lineCap = .round + layer.lineWidth = model.circularLineWidth } } } From 677132b24bbe80c4dbc0f187911fb2c7cb5e681d Mon Sep 17 00:00:00 2001 From: Vislov Ivan Date: Fri, 7 Feb 2025 17:44:35 +0300 Subject: [PATCH 21/25] updateProgress deleted from init - stroke values and label text inside the setup method --- .../CircularProgress/UKCircularProgress.swift | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/Sources/ComponentsKit/Components/CircularProgress/UKCircularProgress.swift b/Sources/ComponentsKit/Components/CircularProgress/UKCircularProgress.swift index dde74802..05ef4200 100644 --- a/Sources/ComponentsKit/Components/CircularProgress/UKCircularProgress.swift +++ b/Sources/ComponentsKit/Components/CircularProgress/UKCircularProgress.swift @@ -59,8 +59,6 @@ open class UKCircularProgress: UIView, UKComponent { self.setup() self.style() self.layout() - - self.updateProgress() } public required init?(coder: NSCoder) { @@ -82,6 +80,19 @@ open class UKCircularProgress: UIView, UKComponent { view.handleTraitChanges() } } + + CATransaction.begin() + CATransaction.setDisableActions(true) + + let progress = self.model.progress(for: self.currentValue) + self.progressLayer.strokeEnd = progress + if !self.model.isStripesLayerHidden { + self.stripesMaskLayer.strokeStart = self.model.stripedArcStart(for: progress) + self.stripesMaskLayer.strokeEnd = self.model.stripedArcEnd(for: progress) + } + self.label.text = self.model.label + + CATransaction.commit() } // MARK: - Style From bbd4e8c6916a55cbe4db88008b8fb3f150d08a98 Mon Sep 17 00:00:00 2001 From: Vislov Ivan Date: Fri, 7 Feb 2025 17:46:59 +0300 Subject: [PATCH 22/25] swiftlint fix --- .../Components/CircularProgress/UKCircularProgress.swift | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Sources/ComponentsKit/Components/CircularProgress/UKCircularProgress.swift b/Sources/ComponentsKit/Components/CircularProgress/UKCircularProgress.swift index 05ef4200..e9678bae 100644 --- a/Sources/ComponentsKit/Components/CircularProgress/UKCircularProgress.swift +++ b/Sources/ComponentsKit/Components/CircularProgress/UKCircularProgress.swift @@ -80,7 +80,7 @@ open class UKCircularProgress: UIView, UKComponent { view.handleTraitChanges() } } - + CATransaction.begin() CATransaction.setDisableActions(true) @@ -249,7 +249,7 @@ extension UKCircularProgress { layer.isHidden = model.isStripesLayerHidden layer.fillColor = model.color.main.uiColor.cgColor } - + static func stripesMaskLayer( _ layer: CAShapeLayer, model: CircularProgressVM From 77ade4625c8623e3603828f82f4746f6c14e40eb Mon Sep 17 00:00:00 2001 From: Mikhail Date: Mon, 10 Feb 2025 11:57:01 +0100 Subject: [PATCH 23/25] improve code in UKCircularProgress --- .../Models/CircularProgressVM.swift | 21 ++++++- .../CircularProgress/UKCircularProgress.swift | 58 ++++++++----------- 2 files changed, 42 insertions(+), 37 deletions(-) diff --git a/Sources/ComponentsKit/Components/CircularProgress/Models/CircularProgressVM.swift b/Sources/ComponentsKit/Components/CircularProgress/Models/CircularProgressVM.swift index ab569ec7..1c763ff7 100644 --- a/Sources/ComponentsKit/Components/CircularProgress/Models/CircularProgressVM.swift +++ b/Sources/ComponentsKit/Components/CircularProgress/Models/CircularProgressVM.swift @@ -160,10 +160,25 @@ extension CircularProgressVM { } } func stripesBezierPath(in rect: CGRect) -> UIBezierPath { - return UIBezierPath(cgPath: self.stripesCGPath(in: rect)) + let center = CGPoint(x: rect.midX, y: rect.midY) + let path = UIBezierPath(cgPath: self.stripesCGPath(in: rect)) + var transform = CGAffineTransform.identity + transform = transform + .translatedBy(x: center.x, y: center.y) + .rotated(by: -CGFloat.pi / 2) + .translatedBy(x: -center.x, y: -center.y) + path.apply(transform) + return path + } + func shouldInvalidateIntrinsicContentSize(_ oldModel: Self) -> Bool { + return self.preferredSize != oldModel.preferredSize + } + func shouldUpdateText(_ oldModel: Self) -> Bool { + return self.label != oldModel.label } - func shouldInvalidateIntrinsicContentSize(_ oldValue: Self) -> Bool { - return self.preferredSize != oldValue.preferredSize + func shouldRecalculateProgress(_ oldModel: Self) -> Bool { + return self.minValue != oldModel.minValue + || self.maxValue != oldModel.maxValue } } diff --git a/Sources/ComponentsKit/Components/CircularProgress/UKCircularProgress.swift b/Sources/ComponentsKit/Components/CircularProgress/UKCircularProgress.swift index e9678bae..880ec083 100644 --- a/Sources/ComponentsKit/Components/CircularProgress/UKCircularProgress.swift +++ b/Sources/ComponentsKit/Components/CircularProgress/UKCircularProgress.swift @@ -81,9 +81,6 @@ open class UKCircularProgress: UIView, UKComponent { } } - CATransaction.begin() - CATransaction.setDisableActions(true) - let progress = self.model.progress(for: self.currentValue) self.progressLayer.strokeEnd = progress if !self.model.isStripesLayerHidden { @@ -91,8 +88,6 @@ open class UKCircularProgress: UIView, UKComponent { self.stripesMaskLayer.strokeEnd = self.model.stripedArcEnd(for: progress) } self.label.text = self.model.label - - CATransaction.commit() } // MARK: - Style @@ -102,6 +97,7 @@ open class UKCircularProgress: UIView, UKComponent { Self.Style.progressLayer(self.progressLayer, model: self.model) Self.Style.label(self.label, model: self.model) Self.Style.stripesLayer(self.stripesLayer, model: self.model) + Self.Style.stripesMaskLayer(self.stripesMaskLayer, model: self.model) } // MARK: - Update @@ -110,8 +106,21 @@ open class UKCircularProgress: UIView, UKComponent { guard self.model != oldModel else { return } self.style() self.updateShapePaths() - self.updateProgress() + if self.model.shouldUpdateText(oldModel) { + UIView.transition( + with: self.label, + duration: self.model.animationDuration, + options: .transitionCrossDissolve, + animations: { + self.label.text = self.model.label + }, + completion: nil + ) + } + if self.model.shouldRecalculateProgress(oldModel) { + self.updateProgress() + } if self.model.shouldInvalidateIntrinsicContentSize(oldModel) { self.invalidateIntrinsicContentSize() } @@ -130,15 +139,7 @@ open class UKCircularProgress: UIView, UKComponent { self.backgroundLayer.path = circlePath.cgPath self.progressLayer.path = circlePath.cgPath self.stripesMaskLayer.path = circlePath.cgPath - - let stripesPath = self.model.stripesBezierPath(in: self.bounds) - var transform = CGAffineTransform.identity - transform = transform - .translatedBy(x: center.x, y: center.y) - .rotated(by: -CGFloat.pi / 2) - .translatedBy(x: -center.x, y: -center.y) - stripesPath.apply(transform) - self.stripesLayer.path = stripesPath.cgPath + self.stripesLayer.path = self.model.stripesBezierPath(in: self.bounds).cgPath } private func updateProgress() { @@ -153,20 +154,6 @@ open class UKCircularProgress: UIView, UKComponent { self.stripesMaskLayer.strokeEnd = self.model.stripedArcEnd(for: progress) } CATransaction.commit() - - if let labelText = self.model.label { - UIView.transition( - with: self.label, - duration: self.model.animationDuration, - options: .transitionCrossDissolve, - animations: { - self.label.text = labelText - }, - completion: nil - ) - } else { - self.label.text = nil - } } // MARK: - Layout @@ -202,9 +189,6 @@ open class UKCircularProgress: UIView, UKComponent { } private func handleTraitChanges() { - Self.Style.backgroundLayer(self.backgroundLayer, model: self.model) - Self.Style.progressLayer(self.progressLayer, model: self.model) - Self.Style.label(self.label, model: self.model) Self.Style.backgroundLayer(self.backgroundLayer, model: self.model) Self.Style.progressLayer(self.progressLayer, model: self.model) Self.Style.stripesLayer(self.stripesLayer, model: self.model) @@ -227,14 +211,20 @@ extension UKCircularProgress { layer.isHidden = model.isBackgroundLayerHidden } - static func progressLayer(_ layer: CAShapeLayer, model: CircularProgressVM) { + static func progressLayer( + _ layer: CAShapeLayer, + model: CircularProgressVM + ) { layer.fillColor = UIColor.clear.cgColor layer.strokeColor = model.color.main.uiColor.cgColor layer.lineCap = .round layer.lineWidth = model.circularLineWidth } - static func label(_ label: UILabel, model: CircularProgressVM) { + static func label( + _ label: UILabel, + model: CircularProgressVM + ) { label.textAlignment = .center label.adjustsFontSizeToFitWidth = true label.minimumScaleFactor = 0.5 From 1b2017217ecc213229cb45a2137094fb0b5d493d Mon Sep 17 00:00:00 2001 From: Mikhail Date: Tue, 11 Mar 2025 13:07:51 +0100 Subject: [PATCH 24/25] change font style in circular progress preview --- .../PreviewPages/CircularProgressPreview.swift | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/Examples/DemosApp/DemosApp/ComponentsPreview/PreviewPages/CircularProgressPreview.swift b/Examples/DemosApp/DemosApp/ComponentsPreview/PreviewPages/CircularProgressPreview.swift index 1feb9271..40c9edee 100644 --- a/Examples/DemosApp/DemosApp/ComponentsPreview/PreviewPages/CircularProgressPreview.swift +++ b/Examples/DemosApp/DemosApp/ComponentsPreview/PreviewPages/CircularProgressPreview.swift @@ -35,14 +35,7 @@ struct CircularProgressPreview: View { } Form { ComponentColorPicker(selection: self.$model.color) - - Picker("Font", selection: self.$model.font) { - Text("Default").tag(Optional.none) - Text("Small").tag(UniversalFont.smButton) - Text("Medium").tag(UniversalFont.mdButton) - Text("Large").tag(UniversalFont.lgButton) - Text("Custom: system bold of size 16").tag(UniversalFont.system(size: 16, weight: .bold)) - } + CaptionFontPicker(selection: self.$model.font) Picker("Line Width", selection: self.$model.lineWidth) { Text("Default").tag(Optional.none) Text("2").tag(Optional.some(2)) From 3b428ff7188899ac283117800cfc8ee024dbb2d3 Mon Sep 17 00:00:00 2001 From: Mikhail Date: Tue, 11 Mar 2025 13:08:36 +0100 Subject: [PATCH 25/25] improve stripes display in circular progress --- .../Models/CircularProgressVM.swift | 20 ++---- .../CircularProgress/SUCircularProgress.swift | 67 +++++++------------ .../CircularProgress/UKCircularProgress.swift | 3 +- 3 files changed, 31 insertions(+), 59 deletions(-) diff --git a/Sources/ComponentsKit/Components/CircularProgress/Models/CircularProgressVM.swift b/Sources/ComponentsKit/Components/CircularProgress/Models/CircularProgressVM.swift index 1c763ff7..a032d056 100644 --- a/Sources/ComponentsKit/Components/CircularProgress/Models/CircularProgressVM.swift +++ b/Sources/ComponentsKit/Components/CircularProgress/Models/CircularProgressVM.swift @@ -81,8 +81,10 @@ extension CircularProgressVM { return .lgCaption } } + var stripeWidth: CGFloat { + return 0.5 + } private func stripesCGPath(in rect: CGRect) -> CGMutablePath { - let stripeWidth: CGFloat = 0.5 let stripeSpacing: CGFloat = 3 let stripeAngle: Angle = .degrees(135) @@ -93,14 +95,10 @@ extension CircularProgressVM { let dx: CGFloat = rect.height * tan(radians) for x in stride(from: 0, through: rect.width + rect.height, by: step) { let topLeft = CGPoint(x: x, y: 0) - let topRight = CGPoint(x: x + stripeWidth, y: 0) - let bottomLeft = CGPoint(x: x + dx, y: rect.height) - let bottomRight = CGPoint(x: x + stripeWidth + dx, y: rect.height) + let bottomRight = CGPoint(x: x + dx, y: rect.height) path.move(to: topLeft) - path.addLine(to: topRight) path.addLine(to: bottomRight) - path.addLine(to: bottomLeft) path.closeSubpath() } return path @@ -109,15 +107,7 @@ extension CircularProgressVM { extension CircularProgressVM { func gap(for normalized: CGFloat) -> CGFloat { - normalized > 0 ? 0.05 : 0 - } - - func progressArcStart(for normalized: CGFloat) -> CGFloat { - return 0 - } - - func progressArcEnd(for normalized: CGFloat) -> CGFloat { - return max(0, min(1, normalized)) + return normalized > 0 ? 0.05 : 0 } func stripedArcStart(for normalized: CGFloat) -> CGFloat { diff --git a/Sources/ComponentsKit/Components/CircularProgress/SUCircularProgress.swift b/Sources/ComponentsKit/Components/CircularProgress/SUCircularProgress.swift index cfae7e9a..0ba970ac 100644 --- a/Sources/ComponentsKit/Components/CircularProgress/SUCircularProgress.swift +++ b/Sources/ComponentsKit/Components/CircularProgress/SUCircularProgress.swift @@ -102,52 +102,33 @@ public struct SUCircularProgress: View { } var stripedBackground: some View { - Path { path in - path.addArc( - center: self.model.center, - radius: self.model.radius, - startAngle: .radians(0), - endAngle: .radians(2 * .pi), - clockwise: false - ) - } - .trim( - from: self.model.stripedArcStart(for: self.progress), - to: self.model.stripedArcEnd(for: self.progress) - ) - .stroke( - .clear, - style: StrokeStyle( - lineWidth: self.model.circularLineWidth, - lineCap: .round + StripesShapeCircularProgress(model: self.model) + .stroke( + self.model.color.main.color, + style: StrokeStyle(lineWidth: self.model.stripeWidth) ) - ) - .overlay { - StripesShapeCircularProgress(model: self.model) - .foregroundColor(self.model.color.main.color) - .mask { - Path { maskPath in - maskPath.addArc( - center: self.model.center, - radius: self.model.radius, - startAngle: .radians(0), - endAngle: .radians(2 * .pi), - clockwise: false - ) - } - .trim( - from: self.model.stripedArcStart(for: self.progress), - to: self.model.stripedArcEnd(for: self.progress) - ) - .stroke( - style: StrokeStyle( - lineWidth: self.model.circularLineWidth, - lineCap: .round - ) + .mask { + Path { maskPath in + maskPath.addArc( + center: self.model.center, + radius: self.model.radius, + startAngle: .radians(0), + endAngle: .radians(2 * .pi), + clockwise: false ) } - } - .rotationEffect(.degrees(-90)) + .trim( + from: self.model.stripedArcStart(for: self.progress), + to: self.model.stripedArcEnd(for: self.progress) + ) + .stroke( + style: StrokeStyle( + lineWidth: self.model.circularLineWidth, + lineCap: .round + ) + ) + } + .rotationEffect(.degrees(-90)) } } diff --git a/Sources/ComponentsKit/Components/CircularProgress/UKCircularProgress.swift b/Sources/ComponentsKit/Components/CircularProgress/UKCircularProgress.swift index 880ec083..e910e623 100644 --- a/Sources/ComponentsKit/Components/CircularProgress/UKCircularProgress.swift +++ b/Sources/ComponentsKit/Components/CircularProgress/UKCircularProgress.swift @@ -237,7 +237,8 @@ extension UKCircularProgress { model: CircularProgressVM ) { layer.isHidden = model.isStripesLayerHidden - layer.fillColor = model.color.main.uiColor.cgColor + layer.strokeColor = model.color.main.uiColor.cgColor + layer.lineWidth = model.stripeWidth } static func stripesMaskLayer(