Code of the classes is below, the issue is: I have a custom view that is a list of custom buttons Data for this view is being fetched in View Model in @Published field and then passed to the view as @Binding
UPD: what I found out, the scrollview is not updating its height or something like that, hence the RadioButtonGroup just don't fit and not displayed
Thanks a lot for everyone reading this! You are amazing
So here is my main class
import Foundation
import SwiftUI
import PhotosUI
struct SignupView: View {
@StateObject var viewModel: SignUpVM
@State private var selectedPos = ""
var body: some View {
ScrollView(showsIndicators: false){
VStack( spacing: 24){
Text("Select your position")
.font(UIConstraints.fontRegular(size: 18))
.frame(maxWidth: .infinity, alignment: .leading)
RadioButtonGroup<Position>(items: $viewModel.positions, selectedId: "London") { selected in
}
Spacer()
}
.padding(.vertical, 32)
.padding(.horizontal, 16)
}
}
}
struct ContentView_Previews4: PreviewProvider {
struct Wrapper: View {
@State private var isPresented: UIImage? = UIImage(named: "photo-cover")
@StateObject var vm = SignUpVM()
var body: some View {
SignupView(viewModel: vm)
}
}
static var previews: some View {
Wrapper()
}
}
And a second one
import Foundation
import SwiftUI
protocol RadioButtonItem {
var id: Int { get set }
var name: String { get set }
}
struct RadioButtonGroup<T: RadioButtonItem>: View {
@Binding var items : [T]
@State var selectedId: String = ""
let callback: (String) -> ()
var body: some View {
VStack {
List(items, id: \.id) { item in
RadioButton(item.name, callback: self.radioGroupCallback, selectedID: self.selectedId)
.listRowSeparator(.hidden)
.listRowInsets(EdgeInsets())
}
.listStyle(PlainListStyle())
}
}
func radioGroupCallback(id: String) {
selectedId = id
callback(id)
}
}
struct RadioButton: View {
@Environment(\.colorScheme) var colorScheme
let id: String
let callback: (String)->()
let selectedID : String
let size: CGFloat
let color: Color
let textSize: CGFloat
init(
_ id: String,
callback: @escaping (String)->(),
selectedID: String,
size: CGFloat = 20,
color: Color = Color.primary,
textSize: CGFloat = 14
) {
self.id = id
self.size = size
self.color = color
self.textSize = textSize
self.selectedID = selectedID
self.callback = callback
}
var body: some View {
Button(action:{
self.callback(self.id)
}) {
HStack(alignment: .center, spacing: 10) {
Image(self.selectedID == self.id ? "radio-button-selected" : "radio-button-unselected")
.renderingMode(.original)
.resizable()
.frame(width: 17, height: 17)
.aspectRatio(contentMode: .fit)
.foregroundColor(self.selectedID == self.id ? UIConstraints.secondary : .gray)
.padding(17)
Text(id)
.font(UIConstraints.fontRegular(size: 16))
Spacer()
}.foregroundColor(self.color)
}
.foregroundColor(self.color)
.padding(0)
}
}
struct InputTextField_PreviewsRadio: PreviewProvider {
struct Wrapper: View {
@StateObject var viewModel = SignUpVM()
var body: some View {
RadioButtonGroup<Position>(items: $viewModel.positions, selectedId: "London") { selected in
}
}
}
static var previews: some View {
Wrapper()
}
}
Like lorem ipsum said, List
in ScrollView
can only have fixed size. Use ForEach
instead.