So basically I have already crafted my UI and it works just fine if it wasnt for the fact that my UI/Stacks do not seem to be fitting into devices with smaller screens such as the iPod Touch 7th gen or the iPhone SE 2nd gen. I was under the impression that if I avoided hardcoded frames and went with dynamic elements such as the spacing parameter on stacks, .padding, Spacer(), etc. then SwiftUI would do its layout magic and it would work across multiple screen sizes. Im not even using complex views here, its just a couple stacks & Text views.
Code:
struct EntireView: View {
var viewModel: ViewModel
var body: some View {
VStack {
HeadView(vm: viewModel)
Rectangle()
.frame(width: UIScreen.main.bounds.width - 20, height: 1)
FieldView(viewModel: viewModel)
ButtonView()
}
}
}
struct HeadView: View {
var body: some View {
VStack {
VStack(spacing: 15) {
Text("some text")
.font(.custom(FontType.OpenSans.bold, size: 16))
Text(vm.description)
.font(.custom(FontType.OpenSans.semibold, size: 14))
}
.padding()
VStack {
HStack {
VStack {
Text("some text")
.font(.custom(FontType.OpenSans.bold, size: 16))
Text("some text")
.font(.custom(FontType.OpenSans.regular, size: 12))
}
Spacer()
VStack {
Text("some text")
.font(.custom(FontType.OpenSans.bold, size: 16))
Text(""some text")
.font(.custom(FontType.OpenSans.regular, size: 12))
}
Spacer()
VStack {
Text("some text")
.font(.custom(FontType.OpenSans.bold, size: 16))
Text("some text")
.font(.custom(FontType.OpenSans.regular, size: 12))
}
}
}
.padding()
HStack {
Text("some text")
.font(.custom(FontType.OpenSans.italic, size: 14))
Spacer()
Text("some text")
.font(.custom(FontType.OpenSans.bold, size: 14))
.foregroundColor(.white)
.frame(width: 69, height: 25)
.background(.green)
.cornerRadius(4)
}
.padding()
}
}
}
struct FieldView: View {
let viewModel: HoldingDetailViewModel
var body: some View {
VStack(spacing: 20) {
VStack(spacing: 10) {
Text("some text")
.foregroundColor(.blue)
Text("some text")
.foregroundColor(.blue)
}
VStack(spacing: 10) {
Text("some text")
.foregroundColor(.blue)
HStack {
Text("some text")
Rectangle()
.fill(.blue)
.frame(width: 1, height: 25)
Text("some text")
}
.foregroundColor(.blue)
}
VStack(spacing: 10) {
Text("some text")
.foregroundColor(.blue)
Text("some text")
.foregroundColor(.blue)
}
VStack(spacing: 10) {
Text("some text")
.foregroundColor(.blue)
Text("some text")
.foregroundColor(.blue)
}
VStack(spacing: 10) {
Text("some text")
.foregroundColor(.blue)
Text("some text")
.foregroundColor(.blue)
}
}
.font(.custom(FontType.OpenSans.semibold, size: 14))
}
On smaller devices, theres elements not even being rendered as they do not fit the screen, how should I go about fixing this?
Currently, you have stacked so many Vertical Stacks on top of each other, that the UI builder simply runs out of physical screen estate to render all your UI elements.
I think what you want to use is a ScrollView
like this:
struct EntireView: View {
var viewModel: ViewModel
var body: some View {
ScrollView(.vertical, showsIndicators: false) {
HeadView(vm: viewModel)
Rectangle()
.frame(width: UIScreen.main.bounds.width - 20, height: 1)
FieldView(viewModel: viewModel)
ButtonView()
}
}
}
This way, all UI elements are rendered in a large VStack
so to say, which you can scroll through. Thus, not limited to the phyiscal screen size. Is this what you wanted?
If you desire some parts of your Views to be scrollable and some not, you can do the following for example:
struct EntireView: View {
var viewModel: ViewModel
var body: some View {
VStack {
HeadView(vm: viewModel)
ScrollView(.vertical, showsIndicators: false) {
Rectangle()
.frame(width: UIScreen.main.bounds.width - 20, height: 1)
FieldView(viewModel: viewModel)
ButtonView()
}
}
}
}
This way, the HeadView
stays in position at the top of the screen and the other contents will be scrollable.