Home > Mobile >  Why does preview layout shown in SwiftUI not match layout on phone?
Why does preview layout shown in SwiftUI not match layout on phone?

Time:03-09

I am new to SwiftUI and so have just started a project in it. I have set the display to an iPhone12 as that is currently what I have. I have just completed creating the graphical user interface and when in click run it is all perfect. However, when I run it on my actual phone the entire layout messes up? It used to work but recently it's varied a lot from the preview. Any idea what's gone wrong? Any help would be appreciated

Xcode preview iPhone preview

import SwiftUI
struct ContentView: View {


//Creating Variables for Topics
@State private var setMemory = false
@State private var setSocialInfluence = false
@State private var setApproaches = false
@State private var setPsychopathology = false
@State private var setBiopsychology = false
@State private var setAttachment = false
@State private var setIssuesandDebates = false
@State private var setSchizophrenia = false
@State private var setResearchMethods = false

//Creating Buttons for Number of Questions
        let buttons = ["10", "20", "30", "40", "50"]
@State public var buttonSelected: Int?

//Creating Variable for 'How To Use' Instructions
@State private var HowToUse = """
1. Select your revision topics
2. Choose how many questions you are able to answer
3. Click the 'continue' button and start revising!
"""
@State private var HowToUse2 = """
Multiple choice questions will appear first. Once you have a score of 5 or over, the difficulty will increase to short-answer questions. If you master these and achieve a score of 25 or above, long-answer questions will appear.
"""
@State private var HowToUse3 = """
All multiple choice questions will be automatically marked. For the harder questions, a student-friendly markscheme will show and you will need to input your score. Be honest!
"""

//Creating Variables for 'Continue' Button
let button = ["Continue"]
@State public var buttonContinue: Int?

var body: some View {
    
//App Logo and Vertical Stacks
    VStack(spacing: 1.0) {
        HStack {
            Image("AppLogo")
                .resizable()
                .scaledToFit()
                .padding(.trailing, 50.0)
            .frame(height: 100, alignment: .topLeading)
            .padding(.top, 55)}
        
//'Topics to Revise' Header
        HStack {
        Text("A-Level Topics")
            .font(.title2)
            .fontWeight(.medium)
            .padding(.top, -20.0)
            .frame(width: 161, height: 10, alignment: .topLeading)
            .padding(.trailing, 198.0)
            
            Text("Click to Revise")
                .padding(.leading, -368.0)
                .padding(.top, 30.0)
                .padding(.bottom, 10.0)
        }
        
//Toggles for Topics
//Used Group{} to Prevent Argument Error
        Group{
        HStack {
            Toggle("Memory",isOn: $setMemory)
                .padding(.leading, -40.0)
                .padding(.top, -5.0)
                .toggleStyle(.button)
                .tint(Color(hue: 0.688, saturation: 1.0, brightness: 1.0))
            Toggle("Social Influence",isOn: $setSocialInfluence)
                .padding(.top, -5.0)
                .toggleStyle(.button)
                .tint(Color(red: 1.0, green: 0.601, blue: 0.783))
                .padding(.leading, 105.0)}

            HStack {
            Toggle("Approaches",isOn: $setApproaches)
                    .padding(.leading, -27.0)
                   .padding(.top, 5.0)
                .toggleStyle(.button)
                .tint(Color(red: 0.629, green: 0.909, blue: 0.527))
            Toggle("Psychopathology",isOn: $setPsychopathology)
                    .padding(.top, 5.0)
                .toggleStyle(.button)
                .tint(Color(red: 0.99, green: 0.862, blue: 0.028))
                .padding(.leading, 76.0)}
        
        HStack {
            Toggle("Biopsychology",isOn: $setBiopsychology)
                .toggleStyle(.button)
                .tint(Color(red: 1.0, green: 0.601, blue: 0.079))
                .padding(.top, 5.0)
                .padding(.leading, -70.0)
            Toggle("Attachment",isOn: $setAttachment)
                .toggleStyle(.button)
                .tint(.cyan)
                .padding(.top, 5.0)
                .padding(.leading, 57.0)}
        
        HStack {
            Toggle("Issues & Debates",isOn: $setIssuesandDebates)
                .padding(.leading, -51.0)
                .padding(.top, 5.0)
                .toggleStyle(.button)
                .tint(Color(red: 0.864, green: 0.879, blue: 0.735))
            Toggle("Schizophrenia",isOn: $setSchizophrenia)
                .toggleStyle(.button)
                .tint(Color(red: 0.722, green: 0.348, blue: 0.7))
                .padding(.top, 5.0)
                .padding(.leading, 36.0)}
        
        HStack {
            Toggle("Research Methods Year 1 & 2",isOn: $setResearchMethods)
                .padding(.leading, -137.0)
                .padding(.top, 5.0)
                .toggleStyle(.button)
            .tint(Color(red: 0.649, green: 0.881, blue: 0.98))}
        .padding(.bottom, 10.0)
        }
        
        
//'Number of Questions' Header
        Group{
        Text("Number of Questions")
            .font(.title2)
            .fontWeight(.medium)
            .foregroundColor(.black)
            .padding(.trailing, 161.0)
        
        Spacer()
        
//Number of Questions - Selected Buttons
        HStack(spacing: 15) {
        ForEach(0..<buttons.count) {button in
                Button(action: {
                    self.buttonSelected = button
                    
                }) {
                    Text("\(self.buttons[button])")
                        .padding()
                        .foregroundColor(.white)
                        .background(self.buttonSelected == button ? Color.black: Color.gray)
                    .clipShape(Capsule())}}
            
        }
    }
        
        Spacer()
        
//'How To Use' Header
        Text("How To Use")
             .font(.title2)
             .fontWeight(.medium)
             .foregroundColor(.black)
             .padding(.trailing, 254.0)

//How To Use Instructions
      VStack{
         Text(HowToUse)
         .fixedSize(horizontal: false, vertical: true)
         .font(.subheadline)
          
          Spacer()
          
          Text(HowToUse2)
              .fixedSize(horizontal: false, vertical: true)
              .font(.subheadline)
              .padding(.leading, 5)
              .padding(.bottom, -6)
          
         Text(HowToUse3)
              .fixedSize(horizontal: false, vertical: true)
              .font(.subheadline)
              .padding(.leading, -2)
          
      }
        
        Spacer()
        
        HStack(spacing: 15) {
        ForEach(0..<button.count) {button in
                Button(action: {
                    self.buttonContinue = button
                    
                }) {
                    Text("\(self.button[button])").padding(.vertical, 12.5)
                        .padding(.horizontal, 120)
                        .foregroundColor(.white)
                        .background(self.buttonContinue == button ? Color.black: Color.gray)
                    .clipShape(Capsule())}}
            
        }
        
        
      .padding(.bottom, 45)
        
    }
    
}


struct Previews_ContentView_Previews: PreviewProvider {
static var previews: some View {
        ContentView()
    
    
  }
}
}

CodePudding user response:

You'll need to make some decisions about what happens when you have varying screen sizes. Right now, you have some code that works on one screen size, but is a bit fragile if anything changes even slightly.

In your current code, it looks like you want your Text items in the lower section of your View to be aligned to the leading edge of the View. To do that, you'll need to set an alignment on your VStack. But, it's unclear whether you want all of the titles to be aligned that way as well, or just the sub-items.

Here's an example of the types of modifications you'll want to make:

VStack(alignment: .leading) { //<-- Note the leading here 
    Text(HowToUse)
        .fixedSize(horizontal: false, vertical: true)
        .font(.subheadline)
    
    Spacer()
    
    Text(HowToUse2)
        .fixedSize(horizontal: false, vertical: true)
        .font(.subheadline)
        .padding(.bottom, -6)
            //<-- Remove leading padding 
    
    Text(HowToUse3)
        .font(.subheadline)
        .fixedSize(horizontal: false, vertical: true)
           //<-- Remove leading padding
}

Another consideration you'll have to make is what happens if the screen isn't tall enough to accommodate your View -- this could happen with a smaller device or if the user has accessibility settings turned on that increase the font size, for example. Most likely, you'll want to embed your content in a ScrollView to account for this.

In terms of why this looked different in the preview vs the device, perhaps the preview returns slightly different dimensions for either the screen or maybe even just the safe area. Regardless, it is actually probably a good thing, as it exposed some potential fragility in the current layout.

  • Related