首页 > 解决方案 > 子视图的手势在 SwiftUI 中不起作用

问题描述

使用 Swift5.3.2、iOS14.4.1、Xcode12.4、

我正在尝试在 SwiftUI 中同时使用两个手势。

有问题的子视图是 VideoPlayer。

父视图是一个 ZStack。

我正在使用.simultaneousGesture修饰符,希望这将允许所有子视图手势仍然通过。

但他们没有!

以下代码有效,但不允许识别 VideoPlayer 的控制手势。

事实上,restartScannerTapGesture我的示例中的 TapGesture 总是会启动 - 不幸的是,VideoPlayer 控制手势(如暂停、播放、停止等)被忽略了。

在 Swift UI 中向父视图添加手势时如何让子视图手势起作用的任何想法?

struct ParentView: View {

    @EnvironmentObject var myURLList

    var body: some View {
        
        let restartScannerTapGesture = TapGesture(count: 1)
            .onEnded {
                actionClickID = UUID()
            }

        ZStack {
            if let url = URL(fileURLWithPath: myURLList[0].path){
                if url.containsImage {
                    Image(uiImage: UIImage(contentsOfFile: url.path)!)
                        .resizable()
                        .scaledToFit()
                        .onAppear() {
                            isVideo = false
                        }
                } else if url.containsVideo {
                    CustomPlayerView(url: url, isVideo: $isVideo)
                        .onAppear() {
                            isVideo = true
                        }
                } else {
                    Text(LocalizedStringKey("MediaNotRecognizedKey"))
                        .multilineTextAlignment(.center)
                        .padding()
                        .onAppear() {
                            isVideo = false
                        }
                }
            } else {
                Text(LocalizedStringKey("MediaNotRecognizedKey"))
                    .multilineTextAlignment(.center)
                    .padding()
                    .onAppear() {
                        isVideo = false
                    }
            }
        }
    }
    .simultaneousGesture(restartScannerTapGesture)
}

这是首先显示视频控件的 CustomPlayerView。这显然是有问题的子视图。它的手势也应该起作用,但它们不起作用。为什么 ??

import SwiftUI
import AVKit

class PlayerViewModel: ObservableObject {
    
    @Published var avPlayer: AVPlayer?
    
    func loadFromUrl(url: URL) {
        avPlayer = AVPlayer(url: url)
    }
    
    func playVideo() {
        avPlayer?.play()
    }
    
    func stopVideo() {
        avPlayer?.pause()
        avPlayer?.replaceCurrentItem(with: nil)
    }
}

struct CustomPlayerView: View {
    
    var url : URL
    @Binding var isVideo: Bool
    @StateObject private var playerViewModel = PlayerViewModel()
    
    var body: some View {
        
           ZStack {
        if let url = URL(fileURLWithPath: list.paths[index]){
            if url.containsImage {
                Image(uiImage: UIImage(contentsOfFile: url.path)!)
                    .resizable()
                    .scaledToFit()
                    .onAppear() {
                        isVideo = false
                    }
            } else if url.containsVideo {
                CustomPlayerView(url: url, isVideo: $isVideo)
                    .onAppear() {
                        isVideo = true
                    }
            } else {
                Text(LocalizedStringKey("MediaNotRecognizedKey"))
                    .multilineTextAlignment(.center)
                    .padding()
                    .onAppear() {
                        isVideo = false
                    }
            }
        } else {
            Text(LocalizedStringKey("MediaNotRecognizedKey"))
                .multilineTextAlignment(.center)
                .padding()
                .onAppear() {
                    isVideo = false
                }
        }
    }
}

以及所需的扩展:

extension URL {
    func mimeType() -> String {
         let pathExtension = self.pathExtension
         if let uti = UTTypeCreatePreferredIdentifierForTag(kUTTagClassFilenameExtension, pathExtension as NSString, nil)?.takeRetainedValue() {
             if let mimetype = UTTypeCopyPreferredTagWithClass(uti, kUTTagClassMIMEType)?.takeRetainedValue() {
                return mimetype as String
             }
         }
         return "application/octet-stream"
    }

    var containsImage: Bool {
        let mimeType = self.mimeType()
        guard let uti = UTTypeCreatePreferredIdentifierForTag(kUTTagClassMIMEType, mimeType as CFString, nil)?.takeRetainedValue() else {
             return false
        }
        return UTTypeConformsTo(uti, kUTTypeImage)
    }

    var containsAudio: Bool {
        let mimeType = self.mimeType()
        guard let uti = UTTypeCreatePreferredIdentifierForTag(kUTTagClassMIMEType, mimeType as CFString, nil)?.takeRetainedValue() else {
              return false
        }
        return UTTypeConformsTo(uti, kUTTypeAudio)
    }
    
    var containsVideo: Bool {
        let mimeType = self.mimeType()
        guard  let uti = UTTypeCreatePreferredIdentifierForTag(kUTTagClassMIMEType, mimeType as CFString, nil)?.takeRetainedValue() else {
               return false
        }
        return UTTypeConformsTo(uti, kUTTypeMovie)
    }
 }

标签: swiftuiparent-childhierarchygesturesimultaneous

解决方案


推荐阅读