问题
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 photos
If I change [navigationController.viewControllers count] == 3 --> [navigationController.viewControllers count] == 1 works for camera too, but not in next view (preview view where you accept to use the photo)
Someone help me??
-(void)actionSheet:(UIActionSheet *)actionSheet clickedButtonAtIndex:(NSInteger)buttonIndex{
if (buttonIndex == 0) {
NSLog(@"Camara");
UIImagePickerController * imagePicker = [[UIImagePickerController alloc] init];
imagePicker.allowsEditing = YES;
imagePicker.sourceType = UIImagePickerControllerSourceTypeCamera;
imagePicker.delegate = self;
self.isCamera = YES;
[self presentViewController:imagePicker animated:YES completion:nil];
}else{
NSLog(@"Carrete");
UIImagePickerController *imagePickerController = [[UIImagePickerController alloc]init];
imagePickerController.allowsEditing = YES;
imagePickerController.delegate = self;
imagePickerController.sourceType = UIImagePickerControllerSourceTypePhotoLibrary;
self.isCamera = NO;
[self presentViewController:imagePickerController animated:YES completion:nil];
}
}
- (void)navigationController:(UINavigationController *)navigationController didShowViewController:(UIViewController *)viewController animated:(BOOL)animated{
if (self.isCamera) {
if ([navigationController.viewControllers count] == 1)
{
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];
}
}else{
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];
}
}
}
回答1:
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:
In order to get overlay working properly on Camera, I was listening to notifications (taken & rejecting picture) due to add or remove circle overlay
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)
}
}
回答2:
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];
}
}
来源:https://stackoverflow.com/questions/28365819/ios-custom-uiimagepickercontroller-camera-crop-to-circle-in-preview-view