简体   繁体   English

如何制作具有绝对 position 和 SwiftUI 的底栏

[英]how to make a bottom bar which has absolute position with SwiftUI

Hi I'm novice in SwiftUI and have a problem.嗨,我是 SwiftUI 的新手,遇到了问题。

I want to make a bottom bar (reusable module) to use in multiple Views.我想制作一个底栏(可重用模块)以在多个视图中使用。

But its position is different in every single views because of its sibling views但是它的 position 在每个视图中都不同,因为它的兄弟视图

These are what I tried:这些是我尝试过的:

  1. GeometryReader But Each View's geometry is different. GeometryReader 但是每个 View 的几何图形都是不同的。
  2. overlay & position(x:y:) This also doesn't work覆盖 & 位置(x:y:) 这也不起作用
  3. ZStack ZStack

My questions are我的问题是

  1. How can I make fixed position View?如何制作固定的 position 视图? (like position: absolute in css) (如 position:css 中的绝对值)
  2. What is the normal solution for this problem?这个问题的正常解决方案是什么?
  3. Is there any helpful references for SwiftUI? SwiftUI 是否有任何有用的参考资料?

I want use this Module as Bottom Button Bar我想将此模块用作底部按钮栏

struct BaseBottomButton: View {
    let screen = UIScreen.main.bounds
    
    var body: some View {
        Button(action: {
            print("hello")
        }) {
            Text("Hello")
        }
        .frame(width: self.screen.width ,height: 40)
        .background(Color.red)
    }
}

In this view, it works在这个视图中,它有效

struct ContentView: View {
    var body: some View {
        GeometryReader { proxy in
            VStack {
                VStack {
                    Text("What")
                        .frame(width: 400, height: 50)
                        .background(Color.green)
                }
                
                Spacer()
                
                Group {
                    VStack {
                        Text("Some Text")
                        Text("")
                        .frame(width: 200, height: 200)
                            .background(Color.yellow)
                    }
                }
                
                Spacer()
                
                BaseBottomButton()
            }
        }
    }
}

But in this complex view, it doesn't work但是在这个复杂的视图中,它不起作用

struct NewView: View {
    var body: some View {
        GeometryReader { geometry in
            ScrollView(showsIndicators: false) {
                VStack(spacing: 0) {
                    Text("hello")
                        .frame(width: 200, height: 200)
                        .background(Color.blue)
                    ZStack(alignment: .leading) {
                        VStack {
                            Spacer()
                                .frame(height: 24)
                            
                        }
                        .padding(.leading, 20)
                        .padding(.bottom, 138)
                        
                        Text("some box")
                        .frame(width: 200, height: 100)
                        .background(Color.yellow)
                        
                    }
                    .frame(minWidth: 0, maxWidth: .infinity)
                    .background(Color.gray)
                    
                    Spacer(minLength: 40)
                }
                
                BaseBottomButton()
            }
        }
    }
}

This is not answer to the question这不是问题的答案

How can I make fixed position View?如何制作固定的 position 视图? (like position : absolute in css ) (如 position : css中的绝对值

but you can first use something like this:但你可以先使用这样的东西:

VStack(spacing: 0) {
     Spacer()
     Button(action: {
         print("button clicked")
     }) {
         Text("MY BUTTON")
     }
}

This will give you a button appearing at the bottom of the screen.这将为您提供一个出现在屏幕底部的按钮。 If you want a view to appear on the top side the screen simply place it before the Spacer like this:如果您希望视图显示在屏幕的顶部,只需将其放在 Spacer 之前,如下所示:

VStack(spacing: 0) {
     SomeView()
     Spacer()
     Button(action: {
         print("button clicked")
     }) {
         Text("MY BUTTON")
     }
}

and finally if the View is too large vertically simply place it in a ScrollView (but do not place the button inside it).最后,如果 View 在垂直方向上太大,只需将其放在 ScrollView 中(但不要将按钮放在其中)。 Thus you will achieve an effect in which the button is always displayed at the bottom and in the front and the view is scrollable behind it.因此,您将获得一种效果,其中按钮始终显示在底部和前面,并且视图可在其后面滚动。

If you copy and paste the following final code of my simple example you will see this effect and will quickly understand how it works and how to apply it to your scenario:如果您复制并粘贴我的简单示例的以下最终代码,您将看到这种效果,并很快了解它的工作原理以及如何将其应用到您的场景中:

VStack(spacing: 0) {
    ScrollView(.vertical, showsIndicators: false) {
       Text("some text").font(.system(size: 60)).padding()
       Text("some text").font(.system(size: 60)).padding()
       Text("some text").font(.system(size: 60)).padding()
       Text("some text").font(.system(size: 60)).padding()
       Text("some text").font(.system(size: 60)).padding()
       Text("some text").font(.system(size: 60)).padding()
       Text("some text").font(.system(size: 60)).padding()
       Text("some text").font(.system(size: 60)).padding()
       Text("some text").font(.system(size: 60)).padding()
    }
    Spacer()
    Button(action: {
       print("button clicked")
    }) {
       Text("MY BUTTON")
    }
}

You need explicit view container to manage bottom bar, like您需要明确的视图容器来管理底栏,例如

struct BottomBarContainer<Content: View>: View {
    let content: () -> Content

    init(@ViewBuilder _ content: @escaping () -> Content) {
        self.content = content
    }

    var body: some View {
        VStack {
            content()
            Spacer() // << always pushes below bar to bottom
            BaseBottomButton() // or any bar container here
        }
    }
}

so independently of used content bottom bar would be always at bottom.因此独立于使用的内容底部栏将始终位于底部。

As a result we can remove BaseBottomButton() from NewView and use it instead in the same way as other SwiftUI container used:因此,我们可以从NewView中删除BaseBottomButton()并以与使用的其他 SwiftUI 容器相同的方式使用它:

BottomBarContainer {
   NewView()
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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