I’ve a video participant that’s embedded inside a scroll view inside a subview. When the video participant is clicked I need to animate the video participant to the highest of the view hierarchy and current it above all the things else utilizing a matched geometry impact. I can not get the animation to work and as a substitute the video is instantly offered.
My strategy is passing the AVPlayer and url by way of an atmosphere object and utilizing the url because the id for geo impact.
struct SomeView: View { // subview
let instance = "instance https://drive.google.com/file/d/1fom7lDNjP7thxTuowYtsUXbErvX2jhzH/view?usp=sharing"
var physique: some View {
ScrollView {
BottomVideoView(url: URL(string: instance)!)
//some views
}
}
}
struct ContentView: View { //prime of view hierarchy
@EnvironmentObject var popRoot: PopToRoot
@Namespace personal var animation
var physique: some View {
SomeView()
.overlay {
if popRoot.participant != nil {
TopVideoView(participant: $popRoot.participant)
.matchedGeometryEffect(id: popRoot.playID, in: animation)
// ----- HERE
}
}
}
}
class PopToRoot: ObservableObject { //envirnment object to be accessed anyplace
@Revealed var participant: AVPlayer? = nil
@Revealed var playID: String = ""
}
video participant that goes above all the things
struct TopVideo: View {
@Binding var participant: AVPlayer?
var physique: some View {
ZStack(alignment: .topTrailing){
Shade.black
if let vid = participant {
VStack {
Spacer()
VidPlayer(participant: vid).aspectRatio(contentMode: .match)
Spacer()
}
}
Button(motion: {
withAnimation {
participant = nil
}
}, label: {
Picture(systemName: "xmark").foregroundStyle(.white).font(.headline)
}).padding(.trailing, 20).padding(.prime, 80)
}
.ignoresSafeArea()
}
}
struct TopVideoView: View {
@Binding var participant: AVPlayer?
@State personal var hostingController: UIHostingController<TopVideo>? = nil
func showImage() {
let swiftUIView = TopVideo(participant: $participant)
hostingController = UIHostingController(rootView: swiftUIView)
hostingController?.view.backgroundColor = .clear
hostingController?.view.body = CGRect(
x: 0,
y: 0,
width: UIScreen.principal.bounds.width,
peak: UIScreen.principal.bounds.peak)
if let windowScene = UIApplication.shared.connectedScenes.first as? UIWindowScene,
let window = windowScene.home windows.first {
window.addSubview(hostingController!.view)
hostingController?.view.heart.x = window.heart.x
}
}
func dismissImage() {
hostingController?.view.removeFromSuperview()
hostingController = nil
}
var physique: some View {
VStack {}
.onAppear { showImage() }
.onDisappear { dismissImage() }
}
}
video participant in subview
struct BottomVideoView: View {
@EnvironmentObject var popRoot: PopToRoot
let url: URL
@State var participant: AVPlayer? = nil
@Namespace personal var animation
var physique: some View {
ZStack {
if let vid = participant {
VidPlayer(participant: vid)
// ----- HERE
.matchedGeometryEffect(id: url.absoluteString, in: animation)
.onTapGesture {
withAnimation {
popRoot.playID = url.absoluteString
popRoot.participant = participant
}
}
}
}
.onAppear {
if participant == nil {
participant = AVPlayer(url: url)
}
self.participant?.play()
}
}
}
struct VidPlayer : UIViewControllerRepresentable {
var participant : AVPlayer
func makeUIViewController(context: UIViewControllerRepresentableContext<VidPlayer>) -> AVPlayerViewController {
let controller = AVPlayerViewController()
controller.participant = participant
controller.showsPlaybackControls = false
controller.allowsVideoFrameAnalysis = false
return controller
}
func updateUIViewController(_ uiViewController: AVPlayerViewController, context: UIViewControllerRepresentableContext<VidPlayer>) { }
}