SpacePOD icon indicating copy to clipboard operation
SpacePOD copied to clipboard

ZoomableScrollView adds padding around image when .edgesIgnoringSafeArea(.all) set

Open robinst opened this issue 2 years ago • 1 comments

Hey, I raised the earlier issue (#1) and just wanted to let you know of a problem I found:

When ZoomableScrollView is used within a container that has .edgesIgnoringSafeArea(.all) set, the image has some padding on top and bottom added, see the white bars on top and bottom:

Screen Shot 2021-09-14 at 14 37 13

They are also there when zooming in and what it means is that if you scroll all the way to the top/bottom of an image, there's still padding there.

I've done quite a bit of experimentation and searching and ultimately landed on this being a problem with UIHostingController and sizeThatFits, see this blog post and linked tweets (and FB8176223): https://noahgilmore.com/blog/swiftui-self-sizing-cells/

There is a hack to potentially fix it: https://twitter.com/b3ll/status/1193747288302075906

But IMO it's too much. I'm currently looking at either adapting the view so that it only handles images (because it's easy to get the correct size of an image, and no need to use UIHostingController), or keep the current Content but also allowing to specify the exact content size.

(Another thing I want to do is double tap to zoom to the tapped position (not just center), but that turns out to be hard with the current centerContent way of doing things because it offsets the position.)

robinst avatar Sep 14 '21 05:09 robinst

I'm trying to replicate the problem you described but haven't been able to. I tried this:

struct ZoomableScrollView_Previews: PreviewProvider {
  struct SafeAreaExample: View {
    @State var ignoreSafeArea = true
    var body: some View {
      ZStack(alignment: .top) {
        Rectangle().foregroundColor(.blue)
        Toggle("Ignore safe area", isOn: $ignoreSafeArea).padding(50)
        ZoomableScrollView {
          Rectangle()
            .fill(
              LinearGradient(
                gradient: Gradient(
                  colors: [
                    Color(white: 0.5),
                    Color(white: 0.8),
                  ]),
                startPoint: .topLeading,
                endPoint: .bottomTrailing)
            )
            .frame(width: 300, height: 200)
            .border(Color.orange, width: 2)
        }
      }
      .edgesIgnoringSafeArea(ignoreSafeArea ? .all : [])
    }
  }

  static var previews: some View {
    SafeAreaExample().previewDevice("iPhone 12 mini")
  }
}

What I see in the Xcode preview (with .edgesIgnoringSafeArea(.all)) is an initial rendering glitch, but as soon as I zoom, it seems to look fine:

https://user-images.githubusercontent.com/14237/133916187-18b59fd5-860d-4396-b737-cd5bec7a256d.mov

Can you modify my example above so it reproduces the problem?

Or maybe the problem you describe is demonstrated by how the zoomed-in image doesn’t exactly align with the top and bottom of the screen when I scroll (although I don’t get the white bars like in your screenshot)?

jtbandes avatar Sep 19 '21 05:09 jtbandes

Hey. Thanks for the response and sorry for coming back to this late, but I've since implemented my own view that satisfies all my requirements, such as double tap to zoom into the tapped area and other things.

robinst avatar Oct 20 '22 05:10 robinst

Cool! Do you have a link? I'd be curious to take a look. Zooming into the tapped area would be a good improvement to this version.

jtbandes avatar Oct 20 '22 18:10 jtbandes