0

I m making a TimerView in swiftui getting a start time and stop time on button pressed.
This is what it looks like on loading When I click Start When I click Stop

I am using two VStack inside a HStack to ensure that the text are aligned properly, but I am unable to account for the timestamp text size that are sometimes too large and goes out of alignment (timestamp is lower than the label!) (click start) or that the two different timestamps have different sizing (click stop)

How should I ensure that the text is uniformly sized while fitting to the window (the text was too long and went out of bounds)?

import SwiftUI

struct TimerView: View {
    @State var fromTime = ""
    @State var toTime = ""
    
    var body: some View {
        VStack (alignment: .leading){
            HStack{
                VStack (alignment: .leading){
                    Text("From Time: ").padding(.bottom, 3.0)
                    Text("To Time: ")
                }
                
                VStack (alignment: .leading) {
                    Text(fromTime).minimumScaleFactor(0.2).padding(.bottom, 3.0)
                    Text(toTime).minimumScaleFactor(0.2)
                }
                //Text(fromTime).minimumScaleFactor(0.2)
            }.padding(.bottom, 60.0)
            //            HStack{
            //                Text("To Time: ")
            //                Text(toTime).minimumScaleFactor(0.2)
            //            }.padding(.bottom, 60.0)
            HStack{
                Button(action: {fromTime = getDate()}) {
                    Text("Start")
                }.padding(.top, 10.0)
                .padding(.bottom, 10.0)
                .padding(.trailing,40.0)
                .padding(.leading, 40.0)
                .overlay(
                    RoundedRectangle(cornerRadius: 10.0).stroke(lineWidth: 2.0)
                )
                
                Button(action: {toTime = getDate()}) {
                    Text("Stop")
                }.padding(.top, 10.0)
                .padding(.bottom, 10.0)
                .padding(.trailing, 40.0)
                .padding(.leading, 40.0)
                .overlay(
                    RoundedRectangle(cornerRadius: 10.0)
                        .stroke(lineWidth: 2.0)
                )
            }
        }
    }
}

struct TimerView_Previews: PreviewProvider {
    static var previews: some View {
        TimerView()
    }
}

extension TimerView {
    func getDate()->String{
        let time = Date()
        let timeFormatter = DateFormatter()
        timeFormatter.dateFormat = "yyyy-MM-dd HH:mm:ss"
        let stringDate = timeFormatter.string(from: time)
        return stringDate
    }
}

2 Answers2

1

you could just simply adjust the font size according to the screen size, eg: one small font for small size devices and another for larger devices. See this How to get device width and height?

Then use this, given the desired font fsize:

HStack {
    VStack (alignment: .leading) {
        Text("From Time: " + fromTime)
        Text("To Time:   " + toTime)
    }
    .font(.system(size: fsize))  // <--- here to fit the screen width
    .padding(.bottom, 3.0)
}.padding(.bottom, 60.0)
  • Hi @workingdog, while your solution is much more simplistic to append to the text, it did not provide the "look" of the user interface i wanted in the simulator which is why I went with the other answer. Thank you for your answer! – experiment unit 1998X Oct 19 '21 at 03:16
1

Add firstTextBaseline

struct TimerView: View {
    @State var fromTime = ""
    @State var toTime = ""
    
    var body: some View {
        VStack (alignment: .leading){
           HStack(alignment: .firstTextBaseline){ // <----- Add this line
                VStack (alignment: .leading){
                    Text("From Time: ").padding(.bottom, 3.0)
                    Text("To Time: ")
                }
                
                VStack (alignment: .leading) {
                    Text(fromTime).minimumScaleFactor(0.2).padding(.bottom, 3.0)
                    Text(toTime).minimumScaleFactor(0.2)
                }
                //Text(fromTime).minimumScaleFactor(0.2)
            }.padding(.bottom, 60.0)
            //            HStack{
            //                Text("To Time: ")
            //                Text(toTime).minimumScaleFactor(0.2)
            //            }.padding(.bottom, 60.0)
            HStack{
                Button(action: {fromTime = getDate()}) {
                    Text("Start")
                }.padding(.top, 10.0)
                .padding(.bottom, 10.0)
                .padding(.trailing,40.0)
                .padding(.leading, 40.0)
                .overlay(
                    RoundedRectangle(cornerRadius: 10.0).stroke(lineWidth: 2.0)
                )
                
                Button(action: {toTime = getDate()}) {
                    Text("Stop")
                }.padding(.top, 10.0)
                .padding(.bottom, 10.0)
                .padding(.trailing, 40.0)
                .padding(.leading, 40.0)
                .overlay(
                    RoundedRectangle(cornerRadius: 10.0)
                        .stroke(lineWidth: 2.0)
                )
            }
        }
    }
}
Ray Xu
  • 130
  • 5
  • Hi @Ray Xu, while your answer helped me resolve the alignment of the text, the text formatting while scaling the text was not resolved, so I opted to remove the text scaling and utilise the following: https://stackoverflow.com/a/57677746 – experiment unit 1998X Oct 19 '21 at 03:19
  • Though your answer was the closest to solving my issue while preserving the look I was trying to go with. Thank you for your answer! – experiment unit 1998X Oct 19 '21 at 03:19