skip to Main Content

I’m trying to create a view that presents a full screen Image and a NavigationLink in the top right corner overlayed on top of the image. However, I’m running into an issue such that the full screen Image somehow pushes the NavigationLink outside of the viewable part of the screen when I align the NavigationLink to the .topTrailing position. Here is the buggy code and the corresponding preview:

ZStack {
   Image("yose").resizable()
        .aspectRatio(contentMode: .fill)
    NavigationLink(destination: OverviewView()) {
        OverviewButton()
    }.frame(maxWidth: .infinity, maxHeight: .infinity, alignment: .topTrailing).padding()
}

NavigationLink not shown on screen

When I comment out the full screen Image, the NavigationLink can be seen where I would like it to be. Also, if I align the NavigationLink to be .bottom or .top, it is within the viewable part of the screen as well. Code:

ZStack {
//   Image("yose").resizable()
//        .aspectRatio(contentMode: .fill)
    NavigationLink(destination: OverviewView()) {
        OverviewButton()
    }.frame(maxWidth: .infinity, maxHeight: .infinity, alignment: .topTrailing).padding()
}

Preview:

NavigationLink in the correct spot

How can I overlay the NavigationLink in the top right corner on top of the full screen image?

2

Answers


  1. I’m not sure what’s causing this, but using a GeometryReader instead of .infinity seems to fix the problem.

        GeometryReader { g in
            ZStack {
                Color(.red)
                    .aspectRatio(contentMode: .fill)
                    .frame(width: g.size.width, height: g.size.height)
                NavigationLink(destination: ContentView()) {
                    Text("HI")
                        .foregroundStyle(.black)
                }
                .frame(maxWidth: g.size.width, maxHeight: g.size.height, alignment: .topTrailing)
            }
        }
    

    enter image description here

    Login or Signup to reply.
  2. The size of a ZStack is determined by the size of its contents.

    Since you are scaling the image to fill, the full image is (probably) going to be larger than the screen (unless the aspect ratio of the image exactly matches the aspect ratio of the screen). This is the size being adopted by the ZStack.

    The .frame modifier being applied to the button is then making it occupy the same size as the image. So this is why it is going off-screen.

    I would suggest applying the Image as background to the ZStack instead:

    ZStack {
        NavigationLink(destination: OverviewView()) {
            OverviewButton()
        }
        .frame(maxWidth: .infinity, maxHeight: .infinity, alignment: .topTrailing)
        .padding()
    }
    .background {
        Image("yose")
            .resizable()
            .scaledToFill()
    }
    

    You could also consider applying the button as an overlay to the parent container. This would be another way of positioning it in the top-right corner and might mean that a ZStack would not be needed any more:

    ZStack { // or whatever container is suitable for the main content
    
        // main content
    
    }
    .frame(maxWidth: .infinity, maxHeight: .infinity)
    .overlay(alignment: .topTrailing) {
        NavigationLink(destination: OverviewView()) {
            OverviewButton()
        }
        .padding()
    }
    .background {
        Image("yose")
            .resizable()
            .scaledToFill()
    }
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search