iOS Custom UIImagePickerController Camera Crop to circle - in preview view

后端 未结 4 653
花落未央
花落未央 2020-12-20 08:45

I\'m using this code to make a custom camera crop:

UIImagePickerController editing view circle overlay

This works perfectly in camera roll but not taking pho

相关标签:
4条回答
  • 2020-12-20 09:16
    extension ProfileViewController: UIImagePickerControllerDelegate, UINavigationControllerDelegate {
    
    func navigationController(_ navigationController: UINavigationController, didShow viewController: UIViewController, animated: Bool) {
        guard imagePickerController?.sourceType == .camera else {
            return
        }
    
        guard let view = viewController.view.subviews(deep: true, where: {
            String(describing: type(of:$0)) == "CAMPreviewView"
        }).first else {
            return
        }
    
        viewController.view.layoutIfNeeded()
    
        let camPreviewBounds = view.bounds
        let circleRect = CGRect(
            x: camPreviewBounds.minX + (camPreviewBounds.width - 320) * 0.5,
            y: camPreviewBounds.minY + (camPreviewBounds.height - 320) * 0.5,
            width: 320,
            height: 320
        )
    
        let path = UIBezierPath(roundedRect: camPreviewBounds, cornerRadius: 0)
        path.append(UIBezierPath(ovalIn: circleRect))
    
        let layer = CAShapeLayer()
        layer.path = path.cgPath
        layer.fillRule = CAShapeLayerFillRule.evenOdd;
        layer.fillColor = UIColor.black.cgColor
        layer.opacity = 0.8;
    
        view.layer.addSublayer(layer)
    }
    }
    
    0 讨论(0)
  • 2020-12-20 09:20

    Although I believe that my reply might be too late, I ended it up mixing my solution with this one: https://gist.github.com/hamin/e8c6dfe00d9c81375f3e, where:

    1. In order to get overlay working properly on Camera, I was listening to notifications (taken & rejecting picture) due to add or remove circle overlay

    2. Kept the solution mentioned above where I need to loop through UINavigationController and draw circle overlay when it was requested to.

    To sum up, please find below my solution written in Swift:

    public class CustomPicture: NSObject {
    //MARK: - Properties
    private var myPickerController: UIImagePickerController?
    private var plCropOverlayBottomBar: UIView?
    private var customLayer: CAShapeLayer?
    
    //MARK: - Constants
    private let screenHeight = UIScreen.mainScreen().bounds.size.height
    private let screenWidth = UIScreen.mainScreen().bounds.size.width
    private let kCameraNotificationIrisAnimationEnd = "_UIImagePickerControllerUserDidCaptureItem"
    private let kCameraNotificationUserRejection = "_UIImagePickerControllerUserDidRejectItem"
    private let kPUUIImageViewController = "PUUIImageViewController"
    private let kPLUIImageViewController = "PLUIImageViewController"
    private let kPLCropOverlayCropView = "PLCropOverlayCropView"
    private let kPLCropOverlayBottomBar = "PLCropOverlayBottomBar"
    
    //MARK: - Overrides
    deinit {
        NSNotificationCenter.defaultCenter().removeObserver(self)
    }
    
    //MARK: - Privates
    private func camera() {
        listenToCameraNotifications()
        let myPickerController = UIImagePickerController()
    
        myPickerController.delegate = self
        myPickerController.sourceType = .Camera
        myPickerController.allowsEditing = true
    
        self.myPickerController = myPickerController
    
        self.navigationController?.presentViewController(myPickerController, animated: true, completion: nil)
    }
    
    private func listenToCameraNotifications() {
        NSNotificationCenter.defaultCenter().addObserver(self, selector: #selector(cameraNotificationIrisEnd), name: kCameraNotificationIrisAnimationEnd, object: nil)
    
        NSNotificationCenter.defaultCenter().addObserver(self, selector: #selector(cameraNotificationRejected), name: kCameraNotificationUserRejection, object: nil)
    }
    
    private func photoLibrary() {
        let myPickerController = UIImagePickerController()
    
        myPickerController.delegate = self
        myPickerController.allowsEditing = true
        myPickerController.sourceType = .PhotoLibrary
    
        self.myPickerController = myPickerController
    
        self.navigationController?.presentViewController(myPickerController, animated: true, completion: nil)
    }
    
    //MARK: - Selector
    /**
     Listen to notification sent after reject button has been touched
     */
    func cameraNotificationRejected() {
        customLayer!.removeFromSuperlayer()
        plCropOverlayBottomBar!.removeFromSuperview()
    }
    
    /**
     Listen to notification sent after picture has been taken
     */
    func cameraNotificationIrisEnd() {
        addCircleOverlay(viewController: self.myPickerController!)
    }
    }
    
    extension CustomPicture: UINavigationControllerDelegate {
    //MARK: - Override
    public func navigationController(navigationController: UINavigationController, willShowViewController: UIViewController, animated: Bool) {
        if isImageViewer(navigationController: navigationController) {
            addCircleOverlay(viewController: willShowViewController)
        }
    }
    
    //MARK: - Private
    private func addCircleOverlay(viewController viewController: UIViewController) {
        hidePLCropOverlay(view: viewController.view)
        setPLCropOverlayBottomBar(view: viewController.view)
        setCustomLayer(viewController: viewController)
    }
    
    private func getCirclePath() -> UIBezierPath {
        let circlePath = UIBezierPath(ovalInRect: CGRectMake(0, screenHeight / 2 - screenWidth / 2, screenWidth, screenWidth))
        circlePath.usesEvenOddFillRule = true
    
        let circleLayer = CAShapeLayer()
        circleLayer.path = circlePath.CGPath
        circleLayer.fillColor = UIColor.clearColor().CGColor
    
        return circlePath
    }
    
    private func getMaskPath(screenWidth screenWidth: CGFloat, screenHeight: CGFloat, circlePath: UIBezierPath) -> UIBezierPath {
        let maskPath = UIBezierPath(roundedRect: CGRectMake(0, 0, screenWidth, screenHeight), cornerRadius: 0)
        maskPath.appendPath(circlePath)
        maskPath.usesEvenOddFillRule = true
    
        return maskPath
    }
    
    private func hidePLCropOverlay(view view: UIView) {
        for myView in view.subviews {
            if myView.isKindOfClass(NSClassFromString(kPLCropOverlayCropView)!) {
                myView.hidden = true
                break
            } else {
                hidePLCropOverlay(view: myView as UIView)
            }
        }
    }
    
    private func isImageViewer(navigationController navigationController: UINavigationController) -> Bool {
        if (navigationController.viewControllers.count == 3 &&
            (navigationController.viewControllers[2].dynamicType.description() == kPUUIImageViewController ||
                navigationController.viewControllers[2].dynamicType.description() == kPLUIImageViewController)) {
    
            return true
        }
    
        return false
    }
    
    private func setPLCropOverlayBottomBar(view view: UIView) {
        for myView in view.subviews {
            if myView.isKindOfClass(NSClassFromString(kPLCropOverlayBottomBar)!) {
                plCropOverlayBottomBar = myView
                break
            }
            else {
                savePLCropOverlayBottomBar(view: myView as UIView)
            }
        }
    }
    
    private func setCustomLayer(viewController viewController: UIViewController) {
        let circlePath = getCirclePath()
        let maskPath = getMaskPath(screenWidth: screenWidth, screenHeight: screenHeight, circlePath: circlePath)
        let maskLayer = CAShapeLayer()
        maskLayer.path = maskPath.CGPath
        maskLayer.fillRule = kCAFillRuleEvenOdd
        maskLayer.fillColor = UIColor.blackColor().colorWithAlphaComponent(0.8).CGColor
        customLayer = maskLayer
    
        viewController.view.layer.addSublayer(customLayer!)
        viewController.view.addSubview(plCropOverlayBottomBar!) // put back overlayBottomBar once we set its parent to hidden (subview of PLCropOverlay)
    }
    }
    
    0 讨论(0)
  • 2020-12-20 09:21

    Here is the solution which might help you to create crop overlay:-

    - (void)navigationController:(UINavigationController *)navigationController didShowViewController:(UIViewController *)viewController animated:(BOOL)animated
    {
        if ([navigationController.viewControllers count] == 3)
        {
            CGFloat screenHeight = [[UIScreen mainScreen] bounds].size.height;
    
            UIView *plCropOverlay = [[[viewController.view.subviews objectAtIndex:1]subviews] objectAtIndex:0];
    
            plCropOverlay.hidden = YES;
    
            int position = 0;
    
            if (screenHeight == 568)
            {
                position = 124;
            }
            else
            {
                position = 80;
            }
    
            CAShapeLayer *circleLayer = [CAShapeLayer layer];
    
            UIBezierPath *path2 = [UIBezierPath bezierPathWithOvalInRect:
                                   CGRectMake(0.0f, position, 320.0f, 320.0f)];
            [path2 setUsesEvenOddFillRule:YES];
    
            [circleLayer setPath:[path2 CGPath]];
    
            [circleLayer setFillColor:[[UIColor clearColor] CGColor]];
            UIBezierPath *path = [UIBezierPath bezierPathWithRoundedRect:CGRectMake(0, 0, 320, screenHeight-72) cornerRadius:0];
    
            [path appendPath:path2];
            [path setUsesEvenOddFillRule:YES];
    
            CAShapeLayer *fillLayer = [CAShapeLayer layer];
            fillLayer.path = path.CGPath;
            fillLayer.fillRule = kCAFillRuleEvenOdd;
            fillLayer.fillColor = [UIColor blackColor].CGColor;
            fillLayer.opacity = 0.8;
            [viewController.view.layer addSublayer:fillLayer];
    
            UILabel *moveLabel = [[UILabel alloc]initWithFrame:CGRectMake(0, 10, 320, 50)];
            [moveLabel setText:@"Move and Scale"];
            [moveLabel setTextAlignment:NSTextAlignmentCenter];
            [moveLabel setTextColor:[UIColor whiteColor]];
    
            [viewController.view addSubview:moveLabel];
        }
    }
    
    0 讨论(0)
  • 2020-12-20 09:23

    Similar solution in SwiftUI, Swift 5

    I banged my head on this for a long, long time, but finally have a solution that works.

    I've not been coding in Swift or SwiftUI for long, and I absolutely welcome comments to improve this code. In some places, I've left in a bit of Debugging code you can uncomment. Wrapping my head around the math involved more trial and error than competent, well-thought out approaches!

    Shortcomings in this code: first, it would be nice to open the Impage picker from ContentView() and then show my custom view. I don't know how to do that. Second, if there is already an image in the ContentView(), it would be nice to populate the image in the custom view. However, then the user may expect to be able to get the "original" image and move it and scale it. That would require more than is needed for this answer. Ie, do you want to save the original photo in some url / application folder as well as the cropped version? Or even save a dictionary with the original picture and the CGRect needed to recreate the cropped view? Third. there seems to be a bug if the selected photo is exactly the size of the screen (a screenshot); it can be scaled too low.

    In a new SwiftUI lifecycle app, I have the following SwiftUI views:

    • ContentView with a UIImage binding to the subsequent
    • ImageMoveAndScaleSheet with a further UIBinding to
    • ImagePicker which is the UIViewControllerRepresentable from Hacking with Swift found here: https://www.hackingwithswift.com/books/ios-swiftui/importing-an-image-into-swiftui-using-uiimagepickercontroller

    This is what you'll get:

    I also use this crucial solution for cropping:

    • ImageManipulation.swift

    Finally, some of my code accesses system UIcolors so I use the extension in

    • Colors.swift

    ContentView

        import SwiftUI
        
        struct ContentView: View {
            
            @State private var isShowingPhotoSelectionSheet = false
    
            @State private var finalImage: UIImage?
            @State private var inputImage: UIImage?
            
            var body: some View {
                
                VStack {
                    
                    if finalImage != nil {
                        Image(uiImage: finalImage!)
                            .resizable()
                            .frame(width: 100, height: 100)
                            .scaledToFill()
                            .aspectRatio(contentMode: .fit)
                            .clipShape(Circle())
                            .shadow(radius: 4)
                    } else {
                        Image(systemName: "person.crop.circle.fill")
                            .resizable()
                            .scaledToFill()
                            .frame(width: 100, height: 100)
                            .aspectRatio(contentMode: .fit)
                            .foregroundColor(.systemGray2)
                    }
                    Button (action: {
                        self.isShowingPhotoSelectionSheet = true
                    }, label: {
                        Text("Change photo")
                            .foregroundColor(.systemRed)
                            .font(.footnote)
                    })
                }
                .background(Color.systemBackground)
                .statusBar(hidden: isShowingPhotoSelectionSheet)
                .fullScreenCover(isPresented: $isShowingPhotoSelectionSheet, onDismiss: loadImage) {
                    ImageMoveAndScaleSheet(croppedImage: $finalImage)
                }
            }
            
            func loadImage() {
                guard let inputImage = inputImage else { return }
                finalImage = inputImage
            }
        }
        
        struct ContentView_Previews: PreviewProvider {
            static var previews: some View {
                ContentView()
            }
        }
    
    

    Clicking / tapping on Change photo brings up the next view:

    ImagemoveAndScaleSheet

    This is a fullscreen modal which hides the statusbar while open.

        import SwiftUI
        
        struct ImageMoveAndScaleSheet: View {
            
            @Environment(\.presentationMode) var presentationMode
            
            @State private var isShowingImagePicker = false
    
            ///The croped image is what will will send back to the parent view.
            ///It should be the part of the image in the square defined by the
            ///cutout circle's diamter. See below, the cutout circle has an "inset" value
            ///which can be changed.
            @Binding var croppedImage: UIImage?
    
            ///The input image is received from the ImagePicker.
            ///We will need to calculate and refer to its aspectr ratio in the functions.
            @State private var inputImage: UIImage?
            @State private var inputW: CGFloat = 750.5556577
            @State private var inputH: CGFloat = 1336.5556577
            
            @State private var theAspectRatio: CGFloat = 0.0
    
            ///The profileImage is what wee see on this view. When added from the
            ///ImapgePicker, it will be sized to fit the screen,
            ///meaning either its width will match the width of the device's screen,
            ///or its height will match the height of the device screen.
            ///This is not suitable for landscape mode or for iPads.
            @State private var profileImage: Image?
            @State private var profileW: CGFloat = 0.0
            @State private var profileH: CGFloat = 0.0
            
            ///Zoom and Drag ...
            @State private var currentAmount: CGFloat = 0
            @State private var finalAmount: CGFloat = 1
            
            @State private var currentPosition: CGSize = .zero
            @State private var newPosition: CGSize = .zero
            
            ///We track of amount the image is moved for use in functions below.
            @State private var horizontalOffset: CGFloat = 0.0
            @State private var verticalOffset: CGFloat = 0.0
            
            var body: some View {
                
                ZStack {
                    ZStack {
                        Color.black.opacity(0.8)
                        if profileImage != nil {
                            profileImage?
                                .resizable()
                                .scaleEffect(finalAmount + currentAmount)
                                .scaledToFill()
                                .aspectRatio(contentMode: .fit)
                                .offset(x: self.currentPosition.width, y: self.currentPosition.height)
                        } else {
                            Image(systemName: "person.crop.circle.fill")
                                .resizable()
                                .scaleEffect(finalAmount + currentAmount)
                                .scaledToFill()
                                .aspectRatio(contentMode: .fit)
                                .foregroundColor(.systemGray2)
                        }
                    }
                    Rectangle()
                        .fill(Color.black).opacity(0.55)
                        .mask(HoleShapeMask().fill(style: FillStyle(eoFill: true)))
                    VStack {
                        Text((profileImage != nil) ? "Move and Scale" : "Select a Photo by tapping the icon below")
                            .foregroundColor(.white)
                            .padding(.top, 50)
                        Spacer()
                        HStack{
                            ZStack {
                                HStack {
                                    Button(
                                        action: {presentationMode.wrappedValue.dismiss()},
                                        label: { Text("Cancel") })
                                    Spacer()
                                    Button(
                                        action: {
                                            self.save()
                                            presentationMode.wrappedValue.dismiss()
                                            
                                        })
                                        { Text("Save") }
                                        .opacity((profileImage != nil) ? 1.0 : 0.2)
                                        .disabled((profileImage != nil) ? false: true)
                                        
                                }
                                .padding(.horizontal)
                                .foregroundColor(.white)
                                Image(systemName: "circle.fill")
                                    .font(.custom("system", size: 45))
                                    .opacity(0.9)
                                    .foregroundColor(.white)
                                Image(systemName: "photo.on.rectangle")
                                    .imageScale(.medium)
                                    .foregroundColor(.black)
                                    .onTapGesture {
                                        isShowingImagePicker = true
                                    }
                            }
                            .padding(.bottom, 5)
                        }
                    }
                    .padding()
                }
                .edgesIgnoringSafeArea(.all)
                
                //MARK: - Gestures
                
                .gesture(
                    MagnificationGesture()
                        .onChanged { amount in
                            self.currentAmount = amount - 1
                            //                    repositionImage()
                        }
                        .onEnded { amount in
                            self.finalAmount += self.currentAmount
                            self.currentAmount = 0
                            repositionImage()
                        }
                )
                .simultaneousGesture(
                    DragGesture()
                        .onChanged { value in
                            self.currentPosition = CGSize(width: value.translation.width + self.newPosition.width, height: value.translation.height + self.newPosition.height)
                        }
                        .onEnded { value in
                            self.currentPosition = CGSize(width: value.translation.width + self.newPosition.width, height: value.translation.height + self.newPosition.height)
                            self.newPosition = self.currentPosition
                            repositionImage()
                        }
                )
                .simultaneousGesture(
                    TapGesture(count: 2)
                        .onEnded({
                            resetImageOriginAndScale()
                        })
                )
                .sheet(isPresented: $isShowingImagePicker, onDismiss: loadImage) {
                    ImagePicker(image: self.$inputImage)
                        .accentColor(Color.systemRed)
                }
            }
            
            //MARK: - functions
            
            private func HoleShapeMask() -> Path {
                let rect = CGRect(x: 0, y: 0, width: UIScreen.main.bounds.width, height: UIScreen.main.bounds.height)
                let insetRect = CGRect(x: inset, y: inset, width: UIScreen.main.bounds.width - ( inset * 2 ), height: UIScreen.main.bounds.height - ( inset * 2 ))
                var shape = Rectangle().path(in: rect)
                shape.addPath(Circle().path(in: insetRect))
                return shape
            }
            
            ///Called when the ImagePicker is dismissed.
            ///We want to measure the image receoived and determine the aspect ratio.
            
            private func loadImage() {
                guard let inputImage = inputImage else { return }
                let w = inputImage.size.width
                let h = inputImage.size.height
                profileImage = Image(uiImage: inputImage)
                
                inputW = w
                inputH = h
                theAspectRatio = w / h
                
                resetImageOriginAndScale()
            }
            
            ///The profileImage will size to fit the screen.
            ///But we need to know the width and height
            ///to set the related @State variables.
            ///Douobke-tpping the image will also set it
            ///as it was sized originally upon loading.
            private func resetImageOriginAndScale() {
                withAnimation(.easeInOut){
                    if theAspectRatio >= screenAspect {
                        profileW = UIScreen.main.bounds.width
                        profileH = profileW / theAspectRatio
                    } else {
                        profileH = UIScreen.main.bounds.height
                        profileW = profileH * theAspectRatio
                    }
                    currentAmount = 0
                    finalAmount = 1
                    currentPosition = .zero
                    newPosition = .zero
                }
            }
            
            
            private func repositionImage() {
                
                //Screen width
                let w = UIScreen.main.bounds.width
                
                if theAspectRatio > screenAspect {
                    profileW = UIScreen.main.bounds.width * finalAmount
                    profileH = profileW / theAspectRatio
                } else {
                    profileH = UIScreen.main.bounds.height * finalAmount
                    profileW = profileH * theAspectRatio
                }
    
                horizontalOffset = (profileW - w ) / 2
                verticalOffset = ( profileH - w ) / 2
                
                
                ///Keep the user from zooming too far in. Adjust as required by the individual project.
                if finalAmount > 4.0 {
                    withAnimation{
                        finalAmount = 4.0
                    }
                }
                
                ///The following if statements keep the image filling the circle cutout.
                if profileW >= UIScreen.main.bounds.width {
                    
                    if newPosition.width > horizontalOffset {
                        withAnimation(.easeInOut) {
                            newPosition = CGSize(width: horizontalOffset + inset, height: newPosition.height)
                            currentPosition = CGSize(width: horizontalOffset + inset, height: currentPosition.height)
                        }
                    }
                    
                    if newPosition.width < ( horizontalOffset * -1) {
                        withAnimation(.easeInOut){
                            newPosition = CGSize(width: ( horizontalOffset * -1) - inset, height: newPosition.height)
                            currentPosition = CGSize(width: ( horizontalOffset * -1 - inset), height: currentPosition.height)
                        }
                    }
                } else {
                    
                    withAnimation(.easeInOut) {
                        newPosition = CGSize(width: 0, height: newPosition.height)
                        currentPosition = CGSize(width: 0, height: newPosition.height)
                    }
                }
                
                if profileH >= UIScreen.main.bounds.width {
                    
                    if newPosition.height > verticalOffset {
                        withAnimation(.easeInOut){
                            newPosition = CGSize(width: newPosition.width, height: verticalOffset + inset)
                            currentPosition = CGSize(width: newPosition.width, height: verticalOffset + inset)
                        }
                    }
                    
                    if newPosition.height < ( verticalOffset * -1) {
                        withAnimation(.easeInOut){
                            newPosition = CGSize(width: newPosition.width, height: ( verticalOffset * -1) - inset)
                            currentPosition = CGSize(width: newPosition.width, height: ( verticalOffset * -1) - inset)
                        }
                    }
                } else {
                    
                    withAnimation (.easeInOut){
                        newPosition = CGSize(width: newPosition.width, height: 0)
                        currentPosition = CGSize(width: newPosition.width, height: 0)
                    }
                }
                
                if profileW <= UIScreen.main.bounds.width && theAspectRatio > screenAspect {
                    resetImageOriginAndScale()
                }
                if profileH <= UIScreen.main.bounds.height && theAspectRatio < screenAspect {
                    resetImageOriginAndScale()
                }
            }
            
            private func save() {
                
                let scale = (inputImage?.size.width)! / profileW
                
                let xPos = ( ( ( profileW - UIScreen.main.bounds.width ) / 2 ) + inset + ( currentPosition.width * -1 ) ) * scale
                let yPos = ( ( ( profileH - UIScreen.main.bounds.width ) / 2 ) + inset + ( currentPosition.height * -1 ) ) * scale
                let radius = ( UIScreen.main.bounds.width - inset * 2 ) * scale
                
                croppedImage = imageWithImage(image: inputImage!, croppedTo: CGRect(x: xPos, y: yPos, width: radius, height: radius))
                
                ///Debug maths
                print("Input: w \(inputW) h \(inputH)")
                print("Profile: w \(profileW) h \(profileH)")
                print("X Origin: \( ( ( profileW - UIScreen.main.bounds.width - inset ) / 2 ) + ( currentPosition.width  * -1 ) )")
                print("Y Origin: \( ( ( profileH - UIScreen.main.bounds.width - inset) / 2 ) + ( currentPosition.height  * -1 ) )")
                
                print("Scale: \(scale)")
                print("Profile:\(profileW) + \(profileH)" )
                print("Curent Pos: \(currentPosition.debugDescription)")
                print("Radius: \(radius)")
                print("x:\(xPos), y:\(yPos)")
            }
            
            let inset: CGFloat = 15
            let screenAspect = UIScreen.main.bounds.width / UIScreen.main.bounds.height
        }
    
    

    Apart from the drag and scale gestures, the main things to look and (and probably clean up!) are the functions.

    • HoleShapeMask() (cannot remember where that code is, but I know I got it on SO.
    • repositionImage() (much headbanging here)
    • save() which uses the funciton in the ImageManipulation.swift file.

    ImagePicker

    Again, this is simply from Hacking With Swift. (Thanks Paul!) https://twitter.com/twostraws/

        import SwiftUI
    
        struct ImagePicker: UIViewControllerRepresentable {
            
            @Environment(\.presentationMode) var presentationMode
            @Binding var image: UIImage?
            
            class Coordinator: NSObject, UINavigationControllerDelegate, UIImagePickerControllerDelegate {
                let parent: ImagePicker
                
                init(_ parent: ImagePicker) {
                    self.parent = parent
                }
                
                func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) {
                    if let uiImage = info[.originalImage] as? UIImage {
                        parent.image = uiImage
                    }
                    parent.presentationMode.wrappedValue.dismiss()
                }
            }
    
            func makeCoordinator() -> Coordinator {
                Coordinator(self)
            }
            
            func makeUIViewController(context: UIViewControllerRepresentableContext<ImagePicker>) -> UIImagePickerController {
                let picker = UIImagePickerController()
                picker.delegate = context.coordinator
                return picker
            }
    
            func updateUIViewController(_ uiViewController: UIImagePickerController, context: UIViewControllerRepresentableContext<ImagePicker>) {
    
            }
        }
    

    ImageManipulation.swift

    This contains the following code:

        import UIKit
    
        func imageWithImage(image: UIImage, croppedTo rect: CGRect) -> UIImage {
    
            UIGraphicsBeginImageContext(rect.size)
            let context = UIGraphicsGetCurrentContext()
    
            let drawRect = CGRect(x: -rect.origin.x, y: -rect.origin.y,
                                  width: image.size.width, height: image.size.height)
    
            context?.clip(to: CGRect(x: 0, y: 0,
                                     width: rect.size.width, height: rect.size.height))
    
            image.draw(in: drawRect)
    
            let subImage = UIGraphicsGetImageFromCurrentImageContext()
    
            UIGraphicsEndImageContext()
            return subImage!
        }
    
    ## Colors.swift ##
    
    A handy extension to access system UIColors in SwiftUI:
    
        import Foundation
        import SwiftUI
    
        extension Color {
    
            static var label: Color {
                return Color(UIColor.label)
            }
    
            static var secondaryLabel: Color {
                return Color(UIColor.secondaryLabel)
            }
    
            static var tertiaryLabel: Color {
                return Color(UIColor.tertiaryLabel)
            }
    
            static var quaternaryLabel: Color {
                return Color(UIColor.quaternaryLabel)
            }
    
            static var systemFill: Color {
                return Color(UIColor.systemFill)
            }
    
            static var secondarySystemFill: Color {
                return Color(UIColor.secondarySystemFill)
            }
    
            static var tertiarySystemFill: Color {
                return Color(UIColor.tertiarySystemFill)
            }
    
            static var quaternarySystemFill: Color {
                return Color(UIColor.quaternarySystemFill)
            }
    
            static var systemBackground: Color {
                   return Color(UIColor.systemBackground)
            }
    
            static var secondarySystemBackground: Color {
                return Color(UIColor.secondarySystemBackground)
            }
    
            static var tertiarySystemBackground: Color {
                return Color(UIColor.tertiarySystemBackground)
            }
    
            static var systemGroupedBackground: Color {
                return Color(UIColor.systemGroupedBackground)
            }
    
            static var secondarySystemGroupedBackground: Color {
                return Color(UIColor.secondarySystemGroupedBackground)
            }
    
            static var tertiarySystemGroupedBackground: Color {
                return Color(UIColor.tertiarySystemGroupedBackground)
            }
    
            static var systemRed: Color {
                return Color(UIColor.systemRed)
            }
    
            static var systemBlue: Color {
                return Color(UIColor.systemBlue)
            }
    
            static var systemPink: Color {
                return Color(UIColor.systemPink)
            }
    
            static var systemTeal: Color {
                return Color(UIColor.systemTeal)
            }
    
            static var systemGreen: Color {
                return Color(UIColor.systemGreen)
            }
    
            static var systemIndigo: Color {
                return Color(UIColor.systemIndigo)
            }
    
            static var systemOrange: Color {
                return Color(UIColor.systemOrange)
            }
    
            static var systemPurple: Color {
                return Color(UIColor.systemPurple)
            }
    
            static var systemYellow: Color {
                return Color(UIColor.systemYellow)
            }
    
            static var systemGray: Color {
                return Color(UIColor.systemGray)
            }
    
            static var systemGray2: Color {
                return Color(UIColor.systemGray2)
            }
    
            static var systemGray3: Color {
                return Color(UIColor.systemGray3)
            }
    
            static var systemGray4: Color {
                return Color(UIColor.systemGray4)
            }
    
            static var systemGray5: Color {
                return Color(UIColor.systemGray5)
            }
    
            static var systemGray6: Color {
                return Color(UIColor.systemGray6)
            }
            
        }
    
    
    
    0 讨论(0)
提交回复
热议问题