SwiftUI, add inverted Opacity - swift

Please see the attach image below, I want to the make this view in siwftUI that have zero opacity inside.
struct TestView: View {
var body: some View {
ZStack{
// any dummy image
Image("bigpancake")
.resizable()
ZStack {
// Make this view opcity zero so that I can see backgourd clearly
Rectangle()
.frame(width: 200, height: 100)
.foregroundColor(.black.opacity(0))
Rectangle()
.foregroundColor(.black.opacity(0.3))
}
}
}
}

If I understand correctly what you are looking for, it sounds like an "inverted mask". You can achieve what you want using compositingGroup()
Example:
struct ContentView: View {
var body: some View {
ZStack {
Image("background")
.resizable()
.aspectRatio(contentMode: .fill)
.ignoresSafeArea()
ZStack {
Rectangle()
.foregroundColor(.black.opacity(0.3))
.ignoresSafeArea()
Rectangle()
.cornerRadius(20)
.frame(width: 200, height: 200)
.blendMode(.destinationOut)
.overlay {
Text("Content")
}
}.compositingGroup()
}
}
}

Related

SwiftUI show collection of images

I would like to show a grid of images similar to UICollectionView like this:
With each color representing an image.
When I do the following:
struct ContentView: View {
var body: some View {
ScrollView{
ForEach(0..<8) { i in
HStack {
ForEach(0..<3) { j in
ZStack(alignment: .center) {
Image("image")
.background(Color.random)
.clipped()
.aspectRatio(contentMode: .fill)
}
.frame(width: 120, height: 120)
.background(Color.random)
}
}
}
}
}
}
I get one image which is not bound by its frame and therefore fills the whole screen.
Set a frame and resizable modifier to you image.
Image("image")
.resizable()
.frame(width: 120, height: 120)
Full example
struct ContentView: View {
var body: some View {
ScrollView{
ForEach(0..<8) { i in
HStack {
ForEach(0..<3) { j in
ZStack(alignment: .center) {
Image("image")
.resizable()
.frame(width: 120, height: 120)
}
.frame(width: 120, height: 120)
.background(Color.blue)
}
}
}
}
}
}
Produces this

Gab being caused by unknown element in swift design

Ok I have tried previous suggestions of just placing it in another vstack but still my view is showing the rectangle at the mid of the screen is their any reason why, also the edges have no padding around them making it edge to edge which I don't want?
struct ProfileView : View
{
var body: some View {
GeometryReader{ geo in
VStack {
VStack(alignment: .trailing, spacing: 10) {
RoundedRectangle(cornerRadius: 20)
.stroke(Color.primary, lineWidth: 2)
.frame(width: geo.size.width, height: 200)
.padding(.horizontal)
}.frame(width: geo.size.width, height: geo.size.height) // <<=== Here }
}
}
}
My Views are being injected into the content area via this page
struct ContentView: View {
var body: some View {
GeometryReader { geometry in
TabView{
HomeView().tabItem {
Image(systemName: "house")
Text("Home")
}
ProfileView()
.tabItem {
Image(systemName: "person.circle.fill")
Text("Profile")
}
ZStack {
StatsView()
.tabItem {
Image(systemName: "murry").renderingMode(.original).padding()
Text("Plus")
}
}
StatsView()
.tabItem {
Image(systemName: "dumbbell.fill").renderingMode(.original).padding()
Text("Stats")
}
StatsView()
.tabItem {
Image(systemName: "dumbbell.fill").renderingMode(.original).padding()
Text("Notes")
}
}
}.safeAreaInset(edge: .bottom, alignment: .center, spacing: 0) {
Color.clear
.frame(height: 20)
.background(Material.bar)
}
}}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
.previewInterfaceOrientation(.landscapeLeft)
}
}
On Simlualtor and real device its placing it in the middle of the screen.
I want this frame so that I can place other elements in side it is a rounded rectangle the best way to go for this?
You are using GeometryReader as the outer most view in the ProfileView, and GeometryReader has the behavior to take as much space as there is available, if you want your rectangle to show in the top or bottom of the screen consider using a Spacer() and if you want to add padding to your rectangle so it does not go to the edges of the screen try removing the .frame(width: geo.size.width) because you are forcing the rectangle to be the width of the screen, in nature the rectangle will take as much space as it can so you do not have to specify that.
This is your code but with some tweaks:
struct ProfileView : View {
var body: some View {
VStack {
RoundedRectangle(cornerRadius: 20)
.stroke(Color.primary, lineWidth: 2)
.frame(height: 200)
.padding(.horizontal)
Spacer()
}
}
}

Unexpected layout issues with SwiftUI Image and ZStack

I'm trying to create a view composed of two parts - the top part is an image with a piece of text overlaid in the top left corner. The top part should take up 2/3 of the height of the view. The bottom part is text information and a button, contained in an HStack, and takes up the remaining 1/3 of the view height.
struct MainView: View {
var body: some View {
GeometryReader { gr in
VStack(spacing: 0) {
ImageInfoView()
.frame(height: gr.size.height * 0.66)
BottomInfoView()
}
.clipShape(RoundedRectangle(cornerRadius: 20))
}
}
}
struct ImageInfoView: View {
var body: some View {
ZStack(alignment: .topLeading) {
Image("testImage")
.resizable()
.aspectRatio(contentMode: .fill)
.overlay(Rectangle()
.fill(Color.black.opacity(0.5))
)
HStack {
Text("Top left text")
.foregroundColor(.white)
.padding()
}
}
}
}
struct BottomInfoView: View {
var body: some View {
HStack {
VStack(alignment:.leading) {
Text("Some title")
Text("Some subtitle")
}
Spacer()
Button("BUTTON") {
}
}
.padding()
.background(.gray)
}
}
In the below sample code, if I set the frame height to 400 I will see the top left text, but when I set it to 200, I do not. What is happening here? The text should be anchored to the top left corner of ImageInfoView no matter what. Further, when set to 400, why does the ImageInfoView take up more than 66% of the height?
struct TestView: View {
var body: some View {
MainView()
.frame(height: 200)
.padding([.leading, .trailing], 16)
}
}
An image's fill pushes ZStack boundaries, so Text goes off screen (see this for details).
A possible solution is to put image into overlay of other container so it respects provided space instead of imposing own.
Tested with Xcode 13.4 / iOS 15.5
ZStack(alignment: .topLeading) {
Color.clear.overlay( // << here !!
Image("testImage")
.resizable()
.aspectRatio(contentMode: .fill)
.overlay(Rectangle()
.fill(Color.black.opacity(0.5))
)
)
// ... other code as-is
This fixes the problem:
ZStack(alignment: .topLeading) {
GeometryReader { gr in
Image("testImage")
.resizable()
.aspectRatio(contentMode: .fill)
.frame(maxWidth: gr.size.width, maxHeight: gr.size.height)
.overlay(Rectangle()
.fill(Color.black.opacity(0.5))
)
HStack {
Text("Top left text")
.foregroundColor(.white)
.padding()
}
}
}
}

SwiftUI Image in ZStack not aligning to bottom of screen

I have this code
struct ContentView: View {
var body: some View {
ZStack(alignment:.bottom) {
Image("login-devices-mobile")
.resizable()
.scaledToFit()
}.padding(0.0).background(Image("login-background").aspectRatio(contentMode: ContentMode.fill))
}
}
which I am trying to display an image on the bottom of the screen. However when I run the preview. It still shows in the middle.
Any tips on anything I can do differently to align the image on the bottom of the screen?
I assume you wanted this
ZStack(alignment:.bottom) {
Image("login-devices-mobile")
.resizable()
.scaledToFit()
}
.frame(maxWidth: .infinity, maxHeight: .infinity, alignment: .bottom) // << here !!
.background(Image("login-background").aspectRatio(contentMode: ContentMode.fill))
You can do something as -
struct ContentView: View {
var body: some View {
ZStack() {
Spacer() // Add these....
Image("login-devices-mobile")
.resizable()
.scaledToFit()
}.padding(0.0).background(Image("login-background").aspectRatio(contentMode: ContentMode.fill))
}
}
Hope it helped.
Wrapping the image in a VStack should do the trick:
struct ContentView: View {
var body: some View {
ZStack() {
VStack {
Spacer()
Image("login-devices-mobile")
.resizable()
.scaledToFit()
}
}.padding(0.0).background(Image("login-background").aspectRatio(contentMode: ContentMode.fill))
}
}

How to resize a background Image in SwiftUI without affecting the screen views?

I have a Content View which looks like this:
The code for the Content View is:
var body: some View {
ZStack(alignment: .bottom) {
VStack {
if selectedTab == "gearshape" {
GearshapeView()
}
}
CustomTabBar(selectedTab: $selectedTab)
}
}
and this is the code of the GearshapeView:
var body: some View {
Color.blue
.edgesIgnoringSafeArea(.all)
}
Now I want to add a picture in the background and keep the size of the menu same like before.
var body: some View {
Image("s7")
.resizable()
.aspectRatio(contentMode: .fill)
.ignoresSafeArea()
}
Unfortunately when I resize the picture to fit the screen, the menu also resizes.
Any ideas on how to keep it static and not stretched?
Solved it by using Geometry reader:
GeometryReader { geo in
Image("s7")
.resizable()
.aspectRatio(contentMode: .fill)
.frame(width: geo.size.width, height: geo.size.height)
}
.edgesIgnoringSafeArea(.all)