SwiftUI - How to add foreground linear gradient on image
Solution 1
The task here is to display gradient over an image. To display one view over another SwiftUI provides ZStack
view, so, the code can have the next structure:
ZStack {
<Image>
<Rectangle with gradient>
}
Additionally, to make sure the image we use is resized correctly to the specified frame resizable
modifier should be applied with correct contentMode
:
Image("IconLoseWeight")
.resizable() // Make it resizable
.aspectRatio(contentMode: .fit) // Specifying the resizing mode so that image scaled correctly
After all, we need to apply frame
and padding parameter to ZStack
so that gradient has the same size as the image.
The result would look like that:
ZStack {
Image("IconLoseWeight")
.resizable() // Making the image resizable to the container size
.aspectRatio(contentMode: .fit) // Setting up resizing mode so that the image scaled correctly
Rectangle() // Shapes are resizable by default
.foregroundColor(.clear) // Making rectangle transparent
.background(LinearGradient(gradient: Gradient(colors: [.clear, .black]), startPoint: .top, endPoint: .bottom), cornerRadius: 0)
// Specifying gradient (note that one color is .clear)
}
.frame(width: 30, height: 30) // Applying frame
.padding(.leading, 17) // Applying padding
Note, that we use a gradient from .clear
to .black
as we need a transparent gradient to make the image visible.
Solution 2
That's because foregroundColor wants a Color
, but LinearGradient
is a struct
that conforms to the protocols ShapeStyle
and View
.
If I understand you correctly you want to fill the intransparent area of an image with a gradient?
ZStack {
Color.white // For the background. If you don't need a background, you don't need the ZStack.
LinearGradient(gradient: Gradient(colors: [.green, .blue]), startPoint: .top, endPoint: .bottom)
.mask(Image("AssetWithTransparency")
.resizable()
.padding()
.aspectRatio(contentMode: .fit))
}.cornerRadius(15)
The result looks like this:
Solution 3
Agree with @RyuX51's answer and it's working well. But some how size and alignment of my image got changed. Because LinearGradient
's frame
isn't set.
So here i came up with the solution for just applying gradient to the Image
,
VStack{
Spacer()
Button(action: {
print("Add Photos")
}, label: {
LinearGradient(gradient: Gradient(colors: [.green, .blue]), startPoint: .top, endPoint: .bottom)
.mask(Image(systemName: "plus.circle.fill")
.resizable()
.aspectRatio(contentMode: .fit)
).frame(width: 70, height: 70, alignment: .center)
})
}
Comments
-
Rodrigo Mata almost 2 years
I am unable to find any related documentation on how to do a linear gradient on the foreground for an image I have with SwiftUI.
I have tried to do it like so:
Image("IconLoseWeight") .frame(width: 30.0, height: 30.0) .padding(.leading, 17) .foregroundColor(LinearGradient(gradient: Gradient(colors: [.white, .black]), startPoint: .top, endPoint: .bottom))
Actually, the code shown above doesn't display any errors, but it breaks the code with warnings that make no sense in the top level Stacks (which I think is a bug with Xcode or SwiftUI). If I remove the
foreground
modifier, the code runs perfectly. -
CIB almost 5 yearsIs it possible to start the gradient at 100px from the top? So you would have a 100px solid colour then the gradient fades out from there?
-
Shaun over 4 yearsGreat solution and example!
-
slimbikr about 4 yearsop wanted a gradient on the foreground (Color) not the background (View)
-
iGhost almost 4 years
.aspectRatio(contentMode: .fit)
is not necessary , but it's fine. Work perfectly ! -
oskarko about 3 yearsThis piece of code saved my life! Thank you so much, mate!!