SwiftUI Полноэкранный UIImagePickerController (Камера) - PullRequest
1 голос
/ 23 апреля 2020

Я представляю UIImagePickerController в своем приложении, представляя его с логиками c внутри модификатора sheet. Короче говоря, следующие три типа обрабатывают отображение и отклонение экземпляра UIImagePickerController внутри типа UIViewControllerRepresentable, который работает, как и ожидалось:

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

Как отобразить камеру в полноэкранном режиме, чтобы она не отображается в карточном стиле презентации?

1 Ответ

0 голосов
/ 02 мая 2020

Хорошо, примите этот ответ с большим количеством соли. Я, вероятно, буду за это осужден и за это все мои дети-кодеры со мной ... Но так же и Apple за то, что она не предоставляет простой способ представить полноэкранный UIImagePickerController в SwiftUI.

очень плохо хитрость заключается в том, чтобы создать свой инструмент выбора в 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)
            }
        }
    }
}

. Конечно, ваше представление аватара будет иметь весь необходимый код для обновления этих привязок. Что-то вроде этого

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 не умещается должным образом на листе. Это нормально для фото-библиотеки, но не для камеры.

...