简体   繁体   中英

SwiftUI erroneous vertical alignment of overlay when using GeometryReader

I have an overlay view that I want to appear hugging the top edge of its parent view (aligned vertically to top not center, see snapshot B) and have the ability to semi-hide it when tapped (move it up so that it doesn't obscure its parent view, and yet have a portion of it visible, say 64 pixels so that it can still be tapped back into original position, see snapshot C). Problem is that when I use the GeometryReader to get the height of the overlay view I'm trying to move, the overlay appears in the center of the view originally (see snapshot A). And if I don't use the geometry reader I don't know by how much to offset the overlay view:

    @State var moveOverlay = false

    var body : some View {

        VStack {
            ForEach(0...18, id: \.self) { _ in
                Text("This is the background... This is the background... This is the background... This is the background... ")
            }
        }
        .overlay(VStack {
            GeometryReader { proxy in
                Text("This is the overlay text snippet sentence that is multiline...\nThis is the overlay text snippet sentence that is multiline...\nThis is the overlay text snippet sentence that is multiline...\nThis is the overlay text snippet sentence that is multiline...\nThis is the overlay text snippet sentence that is multiline...\nThis is the overlay text snippet sentence that is multiline...\n")
                    .lineLimit(9)
                    .background(Color.gray)
                    .padding(32)
                    .frame(maxWidth: nil)
                    .offset(x: 0, y: self.moveOverlay ? -proxy.size.height + 128 + 64 : 0)
                    .onTapGesture {
                        self.moveOverlay = !self.moveOverlay
                }
            }
            Spacer()
        })
    }

Not sure why geometry reader has this effect on the layout.

(A) This is the way it appears with geometry reader code:

在此处输入图像描述

(B) If I remove the geometry reader code I get the desired effect:

在此处输入图像描述

(C) And this is the way I want the overlay when moved to the top:

在此处输入图像描述

EDIT: The code displayed above produces the layout (A). I want layout (B) which I get if I omit the geometry reader code.

Well... still not sure but here is some approach

Tested with Xcode 11.4 / iOS 13.4

演示

.overlay(
    ZStack(alignment: .top) {
        Color.clear
        Text("This is the overlay text snippet sentence that is multiline...\nThis is the overlay text snippet sentence that is multiline...\nThis is the overlay text snippet sentence that is multiline...\nThis is the overlay text snippet sentence that is multiline...\nThis is the overlay text snippet sentence that is multiline...\nThis is the overlay text snippet sentence that is multiline...\n")
                .lineLimit(9)
                .background(Color.gray)
                .alignmentGuide(.top) { self.hideOverlay ? $0.height * 3/2 : $0[.top] - 64 }
                .onTapGesture {
                    withAnimation(Animation.spring()) {
                        self.hideOverlay.toggle()
                    }
            }
    })

You can use the second argument in func overlay<Overlay>(_ overlay: Overlay, alignment: Alignment =.center) to achieve it by aligning it at the top end and moving it up or down with offset depending on the mode.

struct AlignmentView: View {
    @State var hideOverlay = false

    var body : some View {
        GeometryReader{ proxy in
            VStack {
                ForEach(0...18, id: \.self) { _ in
                    Text("This is the background... This is the background... This is the background... This is the background... ")
                }
            }
            .overlay(
                Text("This is the overlay text snippet sentence that is multiline...\nThis is the overlay text snippet sentence that is multiline...\nThis is the overlay text snippet sentence that is multiline...\nThis is the overlay text snippet sentence that is multiline...\nThis is the overlay text snippet sentence that is multiline...\nThis is the overlay text snippet sentence that is multiline...\n")
                        .lineLimit(9)
                        .background(Color.gray)
                        .frame(maxWidth: nil)
                        .offset(x: 0, y: self.hideOverlay ? -proxy.size.height / 5.0 : 50)
                        .onTapGesture {
                            withAnimation {
                                self.hideOverlay.toggle()
                            }
            },
                alignment: .top)
            }
    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM