简体   繁体   English

如何删除 SwiftUI 中“表单”的顶部空间?

[英]How to remove top space of `Form` in SwiftUI?

How do I top align a Form within a NavigationView .如何在NavigationView中顶部对齐Form I have the below, when I remove NaviagationView from the body, the Form is top aligned.我有以下内容,当我从正文中删除NaviagationView时, Form是顶部对齐的。 With NavigationView in place, I get spacing in between(red box added to show space).使用NavigationView后,我在两者之间获得了间距(添加了红色框以显示空间)。 I can use .padding(.top, -20) on the Form but while this works it skews things slightly.我可以在 Form 上使用.padding(.top, -20) ,但是虽然这可行,但它会稍微倾斜一些东西。

截屏

NavigationView {
    Form {
        VStack {
            HStack {
                Text("Name:").underline().font(.headline)
                TextField("Name", text: $routine.name)
                
            }
            roundPicker()
            TimeSelectionView(stateName: "A", stateDuration: "0:30", stateBackground: "#df405a")
            TimeSelectionView(stateName: "B", stateDuration: "1:30", stateBackground: "#4ea1d3")
            TimeSelectionView(stateName: "C", stateDuration: "3:00", stateBackground: "#4f953b")
        }
    }
    .navigationBarTitle("Create", displayMode: .inline)
    .navigationBarItems(trailing:
        Button(action: {
            //Save Routine
            self.routine.rounds = self.roundsArray[self.rounds]
            
            print("Workout Name: \(self.routine.name)")
            print("Workout Rounds: \(self.routine.rounds)")
            }, label: {
                Text("Save")
            }
        )
    )
} 

SwiftUI Form is actually a grouped style UITableView under the hood and that is default tableHeaderView . SwiftUI Form实际上是一个分组样式UITableView在引擎盖下,这是默认的tableHeaderView So you can remove it like this:所以你可以像这样删除它:

iOS 13 iOS 13

struct ContentView: View {
    
    init() { // this can be done in `onAppear` modifier if you need to restore the appereance later on `onDisappear`
        UITableView.appearance().tableHeaderView = UIView(frame: CGRect(x: 0, y: 0, width: 0, height: Double.leastNonzeroMagnitude))
    }
    
    var body: some View {
        ,,,
    }
}

iOS 14 iOS 14

Apple is limiting the appearance hack and setting the tableHeaderView 's frame is one of them so we need to dig more around by adding these steps: Apple 正在限制appearance黑客,设置tableHeaderView的框架就是其中之一,因此我们需要通过添加以下步骤来挖掘更多内容:

1. Use constraint instead of frame : 1.使用约束代替frame

init() {
    let view = UIView()
    view.translatesAutoresizingMaskIntoConstraints = false
    view.heightAnchor.constraint(equalToConstant: 0).isActive = true
    UITableView.appearance().tableHeaderView = view
}

2. Force reload the table: 2.强制重新加载表:

The constraint is added but it needs a reload.添加了约束,但需要重新加载。 SwiftUI does not allow you to reload a list manually. SwiftUI 不允许您手动重新加载列表。 So we need to add a dummy view and a dummy state to trick it:所以我们需要添加一个虚拟视图和一个虚拟state来欺骗它:

@State var loaded = false // need for stay update
,,,

    List {

        if loaded {
            Text("Actual content of the list")

        } else {
            Text("Dummy content. Not important")
                .onAppear {
                    loaded = true // need for instatnt force update 
                }
        }

    }

Note1:注1:

Try never hard-code any numbers (like -35 for inset.).尝试永远不要对任何数字进行硬编码(例如插入 -35。)。 Numbers vary on different devices and platforms and states and etc.数字在不同的设备、平台和状态等方面有所不同。

Note2:笔记2:

.zero frame is not working. .zero帧不工作。 You should pass at least a minimum height if you use frame for iOS 13 or UIKit .如果您使用 iOS 13 或UIKitframe ,您应该至少通过一个最小高度。

Note3:注3:

All methods are hacks and Apple is trying to restrict access to underlying types like UITableView .所有方法都是黑客攻击,Apple 正试图限制对基础类型的访问,例如UITableView So stay up to date and try to help the community.因此,请保持最新状态并尝试帮助社区。

Note4:注4:

Contribute to the community by upvoting and commenting.通过点赞和评论为社区做出贡献。 So people will be more motivated to dig in unknown places and bring us cool stuff.所以人们会更有动力去未知的地方挖掘,给我们带来很酷的东西。

Note5:注5:

Since we are using the Appearance proxy, any change will be applied to all TableView s in the app.由于我们使用的是 Appearance 代理,因此任何更改都将应用于应用程序中的所有TableView You can store the state of the original Appearance -> apply the new style onAppear and restore the original onDisaper if needed.您可以存储原始Appearance的 state -> 应用新样式onAppear并在需要时恢复原始onDisaper

Setting the table header view is no longer working for me in Xcode 12. Instead, setting a negative top content inset seems to achieve the same thing.在 Xcode 12 中设置表 header 视图不再对我有用。相反,设置负顶部内容插图似乎可以达到同样的效果。

UITableView.appearance().contentInset.top = -35

if you use Introspect add this to your NavigationView如果您使用Introspect ,请将其添加到 NavigationView

.introspectTableView {
    $0.tableHeaderView = UIView(frame: CGRect(x: 0, y: 0, width: 0, height: Double.leastNonzeroMagnitude))
}

This works as well:这也有效:

Form {
   // ...
}._safeAreaInsets(EdgeInsets(top: -18, leading: 0, bottom: 0, trailing: 0))

It also works for List .它也适用于List But sometimes it can affect a large navigation bar title where it appears inline as if you scrolled.但有时它会影响一个大的导航栏标题,它看起来像滚动一样内联。

Cleaner add a navbartitle to form section and then set hidden Cleaner 将导航栏标题添加到表单部分,然后设置隐藏

Form {
// add end of form section
}.navigationBarHidden(true).navigationBarTitle("Title") // Form

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

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