Эффект согласованной геометрии анимируется неправильно. ⇐ IOS
Эффект согласованной геометрии анимируется неправильно.
I have a video player that is embedded within a scroll view inside a subview. When the video player is clicked I want to animate the video player to the top of the view hierarchy and present it above everything else using a matched geometry effect. I cannot get the animation to work and instead the video is immediately presented.
My approach is passing the AVPlayer and url through an environment object and using the url as the id for geo effect.
I tried adding the matched geo effect to multiple different places and directly to the video but its not working.
struct SomeView: View { // subview let example = "example https://drive.google.com/file/d/1fom7lD ... sp=sharing" var body: some View { ScrollView { BottomVideoView(url: URL(string: example)!) //some views } } } struct ContentView: View { //top of view hierarchy @EnvironmentObject var popRoot: PopToRoot @Namespace private var animation var body: some View { SomeView() .overlay { if popRoot.player != nil { TopVideoView(player: $popRoot.player) .matchedGeometryEffect(id: popRoot.playID, in: animation) // ----- HERE } } } } class PopToRoot: ObservableObject { //envirnment object to be accessed anywhere @Published var player: AVPlayer? = nil @Published var playID: String = "" } video player that goes above everything
struct TopVideo: View { @Binding var player: AVPlayer? var body: some View { ZStack(alignment: .topTrailing){ Color.black if let vid = player { VStack { Spacer() VidPlayer(player: vid).aspectRatio(contentMode: .fit) Spacer() } } Button(action: { withAnimation { player = nil } }, label: { Image(systemName: "xmark").foregroundStyle(.white).font(.headline) }).padding(.trailing, 20).padding(.top, 80) } .ignoresSafeArea() } } struct TopVideoView: View { @Binding var player: AVPlayer? @State private var hostingController: UIHostingController? = nil func showImage() { let swiftUIView = TopVideo(player: $player) hostingController = UIHostingController(rootView: swiftUIView) hostingController?.view.backgroundColor = .clear hostingController?.view.frame = CGRect( x: 0, y: 0, width: UIScreen.main.bounds.width, height: UIScreen.main.bounds.height) if let windowScene = UIApplication.shared.connectedScenes.first as? UIWindowScene, let window = windowScene.windows.first { window.addSubview(hostingController!.view) hostingController?.view.center.x = window.center.x } } func dismissImage() { hostingController?.view.removeFromSuperview() hostingController = nil } var body: some View { VStack {} .onAppear { showImage() } .onDisappear { dismissImage() } } } video player in subview
struct BottomVideoView: View { @EnvironmentObject var popRoot: PopToRoot let url: URL @State var player: AVPlayer? = nil @Namespace private var animation var body: some View { ZStack { if let vid = player { VidPlayer(player: vid) // ----- HERE .matchedGeometryEffect(id: url.absoluteString, in: animation) .onTapGesture { withAnimation { popRoot.playID = url.absoluteString popRoot.player = player } } } } .onAppear { if player == nil { player = AVPlayer(url: url) } self.player?.play() } } } struct VidPlayer : UIViewControllerRepresentable { var player : AVPlayer func makeUIViewController(context: UIViewControllerRepresentableContext) -> AVPlayerViewController { let controller = AVPlayerViewController() controller.player = player controller.showsPlaybackControls = false controller.allowsVideoFrameAnalysis = false return controller } func updateUIViewController(_ uiViewController: AVPlayerViewController, context: UIViewControllerRepresentableContext) { } }
Источник: https://stackoverflow.com/questions/780 ... -correctly
I have a video player that is embedded within a scroll view inside a subview. When the video player is clicked I want to animate the video player to the top of the view hierarchy and present it above everything else using a matched geometry effect. I cannot get the animation to work and instead the video is immediately presented.
My approach is passing the AVPlayer and url through an environment object and using the url as the id for geo effect.
I tried adding the matched geo effect to multiple different places and directly to the video but its not working.
struct SomeView: View { // subview let example = "example https://drive.google.com/file/d/1fom7lD ... sp=sharing" var body: some View { ScrollView { BottomVideoView(url: URL(string: example)!) //some views } } } struct ContentView: View { //top of view hierarchy @EnvironmentObject var popRoot: PopToRoot @Namespace private var animation var body: some View { SomeView() .overlay { if popRoot.player != nil { TopVideoView(player: $popRoot.player) .matchedGeometryEffect(id: popRoot.playID, in: animation) // ----- HERE } } } } class PopToRoot: ObservableObject { //envirnment object to be accessed anywhere @Published var player: AVPlayer? = nil @Published var playID: String = "" } video player that goes above everything
struct TopVideo: View { @Binding var player: AVPlayer? var body: some View { ZStack(alignment: .topTrailing){ Color.black if let vid = player { VStack { Spacer() VidPlayer(player: vid).aspectRatio(contentMode: .fit) Spacer() } } Button(action: { withAnimation { player = nil } }, label: { Image(systemName: "xmark").foregroundStyle(.white).font(.headline) }).padding(.trailing, 20).padding(.top, 80) } .ignoresSafeArea() } } struct TopVideoView: View { @Binding var player: AVPlayer? @State private var hostingController: UIHostingController? = nil func showImage() { let swiftUIView = TopVideo(player: $player) hostingController = UIHostingController(rootView: swiftUIView) hostingController?.view.backgroundColor = .clear hostingController?.view.frame = CGRect( x: 0, y: 0, width: UIScreen.main.bounds.width, height: UIScreen.main.bounds.height) if let windowScene = UIApplication.shared.connectedScenes.first as? UIWindowScene, let window = windowScene.windows.first { window.addSubview(hostingController!.view) hostingController?.view.center.x = window.center.x } } func dismissImage() { hostingController?.view.removeFromSuperview() hostingController = nil } var body: some View { VStack {} .onAppear { showImage() } .onDisappear { dismissImage() } } } video player in subview
struct BottomVideoView: View { @EnvironmentObject var popRoot: PopToRoot let url: URL @State var player: AVPlayer? = nil @Namespace private var animation var body: some View { ZStack { if let vid = player { VidPlayer(player: vid) // ----- HERE .matchedGeometryEffect(id: url.absoluteString, in: animation) .onTapGesture { withAnimation { popRoot.playID = url.absoluteString popRoot.player = player } } } } .onAppear { if player == nil { player = AVPlayer(url: url) } self.player?.play() } } } struct VidPlayer : UIViewControllerRepresentable { var player : AVPlayer func makeUIViewController(context: UIViewControllerRepresentableContext) -> AVPlayerViewController { let controller = AVPlayerViewController() controller.player = player controller.showsPlaybackControls = false controller.allowsVideoFrameAnalysis = false return controller } func updateUIViewController(_ uiViewController: AVPlayerViewController, context: UIViewControllerRepresentableContext) { } }
Источник: https://stackoverflow.com/questions/780 ... -correctly
-
- Похожие темы
- Ответы
- Просмотры
- Последнее сообщение
-
-
Нежелательный эффект кроссфейда в эффекте согласованной геометрии SwiftUI
Anonymous » » в форуме IOS - 0 Ответы
- 40 Просмотры
-
Последнее сообщение Anonymous
-