SwiftUI全屏UIImagePickerController(相机)。

问题描述 投票:1回答:1

我提出一个 UIImagePickerController 在我的应用程序中,通过在一个 sheet 修饰符。简而言之,以下三种类型处理了显示和驳回一个 UIImagePickerControllerUIViewControllerRepresentable 类型,工作正常。

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 不会导致全屏显示。

Screenshot of UIImagePickerController with a camera source

如何在全屏布局中显示摄像头,使其不出现卡片式的展示方式?

swiftui uiimagepickercontroller
1个回答
0
投票

好吧,请带着大把的盐分接受这个答案。我可能会因此而被降权到地狱,我所有的编码孩子和我一起 ... 但苹果也应该为没有在SwiftUI中提供一个简单的方法来全屏显示一个UIImagePickerController而负责。

糟透了 诀窍是在rootView中创建你的picker,并让它忽略安全区域,然后将所有必要的参数作为绑定传给需要imagePicker的视图。然后将所有必要的参数作为绑定传递给需要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)
            }
        }
    }
}

当然,你的头像视图会有所有必要的代码来更新这些绑定。就像这样

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并不能很好地适应一个工作表。对于照片库来说,它很好,但对于相机来说就不行了。

© www.soinside.com 2019 - 2024. All rights reserved.