I want to implement UIScrollView in UIKit using UIViewRepresentable in SwiftUI. But I have a problem that UIScrollView implemented via UIViewRepresentable bridge can't perform animation with withAnimation .
To find the cause of the problem, I used a ScrollView in SwftUI as a comparison. By comparison, it is found that SwftUI ScrollView executes withAnimation normally; however, UIScrollView implemented through UIViewRepresentable bridge cannot specify animation.
May I ask if it is because of my incorrect use of UIViewRepresentable updateUIView?
I also found related articles, such as https://github.com/rcarver/swift-matched-animation It seems that the solution is mentioned, but it does not actually solve my problem.
English is not very good, I don't know if I can understand this description
import SwiftUI
import UIKit
struct FriendView: View {
@State var display = false
var body: some View {
VStack {
// UIViewRepresentable + UIKit
UScrollView {
VStack {
RoundedRectangle(cornerRadius: 10)
.fill(self.display ? .red.opacity(0.3) : .blue.opacity(0.3))
.frame(width: 200, height: self.display ? 200 : 100)
.onTapGesture {
withAnimation {
self.display.toggle()
}
}
}
}
// SwiftUI
ScrollView {
VStack {
RoundedRectangle(cornerRadius: 10)
.fill(self.display ? .red.opacity(0.3) : .blue.opacity(0.3))
.frame(width: 200, height: self.display ? 200 : 100)
.onTapGesture {
withAnimation {
self.display.toggle()
}
}
}
}
}
}
}
The following is the specific implementation of UIScrollView in UIKit
struct UScrollView<Content: View>: UIViewRepresentable {
typealias UIViewType = UIScrollView
var content: () -> Content
let scrollView: UIScrollView = {
let view = UIScrollView()
return view
}()
var host: UIHostingController<AnyView> = UIHostingController(
rootView: AnyView(EmptyView())
)
init(@ViewBuilder content: @escaping () -> Content) {
self.content = content
}
func makeUIView(context: Context) -> UIScrollView {
host.rootView = AnyView(self.content())
host.view.translatesAutoresizingMaskIntoConstraints = false
scrollView.addSubview(host.view)
scrollView.addConstraints([
host.view.topAnchor.constraint(equalTo: scrollView.topAnchor),
host.view.leadingAnchor.constraint(equalTo: scrollView.leadingAnchor),
host.view.trailingAnchor.constraint(equalTo: scrollView.trailingAnchor),
host.view.bottomAnchor.constraint(equalTo: scrollView.bottomAnchor),
host.view.widthAnchor.constraint(equalTo: scrollView.widthAnchor)
])
return scrollView
}
func updateUIView(_ uiView: UIScrollView, context: Context) {
host.rootView = AnyView(self.content())
host.view.translatesAutoresizingMaskIntoConstraints = false
uiView.addSubview(host.view)
uiView.addConstraints([
host.view.topAnchor.constraint(equalTo: uiView.topAnchor),
host.view.leadingAnchor.constraint(equalTo: uiView.leadingAnchor),
host.view.trailingAnchor.constraint(equalTo: uiView.trailingAnchor),
host.view.bottomAnchor.constraint(equalTo: uiView.bottomAnchor),
host.view.widthAnchor.constraint(equalTo: uiView.widthAnchor)
])
}
}
Comparing the execution effect, 1 withAnimation is invalid, 2 withAnimation is valid
