Search code examples
swiftuser-interfacedebuggingswiftui

scrollView height UI not updating SwiftUI


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()
    }
}

Solution

  • Like lorem ipsum said, List in ScrollView can only have fixed size. Use ForEach instead.