How To Ignore Insets In SwiftUI Form - swiftui

I'm trying to ignore the automatic insets on a SwiftUI form in order to have an image fill the entire width of the screen. I've managed to do so by creating a fake section and adding negative padding, but this seems like a hack. Does anyone have a better suggestion?
struct ContentView: View {
var body: some View {
NavigationView{
Form{
Section(header:
Image("stockPhoto1")
.resizable()
.frame(height: 200)
.padding(.horizontal, -20)
.listRowInsets(.init())
){}
ForEach(0..<5){ section in
Section(header: Text("Section \(section)")){
ForEach(1..<Int.random(in: 3...8)){ row in
Text("Row \(row)")
}
}
}
}
.navigationBarTitleDisplayMode(.inline)
.navigationTitle("Form")
}
}
}

Related

Prevent SwiftUI Divider expanding horizontally

I have the following setup:
struct ContentView: View {
var body: some View {
VStack {
Text("Title").font(.title)
HStack {
Text("Hello:").bold()
Text("World")
}
}
.padding()
.background {
RoundedRectangle(cornerRadius: 8).stroke(.black)
}
}
}
which renders as follows:
When I add a Divider() into the VStack…
struct ContentView: View {
var body: some View {
VStack {
Text("Title").font(.title)
Divider() // Added this
HStack {
Text("Hello:").bold()
Text("World")
}
}
.padding()
.background {
RoundedRectangle(cornerRadius: 8).stroke(.black)
}
.padding()
}
}
… it forces the VStack to expand horizontally as large as possible.
How do I make the Divider fit to the other VStack content?
Having written the question, I tried some more things, and found a solution. Leaving here in case it is useful for others.
I just needed to add
.fixedSize(horizontal: true, vertical: false)
to the VStack, which makes all the subviews have the same horizontal size, resulting in…

NavigationView adding top padding

I have a very simple view, a background color and some text. But when I wrap it in a NavigationView I'm getting unwanted spacing at the top of the view. How can I eliminate this? (I want the Navigation as I will be adding NavigationLinks)
e.g.
var body: some View {
NavigationView {
ZStack(alignment: .leading) {
Rectangle()
.fill(
LinearGradient(
gradient: Gradient(colors: [.indigo, .purple]),
startPoint: .bottom,
endPoint: .top
)
)
.ignoresSafeArea()
VStack {
Text("Test")
Spacer()
}
}
}
}
You can fix this by using .navigationBarHidden(true).
However, .navigationBarHidden(true) will be deprecated in the new version of iOS, so you can use .toolbar(.hidden) instead.
The space is reserved for the title, so if you set the navigation bar title display mode to .inline, then it should reduce that space.
NavigationView {
ZStack {
/* ... */
}
.navigationBarTitleDisplayMode(.inline)
}

Why do the views extend wider than the screen?

Edit: Substitute your "system name:" of choice. "pencil.circle" works fine. "edit" is not a valid SF Symbol.
(I've simplified my code so you can cut and paste. That's why you see .frame, resizable, etc. where much simpler code might your first instinct.)
I have created a view which is a vertical list of row items (table view).
Each row item has a horizontal view with two images inside it.
The images take up too much space and do not fit correctly on the screen:
import SwiftUI
#main
struct StackOverflowDemoApp: App {
var body: some Scene {
WindowGroup {
TandemView()
}
}
}
struct PaddedImageView: View {
let color: Color = .red
var body: some View {
ZStack {
color
Image(systemName: "edit")
.resizable()
.padding()
}
Spacer()
}
}
struct TandemView: View {
var body: some View {
HStack {
Spacer()
Image(systemName: "pencil")
.resizable()
.background(Color.orange)
.frame(height: 80)
.aspectRatio(1, contentMode: .fill)
PaddedImageView()
.frame(width: 200, height: 80)
}
.padding()
.fixedSize()
}
}
struct TandemView_Previews: PreviewProvider {
static var previews: some View {
TandemView()
}
}
The above is the closest I can get to the desired layout (it just needs to fit horizontally). I experimented with GeometryReader but that did not produce desired results.
Here are some things I tried:
The code as provided
NoConstraintsOnPencilOrHStack
NoConstraintsOnTandemView
NoConstraintsOnImageInPaddedViewButWithFrameConstraint
I am trying to get a row view which consists of two Images (my actual source consists of UIImage objects) that fits within the width of the screen.
Edit:
After Accepting cedricbahirwe's spot-on response, I was able to simplify the code further. New results:
I added at the top level
TandemView()
.padding(.horizontal)
I removed:
// Spacer()
at the end of PaddedImageView
updated TandemView -- changed both frames and removed 3 lines:
struct TandemView: View {
var body: some View {
HStack {
Spacer()
Image(systemName: "pencil")
.resizable()
.background(Color.orange)
.frame(width: 80, height: 80)
// .aspectRatio(1, contentMode: .fill)
PaddedImageView()
.frame(height: 80)
}
// .padding()
// .fixedSize()
}
}
This is happening because of the layout of PaddedImageView View, you can actually remove the Spacer since it is not needed there.
So change
struct PaddedImageView: View {
let color: Color = .red
var body: some View {
ZStack {
color
Image(systemName: "edit")
.resizable()
.padding()
}
Spacer()
}
}
to
struct PaddedImageView: View {
let color: Color = .red
var body: some View {
ZStack {
color
Image(systemName: "edit")
.resizable()
.padding()
}
}
}
Note:
SwiftUI Engine infers the layout of your view from the implementation of the body property. It's recommended to have one Parent View inside the body property.

Dismiss button (X) on an image - top right alignment HOW?

What is an effective & effecient way to get the Dismiss button (X) into the top right corner?
I'm struggling with container alignment... can't say I GROK it.
Needless to say ... this ain't it!
var body: some View {
ZStack {
Image("Biz-card_2020")
.resizable()
.edgesIgnoringSafeArea(.all)
HStack(alignment: .top) {
VStack() {
Spacer(minLength: 5) // vertical space
HStack() {
Spacer()
// close Welcome page (X) button
Button(action: {
//print(" - Button to dismiss page \(self.isPresented)")
self.isPresented = false // dismiss the Welcome view
//print(" - after action Button to dismiss Welcome page \(self.isPresented)")
}, label: {
Image(systemName: "xmark.circle" )
.scaledFont(name: "Georgia", size: Const.titleText)
.minimumScaleFactor(0.3)
.accentColor(.white)
.padding(10)
})
}
Spacer()
}
}
}
}
You need to remove Spacer(minLength: 5) and replace it with padding for HStack.
Spacer(minLength: 5) doesn't mean its length will be exactly 5 (only that the minimum length will be 5).
You may also want to extract close button to another function for clarity.
Try the following:
struct ContentView: View {
...
var body: some View {
ZStack {
Image("Biz-card_2020")
.resizable()
.edgesIgnoringSafeArea(.all)
closeButton
}
}
var closeButton: some View {
VStack {
HStack {
Spacer()
Button(action: {
...
}) {
Image(systemName: "xmark.circle")
.padding(10)
}
}
.padding(.top, 5)
Spacer()
}
}
}
ZStack can be configured using .topTrailing etc. You should use those alignments to configure your view. Using something like Spacer() is going to cause the rest of your views to get pushed down.
ZStack(alignment: .topTrailing) {
// your code here
}
If you need to move your code a bit more, use either padding, or offset modifiers.

How to make this simple view with swiftui?

I am trying to do this view with swiftui but i am stuck.
I want the text("Mes évènements") to be centered and I want it to take all the place it can.
The two horizontal line should only take the place left.
I tried with HStack but I couldn't make it work as i would like to.
Here is a possible solution.
struct ContentView: View {
var body: some View {
HStack{
VStack{
OrangeLine()
}
Text("Mes évènements")
.font(.subheadline)
.fontWeight(.bold)
.foregroundColor(Color.orange)
VStack{
OrangeLine()
}
}
}
}
struct OrangeLine: View {
var body: some View {
Rectangle()
.fill(Color.orange)
.frame(height: 2)
.edgesIgnoringSafeArea(.horizontal)
}
}