Position view bottom without using a spacer

前端 未结 3 1065
长发绾君心
长发绾君心 2020-12-19 19:40

How can I position a View at the bottom without using a spacer. I know I can achieve it placing a spacer and my view in inside a VStack but I don\'t want to use a spacer bec

相关标签:
3条回答
  • 2020-12-19 20:08

    I think the simplest way is to add a frame for the container view.

    Group{ // container View
        Text("iner label")
    }.frame(maxHeight: .infinity, alignment: .bottom)
    

    If you don't add frame, the default frame will wrap the inner view and has the same size as the inner View. If you add a frame, it will create a space belonging to the outer view, in the UIView concept, it's a superView. Then you will see what you will need to handle.

    0 讨论(0)
  • 2020-12-19 20:15

    Position property will help you try this way

    Group{ // container View
         Text("iner label")
    }.position(x: UIScreen.main.bounds.width/2, y: UIScreen.main.bounds.height-50)
    
    0 讨论(0)
  • 2020-12-19 20:18

    Experimenting with different approaches I finally end up with creating own custom container, which, having some known limitation, fulfils my needs completely. Hope it would be helpful for someone else.

    Demo:

    PinnedView Demo1

    Pros: ContentView & PinnedView are absolutely independent in layout on each other, automatically handle device orientation, and actually limitless in internal content

    Cons: Due to used GeometryReader using .infinity at top-level content or pinned view result in crash due to "chicken-egg" problem.

    Container code:

    struct ContainerWithPinnedBottomView<Content, Pinned>: View 
                                         where Content: View, Pinned: View {
    
        private var content: () -> Content
        private var bottomView: () -> Pinned
    
        @inlinable public init(@ViewBuilder pinnedView: @escaping () -> Pinned,
                                @ViewBuilder content: @escaping () -> Content) {
            self.content = content
            self.bottomView = pinnedView
        }
    
        var body: some View {
            ZStack(alignment: .bottom) {
                Rectangle().fill(Color.clear) // !! Extends ZStack to full screen
                GeometryReader { _ in
                    ZStack {
                        self.content()
                    }
                }
                self.bottomView()
                    .alignmentGuide(.bottom) { $0[.bottom] }
            }
        }
    
    }
    

    Usage example (of demo screenshot)

    struct TestBottomView: View {
        var body: some View {
            ContainerWithPinnedBottomView(pinnedView: {
                HStack {
                    Spacer()
                    Text("Always Pinned to Bottom")
                        .padding()
        //                .frame(width: .infinity) // !! LIMITATION - don't use, cycling crash
                    Spacer()
                }
                .background(Color.blue)
            }) {
                NavigationView {
                    List (0 ..< 100, id: \.self) { i in
                        NavigationLink(destination: Text("Other")) {
                            Text("Row \(i)")
                        }
                    }
                    .navigationBarTitle("TitleBar")
                }
            }
        }
    }
    
    struct TestBottomView_Previews: PreviewProvider {
        static var previews: some View {
            TestBottomView()
        }
    }
    
    0 讨论(0)
提交回复
热议问题