I am building app to practise my swiftUI skills, I created design with figma and copying that to my xcode, I Think I did it well while my device was Iphone 12 pro max, but after switching to for example: Iphone se the whole design is ruined. How can I Fix design to look good on all iphones
BTW I use .offset's alot, is that the problem ?
ZStack{
Color("background").ignoresSafeArea()
Image("Group 7").offset(x:-163)
Image("Group 6").offset(x:150, y:-400)
Image("Group 8").offset(x:150,y:50)
VStack{
Text("drink water").font(.custom("Lobster 1.4.otf", size: 60)).foregroundColor(Color(#colorLiteral(red: 0.9, green: 0.93, blue: 0.92, alpha: 1))).tracking(-0.3).multilineTextAlignment(.center).shadow(color: Color(#colorLiteral(red: 0, green: 0, blue: 0, alpha: 0.25)), radius:4, x:0, y:4)
Image(uiImage: #imageLiteral(resourceName: "Fitz Water"))
.resizable()
.aspectRatio(contentMode: .fit)
.frame(width: 375, height: 251)
.clipped()
.frame(width: 375, height: 251)
.shadow(color: Color(#colorLiteral(red: 0.9791666865348816, green: 0.9628472328186035, blue: 0.9628472328186035, alpha: 0.25)), radius:25, x:0, y:20)
Spacer()
}
VStack{
Text("Today you have only drank: 0,5 Litres").font(.system(size: 25, weight: .regular, design: .rounded)).foregroundColor(Color(#colorLiteral(red: 0.9, green: 0.93, blue: 0.92, alpha: 1))).tracking(-0.3).multilineTextAlignment(.leading).shadow(color: Color(#colorLiteral(red: 0, green: 0, blue: 0, alpha: 0.25)), radius:4, x:0, y:4).offset(x:38)
.padding(10)
Text("Which is not enough...").font(.system(size: 25, weight: .regular, design: .rounded)).foregroundColor(Color(#colorLiteral(red: 0.9, green: 0.93, blue: 0.92, alpha: 1))).tracking(-0.3).multilineTextAlignment(.leading).shadow(color: Color(#colorLiteral(red: 0, green: 0, blue: 0, alpha: 0.25)), radius:4, x:0, y:4).offset(x:-37)
.padding(10)
Text("You need to drink ").font(.system(size: 25, weight: .regular, design: .rounded)).foregroundColor(Color(#colorLiteral(red: 0.9, green: 0.93, blue: 0.92, alpha: 1))).tracking(-0.3).multilineTextAlignment(.leading).shadow(color: Color(#colorLiteral(red: 0, green: 0, blue: 0, alpha: 0.25)), radius:4, x:0, y:4).offset(x:-57)
.padding(10)
Text("1.5").font(.custom("Prompt Regular", size: 110)).foregroundColor(Color(#colorLiteral(red: 0.14, green: 0.73, blue: 1, alpha: 1))).tracking(-0.3).multilineTextAlignment(.center).shadow(color: Color(#colorLiteral(red: 0, green: 0, blue: 0, alpha: 0.25)), radius:1, x:0, y:2)
Text("Litres more").font(.system(size: 25, weight: .regular, design: .rounded)).foregroundColor(Color(#colorLiteral(red: 0.9, green: 0.93, blue: 0.92, alpha: 1))).tracking(-0.3).multilineTextAlignment(.leading).shadow(color: Color(#colorLiteral(red: 0, green: 0, blue: 0, alpha: 0.25)), radius:4, x:0, y:4).offset(x:-90)
.padding(10)
Button(action: {
print("Edit button was tapped")
}) {
Image("ASD")
}.offset(x:180,y:50)
}.position(x: 160, y: 550)
}
Related
I'm converting my project to SwiftUI and I use a background with gradient. I can't figure out how to convert the below to a SwiftUI view:
let layer = CAGradientLayer()
layer.colors = [
UIColor(red: 0.165, green: 0.224, blue: 0.314, alpha: 1).cgColor,
UIColor(red: 0.112, green: 0.17, blue: 0.26, alpha: 1).cgColor]
layer.locations = [0.45, 1]
layer.startPoint = CGPoint(x: 0.25, y: 0.5)
layer.endPoint = CGPoint(x: 0.75, y: 0.5)
layer.transform = CATransform3DMakeAffineTransform(CGAffineTransform(a: 0, b: 0.46, c: -0.46, d: 0, tx: 0.73, ty: 0.68))
layer.bounds = view.bounds.insetBy(dx: -0.5*view.bounds.size.width, dy: -0.5*view.bounds.size.height)
layer.position = view.center
view.layer.addSublayer(layer)
I tried the below, but the results are not the same:
LinearGradient(gradient: Gradient(colors: [Color("BackgroundNEWTop"), Color("BackgroundNEWBottom")]), startPoint: .top, endPoint: .bottom))
After I tested your UIKit code, this is the closest one I replicated in SwiftUI. I included the result image here, but you should try this code yourself first because the online image may look slightly different.
Sample Code and Image are below:
struct SampleView: View {
let color1 = Color.init(red: 0.112, green: 0.17, blue: 0.26)
let color2 = Color.init(red: 0.165, green: 0.224, blue: 0.314)
var body: some View {
ZStack {
LinearGradient(colors: [color1, color2],
startPoint: UnitPoint(x: 0.75, y: 0.5),
endPoint: UnitPoint(x: 0.25, y: 0.5))
}
}
}
Currently, my code uses a series of switch result cases that asks questions and presents different answer choices. For example, when the user clicks Evening, the code will present a new question with the answer choices being "Sweet" and "Savory". How can I put a cool transition where the "Morning" and "Evening" choices turn into the "Sweet" and "Savory" choices? Open to any transitions that you'd recommend.
var body: some View {
let cardWidth = 300
let cardWidthValue = CGFloat(cardWidth)
let cardHeight = 300
let cardHeightValue = CGFloat(cardHeight)
VStack {
ZStack {
Rectangle()
.fill(Color(red: 0.0, green: 0.5, blue: 1.0, opacity: 0.4))
.frame(width: 350, height: 250)
.cornerRadius(20)
.shadow(color: .gray, radius: 20)
switch result {
case "Start":
VStack{
Text("What time is it?")
.padding()
.foregroundColor(Color.white)
.font(.system(size: 30.0, weight: .bold))
HStack {
Button {
result = "M"
} label: {
Text("Morning🌥")
.foregroundColor(Color.white)
.frame(width: 165, height: 100)
.background(Color(red: 0.0, green: 0.0, blue: 1.0, opacity: 1.0))
.cornerRadius(10)
}
Button {
result = "E"
} label: {
Text("Evening☀️")
.foregroundColor(Color.white)
.frame(width: 165, height: 100)
.background(Color(red: 0.0, green: 0.0, blue: 1.0, opacity: 1.0))
.cornerRadius(10)
}
}
}
case "E":
VStack{
Text("Sweet or Savory?")
.padding()
.foregroundColor(Color.white)
.font(.system(size: 30.0, weight: .bold))
HStack {
Button {
result = "EveningSweet"
} label: {
Text("Sweet🍦")
}
.foregroundColor(Color.white)
.frame(width: 165, height: 100)
.background(Color(red: 0.0, green: 0.0, blue: 1.0, opacity: 1.0))
.cornerRadius(10)
Button {
result = "EveningSavory"
} label: {
Text("Savory🧂")
}
.foregroundColor(Color.white)
.frame(width: 165, height: 100)
.background(Color(red: 0.0, green: 0.0, blue: 1.0, opacity: 1.0))
.cornerRadius(10)
}
}
Using withAnimation{} to animate your event.
Let's say you want to animate views after you click on Evening:
Button {
withAnimation { //here
result = "E"
}
} label: {
Text("Evening☀️")
.foregroundColor(Color.white)
.frame(width: 165, height: 100)
.background(Color(red: 0.0, green: 0.0, blue: 1.0, opacity: 1.0))
.cornerRadius(10)
}
This mean that all views that are related to this event of result = "E" shall be animated. The default transition of all animation is .opacity.
After trying the first case, if you want to change transition type, use .transition()
case "E":
VStack {
}.transition(.slide)
You will see a different animation from the first time that you did not set transition equals to slide.
I would recommend you try the first option without .slide first to see the difference.
i have this card thing in the picture to build, here're the code:
struct ArticleCard: View {
var article: Article
var body: some View {
ZStack {
Color.white
.border(Color(red: 0, green: 0, blue: 0, opacity: 0.2))
.shadow(color: Color(red: 0, green: 0, blue: 0, opacity: 0.2), radius: 0.0, x: 5, y: 5)
VStack{
Text(article.title)
.padding(.top, 5)
.padding(.leading)
.padding(.trailing)
.font(.title2)
Image(article.coverUrl).resizable()
.frame(height: 200)
.padding(.leading)
.padding(.trailing)
Text(article.title)
.padding(.leading)
.padding(.trailing)
.padding(.bottom)
}
}
}
}
in the ZStack i put a Color.white there as a background of the card, and give this color view a shadow, but the color seems to be transparent, therefor i got unwanted lines on the top and the left inside the borders, how do i get rid of them?
You are using border and shadow in wrong place, try this:
PS: there is no reason of using Color(red: 0, green: 0, blue: 0, opacity: 0.2) you can use this: Color.black.opacity(0.2)
import SwiftUI
struct ContentView: View {
var body: some View {
ZStack {
Color.white
VStack {
Text("article.title")
.padding()
Image(systemName: "star")
.resizable()
.scaledToFit()
Text("article.title")
.padding()
}
}
.frame(width: 300, height: 300, alignment: .center)
.border(Color(red: 0, green: 0, blue: 0, opacity: 0.2))
.compositingGroup()
.shadow(color: Color(red: 0, green: 0, blue: 0, opacity: 0.2), radius: 0.0, x: 5, y: 5)
}
}
I refactored your code for better and less code as possible you can use Image instead of Text in your App.
import SwiftUI
struct ContentView: View {
var body: some View {
VStack {
Text("your custom Text")
.padding()
Text("🥩")
.font(Font.system(size: 150))
Text("your custom Text")
.padding()
}
.frame(width: 300, height: 300, alignment: .center)
.background(Color.white)
.border(Color.black.opacity(0.2))
.compositingGroup()
.shadow(color: Color.black.opacity(0.2), radius: 0.0, x: 5, y: 5)
}
}
I am trying to create a shaded cross-hatched. But so far I can do it by adding a Image.
How can I create a custom view in which lines will be drawn and not filled with a Image?
import SwiftUI
struct ContentView: View {
var body: some View {
ZStack {
Image("lineFilledBG").resizable().clipShape(Circle())
Circle().stroke()
Circle().foregroundColor(.yellow).opacity(0.3)
}
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}
This is how it looks now. Want lines to draw on top of another view or shape, without adding opacity and image pattern filling.
Thank to Cenk Bilgen for stripe pattern. Tweaked a bit so that you can rotate the hatch for any shape.
import SwiftUI
import CoreImage.CIFilterBuiltins
extension CGImage {
static func generateStripePattern(
colors: (UIColor, UIColor) = (.clear, .black),
width: CGFloat = 6,
ratio: CGFloat = 1) -> CGImage? {
let context = CIContext()
let stripes = CIFilter.stripesGenerator()
stripes.color0 = CIColor(color: colors.0)
stripes.color1 = CIColor(color: colors.1)
stripes.width = Float(width)
stripes.center = CGPoint(x: 1-width*ratio, y: 0)
let size = CGSize(width: width, height: 1)
guard
let stripesImage = stripes.outputImage,
let image = context.createCGImage(stripesImage, from: CGRect(origin: .zero, size: size))
else { return nil }
return image
}
}
extension Shape {
func stripes(angle: Double = 45) -> AnyView {
guard
let stripePattern = CGImage.generateStripePattern()
else { return AnyView(self)}
return AnyView(Rectangle().fill(ImagePaint(
image: Image(decorative: stripePattern, scale: 1.0)))
.scaleEffect(2)
.rotationEffect(.degrees(angle))
.clipShape(self))
}
}
And usage
struct ContentView: View {
var body: some View {
VStack {
Rectangle()
.stripes(angle: 30)
Circle().stripes()
Capsule().stripes(angle: 90)
}
}
}
Output image link
I'm not sure this is what you want, but CoreImage can generate a striped pattern.
import CoreImage.CIFilterBuiltins
import SwiftUI
extension CGImage {
// width is for total, ratio is second stripe relative to full width
static func stripes(colors: (UIColor, UIColor), width: CGFloat, ratio: CGFloat) -> CGImage {
let filter = CIFilter.stripesGenerator()
filter.color0 = CIColor(color: colors.0)
filter.color1 = CIColor(color: colors.1)
filter.width = Float(width-width*ratio)
filter.center = CGPoint(x: width, y: 0)
let size = CGSize(width: width+width*ratio, height: 1)
let bounds = CGRect(origin: .zero, size: size)
// keep a reference to a CIContext if calling this often
return CIContext().createCGImage(filter.outputImage!.clamped(to: bounds), from: bounds)!
}
}
then use ImagePaint
Circle().fill(
ImagePaint(image: Image(decorative: CGImage.stripes(colors: (.blue, .yellow), width: 80, ratio: 0.25), scale: 1))
)
.rotationEffect(.degrees(-30))
Or CILineScreen filter may be more what you want.
I`m not sure what do you want but another possible solution is using different backgrounds in a ZStack linear gradient and shadows to make convex or concave effect., for this it helps that your background with a little color, not white white. some samples:
The code:
struct ContentView: View {
var body: some View {
ZStack {
Color.yellow.opacity(0.1)
VStack(spacing: 50) {
myCircle()
myCircle1()
}
}
}
}
struct myCircle: View {
var body: some View {
Circle().foregroundColor(Color.clear)
.frame(width: 100, height: 100)
.background(
ZStack {
LinearGradient(gradient: Gradient(colors: [Color( #colorLiteral(red: 0.9764705896, green: 0.850980401, blue: 0.5490196347, alpha: 1) ), Color(#colorLiteral(red: 1, green: 1, blue: 1, alpha: 1))]), startPoint: .topLeading, endPoint: .bottomTrailing)
Circle()
.stroke(Color.clear, lineWidth: 10)
.shadow(color: Color(#colorLiteral(red: 1, green: 1, blue: 1, alpha: 1)), radius: 3, x: -5, y: -5)
Circle()
.stroke(Color.clear, lineWidth: 10)
.shadow(color: Color(#colorLiteral(red: 0.9764705896, green: 0.850980401, blue: 0.5490196347, alpha: 1)), radius: 3, x: 3, y: 3)
}
)
.clipShape(Circle())
.shadow(color: Color( #colorLiteral(red: 1, green: 1, blue: 1, alpha: 1) ), radius: 20, x: -20, y: -20)
.shadow(color: Color( #colorLiteral(red: 0.9764705896, green: 0.850980401, blue: 0.5490196347, alpha: 1) ), radius: 20, x: 20, y: 20)
}
}
struct myCircle1: View {
var body: some View {
Circle().foregroundColor(Color.clear)
.frame(width: 100, height: 100)
.background(
ZStack {
LinearGradient(gradient: Gradient(colors: [Color( #colorLiteral(red: 1, green: 1, blue: 1, alpha: 1) ), Color(#colorLiteral(red: 0.9764705896, green: 0.850980401, blue: 0.5490196347, alpha: 1))]), startPoint: .topLeading, endPoint: .bottomTrailing)
Circle()
.stroke(Color.clear, lineWidth: 10)
.shadow(color: Color(#colorLiteral(red: 1, green: 1, blue: 1, alpha: 1)), radius: 3, x: -5, y: -5)
Circle()
.stroke(Color.clear, lineWidth: 10)
.shadow(color: Color(#colorLiteral(red: 0.9764705896, green: 0.850980401, blue: 0.5490196347, alpha: 1)), radius: 3, x: 3, y: 3)
}
)
.clipShape(Circle())
.shadow(color: Color( #colorLiteral(red: 1, green: 1, blue: 1, alpha: 1) ), radius: 20, x: -20, y: -20)
.shadow(color: Color( #colorLiteral(red: 0.9764705896, green: 0.850980401, blue: 0.5490196347, alpha: 1) ), radius: 20, x: 20, y: 20)
}
}
Thank you to Cenk Bilgen and flyer2001, I edited the code and come up with this code so it can be used with a view.
import SwiftUI
import CoreImage.CIFilterBuiltins
extension CGImage {
static func generateStripePattern(
colors: (UIColor, UIColor) = (.clear, .black),
width: CGFloat = 6,
ratio: CGFloat = 1) -> CGImage? {
let context = CIContext()
let stripes = CIFilter.stripesGenerator()
stripes.color0 = CIColor(color: colors.0)
stripes.color1 = CIColor(color: colors.1)
stripes.width = Float(width)
stripes.center = CGPoint(x: 1 - (width * ratio), y: 0)
let size = CGSize(width: width, height: 1)
guard
let stripesImage = stripes.outputImage,
let image = context.createCGImage(stripesImage, from: CGRect(origin: .zero, size: size))
else { return nil }
return image
}
}
struct ViewStripes : ViewModifier {
var stripeColor : Color
var width : CGFloat
var ratio : CGFloat
var angle : Double
var frameW : CGFloat
var frameH : CGFloat
func body(content: Content) -> some View {
if let stripePattern = CGImage.generateStripePattern(colors: (.clear,UIColor(stripeColor)), width: width, ratio: ratio) {
content
.overlay(Rectangle().fill(ImagePaint(image: Image(decorative: stripePattern, scale: 1.0)))
.frame(width: hypotenuse((frameW / 2), frameH / 2) * 2, height: hypotenuse(frameW / 2, frameH / 2) * 2)
//.scaleEffect(1)
.rotationEffect(.degrees(angle))
.mask(content))
}
}
}
extension View {
func drawStripes(stripeColor: Color, width: CGFloat, ratio: CGFloat, angle : Double, frameW : CGFloat, frameH : CGFloat) -> some View {
modifier(ViewStripes(stripeColor: stripeColor, width: width, ratio: ratio, angle: angle, frameW: frameW, frameH: frameH))
}
}
func hypotenuse(_ a: Double, _ b: Double) -> Double {
return (a * a + b * b).squareRoot()
}
And for usage:
Rectangle()
.foregroundColor(Color.Red)
.frame(width:20, height: 20)
//This is the code itself
.drawStripes(stripeColor: Color.white, width: 3, ratio: 0.9, angle: 45, frameW: 20, frameH: 20)
Hope it may be helpful for someone.
How do I apply a linear gradient with a custom class that I made on a shape? For some reason it is not working for me. The foregroundColor is not working for me.
RoundedRectangle(cornerRadius: 30)
.frame(width: geometry.size.width * 1.01, height:geometry.size.height * 0.23)
.rotationEffect(.degrees(12), anchor: .center)
.foregroundColor(LinearGradient (gradient: Gradient(colors:[Color(ColorsSaved.gitLabDark),Color(ColorsSaved.gitLabLight)]),startPoint: .leading,endPoint: .trailing))
I created my CustomClass in a Swift file. Please see code below for that.
import Foundation
import UIKit
struct ColorsSaved {
static let gitLabDark = UIColor( red: 0.12, green: 0.08, blue: 0.22, alpha: 1.0)
static let gitLabLight = UIColor( red: 0.26, green: 0.2, blue: 0.44, alpha: 1.0)
static let neonGreen = UIColor(red: 0.497, green: 0.738, blue: 0.35, alpha: 1)
static let darkGreenTorquise = UIColor(red: 0.242, green: 0.683, blue: 0.577, alpha: 1)
static let brightOrange = UIColor(red: 0.917, green: 0.469, blue: 0.218, alpha: 1)
If I correctly understood your intention, I would go with the following approach.
Result demo:
Code:
GeometryReader { geometry in
LinearGradient(gradient:
Gradient(colors:
[Color(ColorsSaved.gitLabDark), Color(ColorsSaved.gitLabLight)]),
startPoint: .leading, endPoint: .trailing)
.frame(width: geometry.size.width * 1.01, height:geometry.size.height * 0.23)
.mask(RoundedRectangle(cornerRadius: 30))
.rotationEffect(.degrees(12), anchor: .center)
}
Gradients in SwiftUI are supposed to be added with the help of ZStack. As you haven't added much code in your question I made my assumptions. Try this in your custom view:
struct WelcomeView: View {
var body: some View {
ZStack {
LinearGradient(gradient: Gradient(colors: [.pink, .purple]), startPoint: .leading, endPoint: .trailing)
// here goes your other view component
Text("Welcome, John")
}
}
}