After trimming a Circle(), its borders lose smoothness.
struct WidgetsEntryView : View {
var entry: Provider.Entry
var body: some View {
VStack {
ZStack {
Circle()
.trim(from: 0.0, to: min(CGFloat(0.5), 1.0))
.stroke(Color.green, style: StrokeStyle(lineWidth: 10, lineCap: .round, lineJoin: .round))
.rotationEffect(Angle(degrees: 270))
}
Text("Subtitle")
.foregroundColor(.white)
}
.padding()
.background(Color.black)
}
}
If you remove the padding, text, or the trimming itself anti-aliasing returned.
Related
I have a View stack as Expanded white part and I have given the corner radius to it, I need to give radius to only top left and top right
My Code
struct loginView: View {
#State private var stringOfTextField: String = String()
var body: some View {
ZStack {
LinearGradient(colors: [Color("primarycolor"), Color("secondarycolor")],
startPoint: .top,
endPoint: .center).ignoresSafeArea()
VStack() {
Text("Login").foregroundColor(.white).font(
.system(size: 18)
)
Image("logo")
Spacer()
}
VStack {
Spacer(minLength: 230)
VStack{
HStack {
Image(systemName: "person").foregroundColor(.gray)
TextField("Enter Email", text: $stringOfTextField)
} .padding()
.overlay(RoundedRectangle(cornerRadius: 10.0).strokeBorder(Color.gray, style: StrokeStyle(lineWidth: 1.0)))
.padding(.bottom)
TextField("Enter Password", text: $stringOfTextField)
.padding()
.overlay(RoundedRectangle(cornerRadius: 10.0).strokeBorder(Color.gray, style: StrokeStyle(lineWidth: 1.0)))
.padding(.bottom)
Text("Forgot Password ?")
.frame(maxWidth: .infinity, alignment: .trailing)
.padding(.bottom)
Button(action: {
print("sign up bin tapped")
}) {
Text("SIGN IN")
.frame(minWidth: 0, maxWidth: .infinity)
.font(.system(size: 18))
.padding()
.foregroundColor(.white)
.overlay(
RoundedRectangle(cornerRadius: 10)
.stroke(Color("secondarycolor"), lineWidth: 1)
)
}
.background(Color("secondarycolor"))
.cornerRadius(25)
Spacer()
}
.padding(.vertical, 60)
.padding(.horizontal, 20)
.background(Color.white)
.cornerRadius(30)
}
}
.ignoresSafeArea(edges: [.bottom])
}
}
Preview
You can see on the end it's showing white border because border is given to all sides, I need to give it to top 2 sides only. I try by Roundedcorner, but that was not working.
You can try like this
struct ContentView: View {
var body: some View {
VStack{
//....
//your content
//.....
}
.clipShape(CustomCorner(corners: [.topLeft, .topRight], radius: 25))
}
}
struct CustomCorner: Shape {
var corners : UIRectCorner
var radius : CGFloat
func path(in rect: CGRect)->Path{
let path = UIBezierPath(roundedRect: rect, byRoundingCorners: corners, cornerRadii: CGSize(width: radius, height: radius))
return Path(path.cgPath)
}
}
I've created a progress circle for my App, that will count down from 28 to 0 (number of days until Payday)
I've got the circles to display how I'd like, but I want it to animate when I navigate to the view, is there a way to do this?
More a UI question, but do you think maybe an arrow within the circle to indicate the direction would look any good?
P.s - any ideas how to truncate all the zeros off my Double?
image of how this looks
Thanks!
ZStack {
let progressPeriod = Double(PayData.daysUntilPay) ?? 0
let progressPeriod2 = 1 - (progressPeriod / 28)
Circle()
.stroke(lineWidth: 30.0)
.opacity(0.3)
.foregroundColor(Color(red: 0.941, green: 0.426, blue: 0.004))
.frame(width:150)
.frame(height: 200)
Circle()
.trim(from: 0.0, to: progressPeriod2)
.stroke(style: StrokeStyle(lineWidth: 30.0, lineCap: .round, lineJoin: .round))
.foregroundColor(Color(red: 0.941, green: 0.426, blue: 0.004))
.rotationEffect(Angle(degrees: 270.0))
.frame(width:150)
.frame(height: 200)
Text("\(progressPeriod) days")
.bold()
}
Try to combine following code with your countdown:
struct ContentView: View {
#State var progressValue: Float = 0.0
var body: some View {
ZStack {
Color.yellow
.opacity(0.1)
.edgesIgnoringSafeArea(.all)
VStack {
ProgressBar(progress: self.$progressValue)
.frame(width: 150.0, height: 150.0)
.padding(40.0)
Button(action: {
self.incrementProgress()
}) {
HStack {
Image(systemName: "plus.rectangle.fill")
Text("Increment")
}
.padding(15.0)
.overlay(
RoundedRectangle(cornerRadius: 15.0)
.stroke(lineWidth: 2.0)
)
}
Spacer()
}
}
}
func incrementProgress() {
let randomValue = Float([0.012, 0.022, 0.034, 0.016, 0.11].randomElement()!)
self.progressValue += randomValue
}
}
struct ProgressBar: View {
#Binding var progress: Float
var body: some View {
ZStack {
Circle()
.stroke(lineWidth: 20.0)
.opacity(0.3)
.foregroundColor(Color.red)
Circle()
.trim(from: 0.0, to: CGFloat(min(self.progress, 1.0)))
.stroke(style: StrokeStyle(lineWidth: 20.0, lineCap: .round, lineJoin: .round))
.foregroundColor(Color.red)
.rotationEffect(Angle(degrees: 270.0))
.animation(.linear)
Text(String(format: "%.0f %%", min(self.progress, 1.0)*100.0))
.font(.largeTitle)
.bold()
}
}
}
import SwiftUI
struct CircularProgressView: View {
#Binding var progress: Float
private let strokeStyle = StrokeStyle(lineWidth: 30.0, lineCap: .round, lineJoin: .round)
private let rotation = Angle(degrees: 270.0)
var body: some View {
ZStack {
Circle()
.trim(from: 0.0, to: CGFloat(min(self.progress, 1.0)))
.stroke(style: strokeStyle)
.opacity(0.2)
.foregroundColor(Color.black)
.rotationEffect(rotation)
.offset(x: 0, y: 10)
Circle()
.trim(from: 0.0, to: CGFloat(min(self.progress, 1.0)))
.stroke(style: strokeStyle)
.opacity(1)
.foregroundColor(Color.white)
.rotationEffect(rotation)
}
.animation(.linear(), value: progress)
}
}
struct CircularProgressView_Previews: PreviewProvider {
static var previews: some View {
OtherView(progress: 0.6)
}
struct OtherView : View {
#State var progress : Float = 0.0
var body: some View {
ZStack {
Color.yellow
VStack {
CircularProgressView(progress: self.$progress)
.padding(50)
Button(action: {
if(progress >= 1) {
progress = 0
} else {
progress += 0.1
}
}) {
Text("try me")
.frame(width: 200, height: 50)
.overlay(
RoundedRectangle(cornerRadius: 20)
.stroke(Color.blue, lineWidth: 2)
)
.padding(.bottom, 100)
}
}
}.ignoresSafeArea()
}
}
}
What could be the reason?
It is unclear definitely, probably due to undefined size of shapes as a nature... Anyway, seems using drawing group fixes the issue.
Here is a fixed code. Tested with Xcode 13 / iOS 15.
struct CircularProgressView: View {
#Binding var progress: Float
private let strokeStyle = StrokeStyle(lineWidth: 30.0, lineCap: .round, lineJoin: .round)
private let rotation = Angle(degrees: 270.0)
var body: some View {
ZStack {
Group {
Circle()
.trim(from: 0.0, to: CGFloat(min(self.progress, 1.0)))
.stroke(style: strokeStyle)
.opacity(0.2)
.foregroundColor(Color.black)
.rotationEffect(rotation)
.offset(x: 0, y: 10)
Circle()
.trim(from: 0.0, to: CGFloat(min(self.progress, 1.0)))
.stroke(style: strokeStyle)
.opacity(1)
.foregroundColor(Color.white)
.rotationEffect(rotation)
}
.padding() // << compensate offset within own bounds
}
.drawingGroup() // << here !!
.animation(.linear, value: progress)
}
}
struct CircularProgressView_Previews: PreviewProvider {
static var previews: some View {
OtherView(progress: 0.6)
}
struct OtherView : View {
#State var progress : Float = 0.0
var body: some View {
ZStack {
Color.yellow
VStack {
CircularProgressView(progress: self.$progress)
.padding()
Button(action: {
if(progress >= 1) {
progress = 0
} else {
progress += 0.1
}
}) {
Text("try me")
.frame(width: 200, height: 50)
.overlay(
RoundedRectangle(cornerRadius: 20)
.stroke(Color.blue, lineWidth: 2)
)
.padding(.bottom, 100)
}
}
}.ignoresSafeArea()
}
}
}
The problem is I don't understand how to fix my Content View to the screen and handle things like rotation or even how to make other screen sizes dynamic. Below is my entire View code. When I create a new app out of the box it looks fine in preview, the way I like it. However, screen sizes change and all I know to do is put magic numbers, because there is no superview or frame to size from. Also I can't seem to clip at screen edges. So my background view is way to big. How is this handled in SwiftUI?
import SwiftUI
import AuthenticationServices
struct LoginScreen: View {
var body: some View {
ZStack{
backgroundLayout
loginLayout
}
}
var loginLayout: some View {
VStack {
welcomeText
signInWithAppleButton
}
}
var backgroundLayout: some View {
ZStack{
Rectangle()
.foregroundColor(.init(.sRGB, red: 0, green: 0.750, blue: 0.750, opacity: 0.25))
Circle()
.foregroundColor(.blue)
.offset(x: 200, y: -200)
.aspectRatio(1/3, contentMode: .fill)
.clipped()
Circle()
.foregroundColor(.green)
.offset(x: -200, y: 200)
.aspectRatio(1/3, contentMode: .fill)
.clipped()
}
}
var welcomeText: some View {
HStack {
VStack {
Text("Sign Up")
.font(.largeTitle)
.bold()
Text("Sign In")
.font(.title)
.bold()
Text("Get Started!")
.font(.title2)
.bold()
}
.offset(x: -100, y: -150)
}
}
var signInWithAppleButton: some View {
SignInWithAppleButton(
.continue,
onRequest: { request in
request.requestedScopes = [.fullName, .email]
},
onCompletion: { result in
switch result {
case .success (let authenticationResults):
print("Authorization successful! :\(authenticationResults)")
case .failure(let error):
print("Authorization failed: " + error.localizedDescription)
}
}
)
.offset(x: 0, y: 150)
.frame(width: 200, height: 50, alignment: .center)
}
}
struct Login_Preview: PreviewProvider {
static var previews: some View {
LoginScreen()
}
}
After trying several things this is all I could come up with. It's not perfect and certainly not ideal, but at least it work somewhat as expected.
import SwiftUI
import AuthenticationServices
struct LoginScreen: View {
var body: some View {
loginLayout.background(backgroundLayout)
.statusBar(hidden: true)
}
var loginLayout: some View {
GeometryReader {geo in
VStack {
welcomeText.padding(.top, geo.size.height / 10)
Spacer()
signInWithAppleButton
.padding(.bottom, geo.size.height / 10)
}
}
}
var backgroundLayout: some View {
GeometryReader { geo in
let circleSize = min(geo.size.width, geo.size.height)
ZStack {
Rectangle()
.foregroundColor(.init(.sRGB, red: 0, green: 0.750, blue: 0.750, opacity: 0.25))
Circle()
.foregroundColor(.blue)
.offset(x: circleSize / 1.75,
y: -geo.size.height / 2.5)
.frame(width: circleSize, height: circleSize, alignment: .center)
Circle()
.foregroundColor(.green)
.offset(x: -circleSize / 1.75, y: geo.size.height / 2.5)
.frame(width: circleSize, height: circleSize, alignment: .center)
}
.frame(width: geo.size.width, height: geo.size.height, alignment: .top)
}
}
var welcomeText: some View {
GeometryReader { geo in
HStack {
VStack {
Text("Sign Up")
.font(.largeTitle)
.bold()
Text("Sign In")
.font(.title)
.bold()
Text("Get Started!")
.font(.title2)
.bold()
}
.padding(.leading, geo.size.width / 8)
Spacer()
}
}
}
var signInWithAppleButton: some View {
SignInWithAppleButton(
// Add this below for Continue with Apple button
.continue,
onRequest: { request in
request.requestedScopes = [.fullName, .email]
},
onCompletion: { result in
switch result {
case .success (let authenticationResults):
print("Authorization successful! :\(authenticationResults)")
case .failure(let error):
print("Authorization failed: " + error.localizedDescription)
}
}
)
.frame(width: 200, height: 50, alignment: .center)
}
}
struct Login_Preview: PreviewProvider {
static var previews: some View {
LoginScreen()
}
}
I'm trying to add an icon to the tip of the progress bar in the circle. This is the code I have so far:
Circle()
.trim(from: 0, to: 0.6)
.stroke(style: StrokeStyle(lineWidth: 24, lineCap: .round, lineJoin: .round))
.rotationEffect(.degrees(-90))
.foregroundColor(.green)
.frame(width: 300, height: 300)
.padding()
This ends up looking like this:
But I'm trying to add an icon to the tip of the progress like this:
How can I achieve this in SwiftUI?
Use the left arrow icon and put it into the ZStack and set y offset in minus.
struct DemoView: View {
#State private var angle: Double = -90
var body: some View {
ZStack {
Circle()
.trim(from: 0, to: 0.6)
.stroke(style: StrokeStyle(lineWidth: 24, lineCap: .round, lineJoin: .round))
.rotationEffect(.degrees(angle))
.foregroundColor(.green)
Image("left-arrow")
.offset(y: -150)
.rotationEffect(.degrees(305 + angle))
}.frame(width: 300, height: 300)
.padding()
}
}
I have added an image arrow using progress code from here
struct ProgressBar: View {
#Binding var progress: Float
var body: some View {
GeometryReader { geo in
ZStack(alignment: .center) {
Circle()
.stroke(lineWidth: 20.0)
.opacity(0.3)
.foregroundColor(Color.red)
Circle()
.trim(from: 0.0, to: CGFloat(min(self.progress, 1.0)))
.stroke(style: StrokeStyle(lineWidth: 20.0, lineCap: .round, lineJoin: .round))
.foregroundColor(Color.red)
.rotationEffect(Angle(degrees: 270.0))
.animation(.linear)
Text(String(format: "%.0f %%", min(self.progress, 1.0)*100.0))
.font(.largeTitle)
.bold()
Image("left-arrow")
.offset(y: -(geo.size.height/2))
.rotationEffect(.degrees(Double(self.progress) * 360))
.animation(.linear)
}
}
}
}