UIScrollView в SwiftUI с содержимым Dynami c неправильной длины - PullRequest
0 голосов
/ 11 июля 2020

Я пытаюсь добавить UIScrollView, поддерживающий динамический c контент, в проект SwiftUI. Моя проблема в том, что при изменении содержимого UIScrollView не обновляет свою длину. В этом примере круги будут обрезаны. Это, наверное, довольно просто, но я ничего не нашел по этой топи c в сети. Как я могу это решить?

struct ContentView: View {
    @State var count = 5
    
    var body: some View {
        
        GeometryReader{ geometry in
            VStack{
                Spacer()
                
                UIScrollViewWrapper(pagingEnabled: false){
                    HStack(spacing: 10){
                        ForEach(0..<self.count, id: \.self) { item in
                            Circle()
                                .foregroundColor(.green)
                                .frame(width: 80, height: 50)  
                        }
                    }
                }
                
                Spacer()
                Button(action:{
                    self.count += 1
                })
                {
                    Text("Increase Circle Count")
                }
                Spacer()
            }
        }
    }
}


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

struct UIScrollViewWrapper<Content: View>: UIViewControllerRepresentable {
    
    var content: () -> Content
    var pagingEnabled: Bool
    
    init(pagingEnabled: Bool, @ViewBuilder content: @escaping () -> Content) {
        self.content = content
        self.pagingEnabled = pagingEnabled
    }
    
    func makeUIViewController(context: Context) -> UIScrollViewViewController {
        let vc = UIScrollViewViewController()
        vc.hostingController.rootView = AnyView(self.content())
        vc.pagingEnabled = self.pagingEnabled
        return vc
    }
    
    func updateUIViewController(_ viewController: UIScrollViewViewController, context: Context) {
        viewController.hostingController.rootView = AnyView(self.content())
    }
}

class UIScrollViewViewController: UIViewController {
    
    var pagingEnabled = false
    
    lazy var scrollView: UIScrollView = {
        let v = UIScrollView()
        v.isPagingEnabled = self.pagingEnabled
        v.showsHorizontalScrollIndicator = false
        return v
    }()
    
    var hostingController: UIHostingController<AnyView> = UIHostingController(rootView: AnyView(EmptyView()))
    
    override func viewDidLoad() {
        super.viewDidLoad()
        self.view.addSubview(self.scrollView)
        self.pinEdges(of: self.scrollView, to: self.view)
        
        self.hostingController.willMove(toParent: self)
        self.scrollView.addSubview(self.hostingController.view)
        self.pinEdges(of: self.hostingController.view, to: self.scrollView)
        self.hostingController.didMove(toParent: self)
        
    }
    
    func pinEdges(of viewA: UIView, to viewB: UIView) {
        viewA.translatesAutoresizingMaskIntoConstraints = false
        viewB.addConstraints([
            viewA.leadingAnchor.constraint(equalTo: viewB.leadingAnchor),
            viewA.trailingAnchor.constraint(equalTo: viewB.trailingAnchor),
            viewA.topAnchor.constraint(equalTo: viewB.topAnchor),
            viewA.bottomAnchor.constraint(equalTo: viewB.bottomAnchor),
        ])
    }
    
}

1 Ответ

0 голосов
/ 11 июля 2020

Если нет конкретной c причины использовать UIScrollViewWrapper, вы можете использовать собственный ScrollView компонент SwiftUI. Это обновляет представление по мере необходимости: (Требуется только этот код)

struct ContentView: View {
    @State var count = 5
    
    var body: some View {
        
        GeometryReader{ geometry in
            VStack{
                Spacer()

                // Change here
                ScrollView(.horizontal, showsIndicators: false){
                    HStack(spacing: 10){
                        ForEach(0..<self.count, id: \.self) { item in
                            Circle()
                                .foregroundColor(.green)
                                .frame(width: 80, height: 50)
                            .overlay(Text(String(item)))
                        }
                    }
                }
                
                Spacer()
                Button(action:{
                    self.count += 1
                })
                {
                    Text("Increase Circle Count")
                }
                Text(String(self.count))
                Spacer()
            }
        }
    }
}

См. Здесь:

введите описание изображения здесь

...