From 2c558b2bfc78919e7889ff05e5df1e0851ac6f07 Mon Sep 17 00:00:00 2001 From: Mikhail Date: Fri, 6 Feb 2026 13:09:22 +0800 Subject: [PATCH] make size in circular progress view option --- .../CircularProgressPreview.swift | 2 +- .../Models/CircularProgressVM.swift | 36 ++++++--- .../CircularProgress/SUCircularProgress.swift | 74 +++++++++---------- .../CircularProgress/UKCircularProgress.swift | 17 ++--- 4 files changed, 68 insertions(+), 61 deletions(-) diff --git a/Examples/DemosApp/DemosApp/ComponentsPreview/PreviewPages/CircularProgressPreview.swift b/Examples/DemosApp/DemosApp/ComponentsPreview/PreviewPages/CircularProgressPreview.swift index defdae71..0a23ac06 100644 --- a/Examples/DemosApp/DemosApp/ComponentsPreview/PreviewPages/CircularProgressPreview.swift +++ b/Examples/DemosApp/DemosApp/ComponentsPreview/PreviewPages/CircularProgressPreview.swift @@ -40,7 +40,7 @@ struct CircularProgressPreview: View { Text("Circle").tag(CircularProgressVM.Shape.circle) Text("Arc").tag(CircularProgressVM.Shape.arc) } - SizePicker(selection: self.$model.size) + OptionalSizePicker(selection: self.$model.size) } .onReceive(self.timer) { _ in if self.model.currentValue < self.model.maxValue { diff --git a/Sources/ComponentsKit/Components/CircularProgress/Models/CircularProgressVM.swift b/Sources/ComponentsKit/Components/CircularProgress/Models/CircularProgressVM.swift index 3422d75b..d444ae12 100644 --- a/Sources/ComponentsKit/Components/CircularProgress/Models/CircularProgressVM.swift +++ b/Sources/ComponentsKit/Components/CircularProgress/Models/CircularProgressVM.swift @@ -41,8 +41,13 @@ public struct CircularProgressVM: ComponentVM { /// The size of the circular progress. /// + /// If nil, the view is intended to expand to the available space provided by + /// the surrounding layout: + /// - In SwiftUI, constrain it with .frame(...). + /// - In UIKit, constrain it with Auto Layout. + /// /// Defaults to `.medium`. - public var size: ComponentSize = .medium + public var size: ComponentSize? = .medium /// Initializes a new instance of `CircularProgressVM` with default values. public init() {} @@ -55,10 +60,20 @@ extension CircularProgressVM { return 0.2 } var circularLineWidth: CGFloat { - return self.lineWidth ?? max(self.preferredSize.width / 8, 2) + if let lineWidth { + return lineWidth + } else if let width = self.preferredSize?.width { + return max(width / 8, 2) + } else { + return 3 + } } - var preferredSize: CGSize { - switch self.size { + var preferredSize: CGSize? { + guard let size else { + return nil + } + + switch size { case .small: return CGSize(width: 48, height: 48) case .medium: @@ -67,14 +82,11 @@ extension CircularProgressVM { return CGSize(width: 80, height: 80) } } - var radius: CGFloat { - return self.preferredSize.height / 2 - self.circularLineWidth / 2 + func radius(size: CGSize) -> CGFloat { + return min(size.width, size.height) / 2 - self.circularLineWidth / 2 } - var center: CGPoint { - return .init( - x: self.preferredSize.width / 2, - y: self.preferredSize.height / 2 - ) + func center(size: CGSize) -> CGPoint { + return .init(x: size.width / 2, y: size.height / 2) } var startAngle: CGFloat { switch self.shape { @@ -99,7 +111,7 @@ extension CircularProgressVM { switch self.size { case .small: return .smCaption - case .medium: + case .medium, .none: return .mdCaption case .large: return .lgCaption diff --git a/Sources/ComponentsKit/Components/CircularProgress/SUCircularProgress.swift b/Sources/ComponentsKit/Components/CircularProgress/SUCircularProgress.swift index 392e4438..dee6ad47 100644 --- a/Sources/ComponentsKit/Components/CircularProgress/SUCircularProgress.swift +++ b/Sources/ComponentsKit/Components/CircularProgress/SUCircularProgress.swift @@ -40,49 +40,47 @@ public struct SUCircularProgress: View { public var body: some View { ZStack { - // Background part - Path { path in - path.addArc( - center: self.model.center, - radius: self.model.radius, - startAngle: .radians(self.model.startAngle), - endAngle: .radians(self.model.endAngle), - clockwise: false + GeometryReader { geometry in + // Background part + Path { path in + path.addArc( + center: self.model.center(size: geometry.size), + radius: self.model.radius(size: geometry.size), + startAngle: .radians(self.model.startAngle), + endAngle: .radians(self.model.endAngle), + clockwise: false + ) + } + .stroke( + self.model.color.background.color, + style: StrokeStyle( + lineWidth: self.model.circularLineWidth, + lineCap: self.model.lineCap.cgLineCap + ) ) - } - .stroke( - self.model.color.background.color, - style: StrokeStyle( - lineWidth: self.model.circularLineWidth, - lineCap: self.model.lineCap.cgLineCap - ) - ) - .frame( - width: self.model.preferredSize.width, - height: self.model.preferredSize.height - ) - // Foreground part - Path { path in - path.addArc( - center: self.model.center, - radius: self.model.radius, - startAngle: .radians(self.model.startAngle), - endAngle: .radians(self.model.endAngle), - clockwise: false + // Foreground part + Path { path in + path.addArc( + center: self.model.center(size: geometry.size), + radius: self.model.radius(size: geometry.size), + startAngle: .radians(self.model.startAngle), + endAngle: .radians(self.model.endAngle), + clockwise: false + ) + } + .trim(from: 0, to: self.progress) + .stroke( + self.model.color.main.color, + style: StrokeStyle( + lineWidth: self.model.circularLineWidth, + lineCap: self.model.lineCap.cgLineCap + ) ) } - .trim(from: 0, to: self.progress) - .stroke( - self.model.color.main.color, - style: StrokeStyle( - lineWidth: self.model.circularLineWidth, - lineCap: self.model.lineCap.cgLineCap - ) - ) .frame( - width: self.model.preferredSize.width, - height: self.model.preferredSize.height + width: self.model.preferredSize?.width, + height: self.model.preferredSize?.height ) // Optional label diff --git a/Sources/ComponentsKit/Components/CircularProgress/UKCircularProgress.swift b/Sources/ComponentsKit/Components/CircularProgress/UKCircularProgress.swift index 193d2a11..c1777454 100644 --- a/Sources/ComponentsKit/Components/CircularProgress/UKCircularProgress.swift +++ b/Sources/ComponentsKit/Components/CircularProgress/UKCircularProgress.swift @@ -37,7 +37,7 @@ open class UKCircularProgress: UIView, UKComponent { // MARK: - UIView Properties open override var intrinsicContentSize: CGSize { - return self.model.preferredSize + return self.sizeThatFits(UIView.layoutFittingExpandedSize) } // MARK: - Initialization @@ -130,12 +130,9 @@ open class UKCircularProgress: UIView, UKComponent { } private func updateShapePaths() { - let center = CGPoint(x: self.bounds.midX, y: self.bounds.midY) - let minSide = min(self.bounds.width, self.bounds.height) - let radius = (minSide - self.model.circularLineWidth) / 2 let circlePath = UIBezierPath( - arcCenter: center, - radius: radius, + arcCenter: self.model.center(size: self.bounds.size), + radius: self.model.radius(size: self.bounds.size), startAngle: self.model.startAngle, endAngle: self.model.endAngle, clockwise: true @@ -171,10 +168,10 @@ open class UKCircularProgress: UIView, UKComponent { // 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) + let preferredSize = self.model.preferredSize ?? size + return .init( + width: min(preferredSize.width, size.width), + height: min(preferredSize.height, size.height) ) }