Perform “use photo” button on custom image picker

2020-02-06 08:05发布

问题:

I am creating fully custom overlay for image picker controller. First stage is easy: I am get first view with record/take a shot button, which call takePicture() method.

Next stage is change UI to "Retake" or "Use photo" which is also with my own design. "Retake" probably can be imitated by calling presentViewController again. How should I imitate "Use photo" button?

回答1:

You can easily inherit UIImagePickerController

Objective-C

@interface CameraViewController : UIImagePickerController

@property (readwrite, nonatomic) NSInteger state; // 0 - auto 1 - on 2 - off

@end

@implementation CameraViewController

- (instancetype)init {
    self = [super init];
    if (self) {
        if (!TARGET_IPHONE_SIMULATOR) {
            self.sourceType = UIImagePickerControllerSourceTypeCamera;
            self.showsCameraControls = NO;
            self.cameraCaptureMode = UIImagePickerControllerCameraCaptureModePhoto;
        } else {
            self.sourceType = UIImagePickerControllerSourceTypePhotoLibrary;
        }
        self.modalPresentationStyle = UIModalPresentationFullScreen;
        self.modalTransitionStyle = UIModalTransitionStyleCrossDissolve;
        self.allowsEditing = NO;
        self.mediaTypes = @[(NSString *)kUTTypeImage];
        [[UIDevice currentDevice] beginGeneratingDeviceOrientationNotifications];
        [[NSNotificationCenter defaultCenter] addObserver:self
                                                 selector:@selector(orientationChanged)
                                                     name:UIDeviceOrientationDidChangeNotification
                                                   object:nil];

    }
    return self;
}

- (void)dealloc {
    [[NSNotificationCenter defaultCenter] removeObserver:self];
}

@end

Then override viewDidLoad and customize UI to your needs by creating UIView object and set it to self.cameraOverlayView. In my example it is custom flash button.

- (void)viewDidLoad {
    [super viewDidLoad];

    UIView *view = [[UIView alloc] initWithFrame:self.view.bounds];
    view.backgroundColor = [UIColor clearColor];
    UIButton *changeFlashButton = [UIButton buttonWithType:UIButtonTypeCustom];
    changeFlashButton.frame = CGRectMake(70, 27, 40, 40);
    [changeFlashButton setImage:[UIImage imageNamed:@"flash_auto"] forState:UIControlStateNormal];
    self.cameraFlashMode = UIImagePickerControllerCameraFlashModeAuto;
    changeFlashButton.showsTouchWhenHighlighted = YES;
    [changeFlashButton addTarget:self action:@selector(changeFlashValue:) forControlEvents:UIControlEventTouchUpInside];
    [view addSubview:changeFlashButton];
    if (!TARGET_IPHONE_SIMULATOR) {
        self.cameraFlashMode = UIImagePickerControllerCameraFlashModeAuto;
        changeFlashButton.alpha = [[self class] isFlashAvailableForCameraDevice:self.cameraDevice];
        self.cameraOverlayView = view;
    }
}

- (void)changeFlashValue:(UIButton*)aSwitch {
    if (self.state == 0) { //auto - on
        self.state = 1;
        [self.flashSwitch setImage:[UIImage imageNamed:@"flash_on"] forState:UIControlStateNormal];
        self.cameraFlashMode = UIImagePickerControllerCameraFlashModeOn;
        return;
    }
    if (self.state == 1) { //on - off
        self.state = 2;
        [self.flashSwitch setImage:[UIImage imageNamed:@"flash_off"] forState:UIControlStateNormal];
        self.cameraFlashMode = UIImagePickerControllerCameraFlashModeOff;
        return;
    }
    if (self.state == 2) { //off - auto
        self.state = 0;
        [self.flashSwitch setImage:[UIImage imageNamed:@"flash_auto"] forState:UIControlStateNormal];
        self.cameraFlashMode = UIImagePickerControllerCameraFlashModeAuto;
        return;
    }
}

Your controls of camera could be like this

Please pay attentions that for not showing to user "Retake" and "Use photo" buttons you need to set allowsEditing to false

And actually the same for Swift 2.2+

class CameraViewController: UIImagePickerController {

    var state: Int?

    init() {
        super.init(navigationBarClass: nil, toolbarClass: nil)
        #if (arch(i386) || arch(x86_64)) && (os(iOS) || os(watchOS) || os(tvOS)) // any simulator
            self.sourceType = .PhotoLibrary
        #else
            self.sourceType = .Camera
            self.showsCameraControls = false
            self.cameraCaptureMode = .Photo
        #endif

        self.modalPresentationStyle = .FullScreen
        self.modalTransitionStyle = .CrossDissolve
        self.allowsEditing = false
        self.mediaTypes = [UIImagePickerControllerMediaType]
        UIDevice.currentDevice().beginGeneratingDeviceOrientationNotifications()
        NSNotificationCenter.defaultCenter().addObserver(self, selector: #selector(orientationChanged), name: UIDeviceOrientationDidChangeNotification, object: nil)
    }

    // strange compiler requirements
    required init?(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }

    deinit {
        NSNotificationCenter.defaultCenter().removeObserver(self)
    }

    func orientationChanged() {
        // update to the new orientation
    }

    override func viewDidLoad() {
        super.viewDidLoad()

        let view: UIView = UIView(frame: self.view.bounds)
        view.backgroundColor = UIColor.clearColor()
        var changeFlashButton: UIButton = UIButton(type: .Custom)
        changeFlashButton.frame = CGRectMake(70, 27, 40, 40)
        changeFlashButton.setImage(UIImage(named: "flash_auto"), forState: .Normal)
        self.cameraFlashMode = .Auto
        changeFlashButton.showsTouchWhenHighlighted = true
        changeFlashButton.addTarget(self, action: #selector(changeFlashValue(_:)), forControlEvents: .TouchUpInside)
        view.addSubview(changeFlashButton)
        #if (arch(i386) || arch(x86_64)) && (os(iOS) || os(watchOS) || os(tvOS)) // any simulator
        #else
            self.cameraFlashMode = .Auto
            changeFlashButton.alpha = UIImagePickerController.isFlashAvailableForCameraDevice(self.cameraDevice) ? 1 : 0
        #endif
    }

    func changeFlashValue(aSwitch: UIButton) {
        if self.state == 0 {
            // auto - on
            self.state = 1
            self.flashSwitch.setImage(UIImage.imageNamed("flash_on"), forState: .Normal)
            self.cameraFlashMode = .On
            return
        }
        if self.state == 1 {
            // on - off
            self.state = 2
            self.flashSwitch.setImage(UIImage.imageNamed("flash_off"), forState: .Normal)
            self.cameraFlashMode = .Off
            return
        }
        if self.state == 2 {
            // off - auto
            self.state = 0
            self.flashSwitch.setImage(UIImage.imageNamed("flash_auto"), forState: .Normal)
            self.cameraFlashMode = .Auto
            return
        }
    }
}


回答2:

You can imitate use photo by presenting a view controller that gives user option to edit the taken image and adding save and cancel button as well. How does that sound?