How To Position Controls With SwiftUI

I am coming from C#, where Forms and Controls are placed similar to Swift Storyboards. I have been trying to learn Storyboards, but keep running across tutorials regarding SwiftUI, and Storyboard examples are few. So the question becomes, "how do I position controls on a Form using SwiftUI?" See the example below.

I have run across many videos that use either horizontal or vertical positioning of controls, but these examples are usually very simple, with items occupying only the center portion of the screen. I get stuck on examples that are more complicated.

The example below only shows the controls for the upper part of a Form, with some type of textbox (Viewform) below making up the rest of the Form.

How does one make more complicated placement of controls with SwiftUI?

Answered by Claude31 in 859327022

I personally find that placing precisely objects is a critical limit (or constraint) with SwiftUI.

What I do (sometimes with mixed results) is to group objects in separate Views (red-bordered in the image). It makes it easier to position objects (with HStack / VStack) in each view and then position the views.

Hope that helps.

Accepted Answer

I personally find that placing precisely objects is a critical limit (or constraint) with SwiftUI.

What I do (sometimes with mixed results) is to group objects in separate Views (red-bordered in the image). It makes it easier to position objects (with HStack / VStack) in each view and then position the views.

Hope that helps.

Hi Claude31,

Thanks for the response. You gave me some good suggestions on how to approach the issue using Views.

I guess another question that I would have is, if I use your View approach, how do I locate each one of those in exact locations on the screen? I have found videos about Views, but not how to locate them. Maybe they have to be adjacent to each other?

Based on your response, I did some more digging and found a video by Paul Hudson. Here Paul places some text at an absolute location on the screen as in the sample below. I wonder if it's possible to do this with other controls as well?

You can position the views with position modifier.

And if you want to position relative to screen width for instance, use screenSize

    @State var screenSize : CGSize = CGSize(width: 1200, height: 800) // Will be computed in .onAppear
.onAppear {
   screenSize = CGSize(width: UIScreen.main.bounds.width, height: UIScreen.main.bounds.height)

When you need to position, in the middle

.position(x: screenSize.width / 2, y: 50)

If you have to adapt to view resize:

        .readSize { newSize in
            screenSize = newSize
        }

Thanks Claude31, for the screenSize info. That will come in very handy.

From your red rectangles above, I am starting to understand that one needs to make use of Views, and more specifically, multiple Views, one for each of the red rectangles above.

The code below shows how to stack two Views. Notice MyCustomView is embedded inside the first View below. I have looked at many videos on how to stack more Views, but have not come across any examples. Is there any documentation of how to stack multiple Views.

import SwiftUI

struct ContentView: View {
    var body: some View {
        VStack {
            MyCustomView()
            Image(systemName: "star.fill")
                .font(.largeTitle)
                .foregroundColor(.yellow)
        }
    }
}

Please review the following resouces, they should be helpful in learning about SwiftUI layouts:

Thanks to the responses above, as I appreciate the feedback.

After more digging, I may have found more information about how SwiftUI works. It seems that View is an integral part of how Swift places controls on Forms. At the time I thought that the keyword View was used to differentiate between Controls on the Form, but this does seem to be the case as seen below.

I found an example in the book from Paul Hudson, Hacking With MacOS, Chapter 13. There, Paul has as example with a series of controls appearing on the right side of a Form, which project down the right side, top to bottom. The skeleton sample code that creates this display is shown below.

var body: some View
{
   HStack(spacing: 20)
   {
      RenderView(document: document)
         .draggable(snapshotToURL())
         .dropDestination(for: URL.self)
         { items, location in handleDrop(of: items)}
            VStack(spacing: 20)
            {
               VStack(alignment: .leading)
               {
                  // stuff here
               }
               VStack(alignment: .leading)
               {
                  // stuff here
               }
               .labelsHidden()
               VStack(alignment: .leading)
               {
                  // stuff here
               }
            }
            .frame(width: 250)
       }
       .padding()
       .toolbar {
        Button("Export", action: export)
    }
   { export() }
}

Apparently, the use of VStack, HStack, and so on is considered a form of "View". Seeing the code above gives me a much better idea of how SwiftUI expects to see code that generates controls on the Form.

To those that posted above, I saved that information for later use. Thankyou.

After a bunch of more digging around, I am finally getting a little traction on how to create a SwiftUI interface. And I am posting this here in hopes of helping someone else in my position.

struct MyCustomView: View
{
    @State private var volume: Double = 0
    var body: some View
    {
        Group
        {
            HStack
            {
                Text("oo")
                    .padding(2)
                    .border(Color.black)
                Button("Stop")
                {
                }
                Button("Play")
                {
                }
                Button("Jump")
                {
                }
            }
            .padding(.top, 10)
            VStack
            {
                Slider(value: $volume, in: -10...100)
                    .offset(x: 13,y: 0)
                    .frame(width: 150, height: 40)
            }
        }
        .offset(x: -150, y: 0)
    }
}

I did a screenshot of a portion of the original music player controls and the same thing using SwiftUI. Now there is the basis for improving the SwiftUI code to better match that of the original screen.

I hope this helps someone else.

Your layout seems quite unusual in the sense that you put a slider in the middle of nothing. There is seems to have no placement constraint other than obsolete positioning. (may be i am wrong) As show by Claude31 , you should define logical subviews (buttons view, tile view, header view, ...) Then you define how are these subviews arrange in line or column. If you need more complex positionning, you may use a large ZStack and set each subviews to a specific place. Or use en overlay to put the slider in the middle of the global view.

Hi Ptit-Xav,

  1. I placed the controls in the same manner as Claude31 recommended. If there is a better placement methods, please specify

  2. I don't know what you mean by "placement constraint"

  3. My view above is what I thought was a logical subview

  4. Regarding ZStack, I thought this was used to control depth of controls, such as various picture objects on top of each other.

  5. Don't know what you mean by global view, or what an overlay is

  6. I have spent about one month attempting to find comprehensive documentation on SwiftUI and its controls and how to place them, but have come up short. Even Rust has better documentation when it comes to the types of controls available (think FLTK or Iced), what they look like, and how to use them. 99% of the designs are a single vertical column.

  7. I have several SwiftUI books, and they cover a lot of material, but answering specific questions about how to place controls on a Form, epecially when the design is more complex, is seemingly hard to come by.

Sorry for all the questions, but SwiftUI and its terminology is completely foreign to me. I am used to StoryBoards, which is also very similar to C# WinForms. In the WinForms editor, one simply places controls where they want them.

After more trial and error, I found out that it seems to make more sense to layout the first "row" of controls using one HStack. Please see the attachment.

How To Position Controls With SwiftUI
 
 
Q