I can't modify circular progress bar trim in SwiftUI
struct ContentView: View {
@State private var progress: Double = 0.1
var body: some View {
VStack {
Circle()
.trim(from: 0, to: progress)
.stroke(lineWidth: 20)
.rotationEffect(Angle(degrees: 180))
.shadow(radius: 8)
.rotationEffect(.degrees(90))
.frame(width: 60, height: 60)
.padding()
Slider(value: $progress, in: 0...1)
.padding()
}
}
}
Change size (height) of ProgressView in SwiftUI
There's no direct way that I know of to change the height, but you can use the .scaleEffect
modifier. Make sure to specify 1
for the x scale in order to only increase the height.
struct ContentView: View {
var body: some View {
ProgressBar()
.padding([.leading, .trailing], 10)
}
}
struct ProgressBar: View {
var body: some View {
VStack {
ProgressView(value: 50, total: 100)
.accentColor(Color.green)
.scaleEffect(x: 1, y: 4, anchor: .center)
}
}
}
Result:
A drawback to this is that you can't pass in a Label, because it will also get stretched.
ProgressView("Progress:", value: 50, total: 100)
To work around this, just make your own Text
above the ProgressView
.
struct ProgressBar: View {
var body: some View {
VStack(alignment: .leading) {
Text("Progress:")
.foregroundColor(Color.blue)
ProgressView(value: 50, total: 100)
.accentColor(Color.green)
.scaleEffect(x: 1, y: 4, anchor: .center)
}
}
}
SwiftUI: Change the start position for animated progress bar (or Shape drawing in general)
You don't need to rotate it (moreover it might be not square), just create own rectangular shape with start point anywhere needed.
Demo prepared with Xcode 12.4 / iOS 14.4
struct MyRectangle: Shape {
func path(in rect: CGRect) -> Path {
Path {
$0.move(to: CGPoint(x: rect.midX, y: rect.minY))
$0.addLine(to: CGPoint(x: rect.maxX, y: rect.minY))
$0.addLine(to: CGPoint(x: rect.maxX, y: rect.maxY))
$0.addLine(to: CGPoint(x: rect.minX, y: rect.maxY))
$0.addLine(to: CGPoint(x: rect.minX, y: rect.minY))
$0.addLine(to: CGPoint(x: rect.midX, y: rect.minY))
}
}
}
struct ContentView: View {
@State private var progress: Double = 0
@State private var timer = Timer.publish(every: 0.1, on: .main, in: .common).autoconnect()
var body: some View {
VStack{
HStack{
ZStack {
MyRectangle()
.stroke(lineWidth: 20.0)
.opacity(0.3)
.foregroundColor(Color.gray)
.frame(width: 200, height:100)
MyRectangle()
.trim(from: 0.0, to: CGFloat(min(self.progress, 1.0)))
.stroke(style: StrokeStyle(lineWidth: 20.0, lineCap: .round, lineJoin: .round))
.foregroundColor(Color.blue)
.animation(.linear)
.frame(width: 200, height:100)
.onReceive(timer, perform: { _ in
if(progress < 100){
progress += 0.1/10
}
else{
progress = 0
}
})
}
}
.padding()
}
}
}
Creating a progress indicator with a rounded rectangle
I found a solution so the loading indicator works for round corners:
let queueShapeLayer = CAShapeLayer()
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
// Queue timer
let radius = addToQueue.layer.cornerRadius
let diameter = radius * 2
let totalLength = (addToQueue.frame.width - diameter) * 2 + (CGFloat.pi * diameter)
let queuePath = UIBezierPath(roundedRect: addToQueue.frame, cornerRadius: radius)
queueShapeLayer.path = queuePath.cgPath
queueShapeLayer.lineWidth = 5
queueShapeLayer.strokeColor = UIColor.white.cgColor
queueShapeLayer.fillColor = UIColor.clear.cgColor
queueShapeLayer.strokeStart = 0.25 - CGFloat.pi * diameter / 3 / totalLength // Change the '0.25' to 0.5, 0.75 etc. wherever you want the bar to start
queueShapeLayer.strokeEnd = queueShapeLayer.strokeStart + 0.5 // Change this to the value you want it to go to (in this case 0.5 or 50% loaded)
view.layer.addSublayer(queueShapeLayer)
}
After I had did this though, I was having problems that I couldn't animate the whole way round. To get around this, I created a second animation (setting strokeStart
to 0
) and then I placed completion blocks so I could trigger the animations at the correct time.
Tip:
Add animation.fillMode = CAMediaTimingFillMode.forwards
& animation.isRemovedOnCompletion = false
when using a CABasicAnimation
for the animation to wait until you remove it.
I hope this formula helps anyone in the future!
If you need help, you can always message me and I am willing to help. :)
SwiftUI: How to use a linear gradient in a progress bar?
I think your best bet is to "mask" the gradient, rather than trying to calculate the endPoint
.
Here's an example with 5 "bars" in an HStack
- the first bar has a max value of 10
, then the bars' values go 9, 7.5, 5, 2
:
Sample code:
import SwiftUI
struct GradBars: View {
var maxValue: CGFloat = 10
var val1: CGFloat = 10
var val2: CGFloat = 9
var val3: CGFloat = 7.5
var val4: CGFloat = 5
var val5: CGFloat = 2
@State var open: Bool = true
let gradient = LinearGradient(gradient: Gradient(colors: [ Color(UIColor(red: 0.98, green: 0.85, blue: 0.38, alpha: 1.00)) ,
Color(UIColor(red: 0.63, green: 0.02, blue: 0.11, alpha: 1.00))]),
startPoint: .bottom,
endPoint: .top)
var body: some View {
VStack {
HStack(alignment: .bottom, spacing: 8, content: {
Rectangle()
.fill(gradient)
.frame(width: 40, height: open ? maxValue * 10 : 0, alignment: .bottom)
.mask(
VStack {
RoundedRectangle(cornerRadius: 5.0).frame(height: val1 * 10)
}.frame(maxWidth: .infinity, maxHeight: .infinity, alignment: .bottom)
)
Rectangle()
.fill(gradient)
.frame(width: 40, height: open ? maxValue * 10 : 0, alignment: .bottom)
.mask(
VStack {
RoundedRectangle(cornerRadius: 5.0).frame(height: val2 * 10)
}.frame(maxWidth: .infinity, maxHeight: .infinity, alignment: .bottom)
)
Rectangle()
.fill(gradient)
.frame(width: 40, height: open ? maxValue * 10 : 0, alignment: .bottom)
.mask(
VStack {
RoundedRectangle(cornerRadius: 5.0).frame(height: val3 * 10)
}.frame(maxWidth: .infinity, maxHeight: .infinity, alignment: .bottom)
)
Rectangle()
.fill(gradient)
.frame(width: 40, height: open ? maxValue * 10 : 0, alignment: .bottom)
.mask(
VStack {
RoundedRectangle(cornerRadius: 5.0).frame(height: val4 * 10)
}.frame(maxWidth: .infinity, maxHeight: .infinity, alignment: .bottom)
)
Rectangle()
.fill(gradient)
.frame(width: 40, height: open ? maxValue * 10 : 0, alignment: .bottom)
.mask(
VStack {
RoundedRectangle(cornerRadius: 5.0).frame(height: val5 * 10)
}.frame(maxWidth: .infinity, maxHeight: .infinity, alignment: .bottom)
)
})
}
}
}
struct GradBars_Previews: PreviewProvider {
static var previews: some View {
GradBars()
}
}
Update progress value from fileImporter modifier in SwiftUI
I'd inject progress item in DataManager
via constructor
class DataManager {
private var progressBar: ProgressItem? = nil
init(progressBar: ProgressItem? = nil) {
self.progressBar = progressBar
}
func importData(fileURL: URL, delimeter: String = ",") {
// ... other code
// if importing on background queue
//DispatchQueue.main.async { // this better update async on main queue
progressBar?.progress = Double(index)/Double(numlines) * 100
//}
}
and then inject observed item from view into DataManager
, like
// ... other code
DataManager(progressBar: self.progress).importData(fileURL: selectedFile)
// ... other code
of course somewhere/somewhen you need to reset your current progress item. I don't see any completion in your code, but if you have one it might be inside it.
SwiftUI - Capsule fill till StrokeBorder
I think this is what you are after.
struct ContentView: View {
var body: some View {
HStack{
TextField("Search", text: .constant(""))
}
.padding()
.frame(maxWidth:300)
.background(
Capsule()
.strokeBorder(Color.black,lineWidth: 0.8)
.background(Color.blue)
.clipped()
)
.clipShape(Capsule())
}
}
Xcode preview of HStack with capsule border
Related Topics
Swiftui: How to Only Run Code When the User Stops Typing in a Textfield
Parse.Com Pfgeopoint.Geopointforcurrentlocationinbackground Not Doing Anything
Usage of Withmemoryrebound with Apples Swift 3 Beta 6
Define Struct That Is Treated Like a Class in Swift
Swift Package Manager Unable to Compile Ncurses Installed Through Homebrew
Name Convention for Unwrapped Value in Swift
Optional Type 'Bool' Cannot Be Used as a Boolean; Test for '!=Nil' Instead
Recursion Over a Swift Sliceable
Change Width of a Uibarbuttonitem in a Uinavigationbar in Swift
Cloudkit - "Invalid Bundle Id for Container"
How Does Appdelegate.Swift Replace Appdelegate.H and Appdelegate.M in Xcode 6.3
Swift Codable with Different Array Types
Get Nil When Looking for File in Subdirectory of Main Bundle
Update Nstouchbar on the Fly to Add/Remove Items Programmatically
Swift Alamofire Add Custom Header to All Requests
Swiftui on MACos - Handle Single-Click and Double-Click at the Same Time