如何使用 SwiftUI 制作具有绝对位置的底栏

Posted

技术标签:

【中文标题】如何使用 SwiftUI 制作具有绝对位置的底栏【英文标题】:how to make a bottom bar which has absolute position with SwiftUI 【发布时间】:2020-07-14 05:44:21 【问题描述】:

您好,我是 SwiftUI 新手,遇到了问题。

我想制作一个底栏(可重用模块)以在多个视图中使用。

但由于其兄弟视图,它在每个视图中的位置都不同

这些是我尝试过的:

    几何阅读器 但是每个 View 的几何形状都不同。 叠加和位置(x:y:) 这也不起作用 ZStack

我的问题是

    如何制作固定位置视图? (如位置:css 中的绝对值) 此问题的正常解决方案是什么? 是否有任何对 SwiftUI 有用的参考资料?

我想将此模块用作底部按钮栏

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)
    

在这个视图中,它有效

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()
            
        
    

但在这个复杂的视图中,它不起作用

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()
            
        
    

【问题讨论】:

你会添加你的代码吗? @Asperi 我添加了我的示例代码和图像 【参考方案1】:

这不是问题的答案

如何制作固定位置视图? (类似位置css中的绝对值

但你可以先使用这样的东西:

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

这将为您提供一个显示在屏幕底部的按钮。如果您希望视图显示在屏幕顶部,只需将其放在 Spacer 之前,如下所示:

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

最后,如果 View 在垂直方向上太大,只需将其放在 ScrollView 中(但不要将按钮放在其中)。这样就可以实现按钮始终显示在底部和前面,并且视图可以在其后面滚动的效果。

如果您复制并粘贴我的简单示例的以下最终代码,您将看到这种效果,并很快了解它的工作原理以及如何将其应用到您的场景中:

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")
    

【讨论】:

谢谢!!!!!!我解决了我的问题并了解了它是如何工作的 +plus) .edgesIgnoringSafeArea(.vertical) 这也是我的解决方案【参考方案2】:

你需要明确的视图容器来管理底栏,比如

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
        
    

因此独立于使用的内容底部栏将始终位于底部。

因此,我们可以从 NewView 中删除 BaseBottomButton() 并以与使用其他 SwiftUI 容器相同的方式使用它:

BottomBarContainer 
   NewView()

【讨论】:

以上是关于如何使用 SwiftUI 制作具有绝对位置的底栏的主要内容,如果未能解决你的问题,请参考以下文章

如何使列表内容通过带有材质背景的底栏显示

修复 CoordinatorLayout 中的底栏

基于导航控制器的视图的底栏是啥?

CSS3--Flex弹性盒子布局: 实例篇-固定的底栏 & 流式布局

ios xcode底栏始终是tab项

如何在BottomBar布局android中添加中间按钮