【问题标题】:SwiftUI Full-Screen UIImagePickerController (Camera)SwiftUI 全屏 UIImagePickerController(相机)
【发布时间】:2020-04-22 21:54:49
【问题描述】:

我通过在sheet 修饰符中使用逻辑来在我的应用程序中呈现UIImagePickerController。简而言之,以下三种类型处理在 UIViewControllerRepresentable 类型内显示和关闭 UIImagePickerController 的实例,这可以按预期工作:

struct DetailsView: View {

    enum Sheet: Hashable, Identifiable {
        case takePhoto

        var id: Int { hashValue }
    }

    @State private var activeSheet: Sheet?

    var body: some View {
        Text("Hello, World!")
            .sheet(item: $activeSheet) { (sheet) in self.view(for: sheet) }
    }

    private func view(for sheet: Sheet) -> some View {
        switch sheet {
        case .takePhoto: return PhotoSelectionView(showImagePicker: .init(get: { sheet == .takePhoto }, set: { (show) in self.activeSheet = show ? .takePhoto : nil }), image: $selectedImage, photoSource: .camera).edgesIgnoringSafeArea(.all)
        }
    }

}
struct ImagePicker: UIViewControllerRepresentable {

    @Binding var isShown: Bool

    @Binding var image: Image?

    let photoSource: PhotoSource

    func makeCoordinator() -> ImagePickerCoordinator {
        return ImagePickerCoordinator(isShown: $isShown, selectedImage: $image)
    }

    func updateUIViewController(_ uiViewController: UIImagePickerController, context: UIViewControllerRepresentableContext<ImagePicker>) {

    } 

    func makeUIViewController(context: UIViewControllerRepresentableContext<ImagePicker>) -> UIImagePickerController {
        let imagePicker = UIImagePickerController()
        if photoSource == .camera, UIImagePickerController.isSourceTypeAvailable(.camera) {
            imagePicker.sourceType = .camera
            imagePicker.cameraCaptureMode = .photo
        }
        imagePicker.delegate = context.coordinator
        return imagePicker
    }
}
class ImagePickerCoordinator: NSObject, UINavigationControllerDelegate, UIImagePickerControllerDelegate {

    @Binding private var isShown: Bool

    @Binding private var selectedImage: Image?

    init(isShown: Binding<Bool>, selectedImage: Binding<Image?>) {
        _isShown = isShown
        _selectedImage = selectedImage
    }

    func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) {
        // handle photo selection 
    }

    func imagePickerControllerDidCancel(_ picker: UIImagePickerController) {
        dismiss()
    }

}

我遇到的问题是相机视图是模态显示的,它没有覆盖整个屏幕。这会导致UIImagePickerController 有时在相机是源时出现布局损坏,就好像相机不是以这种方式呈现的一样。设置imagePicker.modalPresentationStyle = .fullScreen 不会导致全屏演示。

如何以全屏布局显示相机,使其不会出现在卡片式演示样式中?

【问题讨论】:

  • 在非 SwiftUI 应用程序中,您可以通过设置所呈现视图的 modalPresentationStyle 来控制它。但这不适用于sheet。没有地方可以指定演示样式(并且尝试在UIImagePickerController 上设置它不起作用)。请参阅stackoverflow.com/a/58970681/1271826 了解可能的解决方法。
  • 只是一个友好的建议:将来如果您可以发布MCVE 可能会很有用。像PhotoSelectionView 和PhotoSource 这样的东西在这里没有定义,这使得很难表现出问题,从而推断出发生了什么。如果您共享足够的代码来重现相关问题,您将来可能会收到更多回复...
  • @Rob,您提供的 URL 很有帮助,因为我错过了 UIHostingController 可用于表示 SwiftUI 视图层次结构的概念。另外,我很欣赏创建 MCVE 的建议。我应该从我的原始代码示例中删除 PhotoSelectionView 和 PhotoSource。
  • 在 SwiftUI 中没有简单的方法来显示全屏 UIImagePicker 真是太疯狂了

标签: swiftui uiimagepickercontroller


【解决方案1】:

结合@LaX 和@GrandSteph 的答案,我有:

.fullScreenCover(isPresented: $activeSheet, content: {
    ImagePicker(image: $inputImage, sourceType: .camera)
       .edgesIgnoringSafeArea(.all)
 })

【讨论】:

    【解决方案2】:

    在 iOS 14 中,Apple 添加了 fullScreenCover(ispresented:ondismiss:content:) 和 fullScreenCover(item:ondismiss:content:) 方法,它们完全符合您的要求。

    从你的例子:

        var body: some View {
            Text("Hello, World!")
                .fullScreenCover(item: $activeSheet) { (sheet) in self.view(for: sheet) }
        }
    

    或者,如果您只是想展示一个视图:

       @State var customViewIsShown = false
    
        // ...
    
        var body: some View {
            Text("Hello, World!")
            .fullScreenCover(isPresented: $customViewIsShown) {
                YourCustomView(isShown: $customViewIsShown)
            }
        }
    

    【讨论】:

      【解决方案3】:

      好的,对这个答案持保留态度。因此,我可能会因为这个以及我所有的程序员孩子和我一起被投下地狱……但 Apple 也应该如此,因为它没有提供一种在 SwiftUI 中呈现全屏 UIImagePickerController 的简单方法。

      非常糟糕的诀窍是在 rootView 中创建您的选择器并让它忽略安全区域。然后将所有必要的参数作为绑定传递给需要 imagePicker 的视图

      struct mainView: View {
      
          @State private var imagePicked = UIImage()
          @State private var showImagePicker = false
          @State private var pickerSource = UIImagePickerController.SourceType.camera
      
          var body: some View {
              ZStack {
                  AvatarView(showImagePicker: self.$showImagePicker, pickerSource: self.$pickerSource , imagePicked: self.$imagePicked)
      
                  if self.showImagePicker {
                      ImagePickerView(isPresented: self.$showImagePicker, selectedImage: self.$imagePicked, source: .camera).edgesIgnoringSafeArea(.all)
                  }
              }
          }
      }
      

      当然,您的 Avatar 视图将包含更新这些绑定所需的所有代码。像这样的

      HStack () {
          Button(action: {
              self.showActionSheet.toggle()
          }) {
              MyImageView(image: self.imagePicked)
          }
          .actionSheet(isPresented: $showActionSheet, content: {
              ActionSheet(title: Text("Picture source"), buttons: [
                  .default(Text("Camera"), action: {
                      self.pickerSource = .camera
                      self.showImagePicker.toggle()
                  }),
                  .default(Text("Photo Library"), action: {
                      self.pickerSource = .photoLibrary
                      self.showImagePicker.toggle()
                  }),
                  .destructive(Text("Cancel"))
              ])
          })
      }
      

      老实说,我对提供这个解决方案犹豫不决,这段代码让我眼花缭乱,但我想有人在阅读这篇文章时可能会有更好的主意,并提供一种真正干净的 SwiftUI 方法。

      这个解决方案的好处是它可以很好地管理方向的变化,让我们面对现实吧,UIImagePickerController 不适合工作表。照片库可以,相机不行。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多