首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >UIImagePickerController编辑视图圆覆盖

UIImagePickerController编辑视图圆覆盖
EN

Stack Overflow用户
提问于 2013-12-27 11:08:40
回答 5查看 11.2K关注 0票数 17

我已经能够实现我一直想要实现的目标,那就是复制iOS内置的圆形照片裁剪器,用于内置的联系人应用程序。然而,我被困在试图让我的CAShapeLayers正确。我试着做一个透明的320像素直径的圆圈,剩下的部分填充0.9阿尔法的黑色背景。圆圈和矩形在正确的位置,但是,圆圈并不像我需要的那样完全透明。

我不知道如何解决这个问题。非常感谢您的帮助!代码和截图:

代码语言:javascript
运行
复制
- (void)navigationController:(UINavigationController *)navigationController didShowViewController:(UIViewController *)viewController animated:(BOOL)animated
{
    if ([navigationController.viewControllers count] == 3)
    {
        CGRect screenRect = [[UIScreen mainScreen] bounds];
        CGFloat screenHeight = screenRect.size.height;

        UIView *plCropOverlay = [[[viewController.view.subviews objectAtIndex:1]subviews] objectAtIndex:0];

        plCropOverlay.hidden = YES;

        CAShapeLayer *circleLayer = [CAShapeLayer layer];

        if (screenHeight == 568)
        {
            [circleLayer setPosition:CGPointMake(0.0f,124.0f)];
        }    
        else
        {
            [circleLayer setPosition:CGPointMake(0.0f,80.0f)];
        }

        UIBezierPath *path = [UIBezierPath bezierPathWithOvalInRect:
                          CGRectMake(0.0f, 0.0f, 320.0f, 320.0f)];

        [circleLayer setPath:[path CGPath]];

        [circleLayer setFillColor:[[UIColor whiteColor] CGColor]];
        circleLayer.opacity = 0.7f;

        // Set to 0.7f to show for screenshot purposes; setting to 0.0 would make it invisible and blend in with the below rectangleLayer.

        CAShapeLayer *rectangleLayer = [CAShapeLayer layer];

        UIBezierPath *path2 = [UIBezierPath bezierPathWithRect:CGRectMake(0.0f, 0.0f, 320.0f, screenHeight - 72)];
        [rectangleLayer setPath:[path2 CGPath]];

        [rectangleLayer setFillColor:[[UIColor blackColor] CGColor]];
        [rectangleLayer setOpacity:0.9f];
        [rectangleLayer addSublayer:circleLayer];
        [[viewController.view layer] addSublayer:rectangleLayer];

        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];
    }
}

EN

回答 5

Stack Overflow用户

回答已采纳

发布于 2013-12-28 05:48:38

已解析代码:

代码语言:javascript
运行
复制
- (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];
    }
}
票数 14
EN

Stack Overflow用户

发布于 2015-05-19 23:41:28

我更改了@aviatorken89的代码,因为它在iPhone 6/6+和iPad上不起作用。现在,它应该可以在任何iPhone的屏幕尺寸上运行,也可以在iPad上运行!已在iOS 7和iOS 8上测试。

所有这些方法都不是真正可靠的,因为它们是基于图像拾取器的子视图层次结构的,当然,苹果可以改变它。我已经尽我所能地保护代码,以防止在未来的iOS版本中可能发生的崩溃。

我会尽量更新我的解决方案,要点是:https://gist.github.com/andreacipriani/74ea67db8f17673f1b8b

代码如下:

代码语言:javascript
运行
复制
- (void)navigationController:(UINavigationController *)navigationController didShowViewController:(UIViewController *)viewController animated:(BOOL)animated
{
    if ([navigationController.viewControllers count] == 3 && ([[[[navigationController.viewControllers objectAtIndex:2] class] description] isEqualToString:@"PUUIImageViewController"] || [[[[navigationController.viewControllers objectAtIndex:2] class] description] isEqualToString:@"PLUIImageViewController"]))

        [self addCircleOverlayToImagePicker:viewController];
    }
}

-(void)addCircleOverlayToImagePicker:(UIViewController*)viewController
{
    UIColor *circleColor = [UIColor clearColor];
    UIColor *maskColor = [[UIColor blackColor] colorWithAlphaComponent:0.8];

    CGFloat screenHeight = [[UIScreen mainScreen] bounds].size.height;
    CGFloat screenWidth = [[UIScreen mainScreen] bounds].size.width;

    UIView *plCropOverlayCropView; //The default crop overlay view, we wan't to hide it and show our circular one
    UIView *plCropOverlayBottomBar; //On iPhone this is the bar with "cancel" and "choose" buttons, on Ipad it's an Image View with a label saying "Scale and move"

    //Subviews hirearchy is different in iPad/iPhone:
    if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad){

        plCropOverlayCropView = [viewController.view.subviews objectAtIndex:1];
        plCropOverlayBottomBar = [[[[viewController.view subviews] objectAtIndex:1] subviews] objectAtIndex:1];

        //Protect against iOS changes...
        if (! [[[plCropOverlayCropView class] description] isEqualToString:@"PLCropOverlay"]){
            DLog(@"Warning - Image Picker with circle overlay: PLCropOverlay not found");
            return;
        }
        if (! [[[plCropOverlayBottomBar class] description] isEqualToString:@"UIImageView"]){
            DLog(@"Warning - Image Picker with circle overlay: BottomBar not found");
            return;
        }
    }
    else{
        plCropOverlayCropView = [[[viewController.view.subviews objectAtIndex:1] subviews] firstObject];
        plCropOverlayBottomBar = [[[[viewController.view subviews] objectAtIndex:1] subviews] objectAtIndex:1];

        //Protect against iOS changes...
        if (! [[[plCropOverlayCropView class] description] isEqualToString:@"PLCropOverlayCropView"]){
            DDLogWarn(@"Image Picker with circle overlay: PLCropOverlayCropView not found");
            return;
        }
        if (! [[[plCropOverlayBottomBar class] description] isEqualToString:@"PLCropOverlayBottomBar"]){
            DDLogWarn(@"Image Picker with circle overlay: PLCropOverlayBottomBar not found");
            return;
        }
    }

    //It seems that everything is ok, we found the CropOverlayCropView and the CropOverlayBottomBar

    plCropOverlayCropView.hidden = YES; //Hide default CropView

    CAShapeLayer *circleLayer = [CAShapeLayer layer];
    //Center the circleLayer frame:
    UIBezierPath *circlePath = [UIBezierPath bezierPathWithOvalInRect:CGRectMake(0.0f, screenHeight/2 - screenWidth/2, screenWidth, screenWidth)];
    circlePath.usesEvenOddFillRule = YES;
    circleLayer.path = [circlePath CGPath];
    circleLayer.fillColor = circleColor.CGColor;
    //Mask layer frame: it begins on y=0 and ends on y = plCropOverlayBottomBar.origin.y
    UIBezierPath *maskPath = [UIBezierPath bezierPathWithRoundedRect:CGRectMake(0, 0, screenWidth, screenHeight- plCropOverlayBottomBar.frame.size.height) cornerRadius:0];
    [maskPath appendPath:circlePath];
    maskPath.usesEvenOddFillRule = YES;

    CAShapeLayer *maskLayer = [CAShapeLayer layer];
    maskLayer.path = maskPath.CGPath;
    maskLayer.fillRule = kCAFillRuleEvenOdd;
    maskLayer.fillColor = maskColor.CGColor;
    [viewController.view.layer addSublayer:maskLayer];

    if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPhone){
        //On iPhone add an hint label on top saying "scale and move" or whatever you want
        UILabel *cropLabel = [[UILabel alloc]initWithFrame:CGRectMake(0, 10, screenWidth, 50)];
        [cropLabel setText:@"Scale and move"]; //You should localize it
        [cropLabel setTextAlignment:NSTextAlignmentCenter];
        [cropLabel setTextColor:[UIColor whiteColor]];
        [viewController.view addSubview:cropLabel];
    }
    else{ //On iPad re-add the overlayBottomBar with the label "scale and move" because we set its parent to hidden (it's a subview of PLCropOverlay)
        [viewController.view addSubview:plCropOverlayBottomBar];
    }
} 
票数 3
EN

Stack Overflow用户

发布于 2017-03-10 22:48:33

Swift 3版本(也有圆形编辑层,用于相机拍摄的照片):

代码语言:javascript
运行
复制
// Insert this code to your view controller
private var editLayer: CAShapeLayer!
private var label: UILabel!


override func viewDidLoad()
{
    super.viewDidLoad()

    // Rounded edit layer
    navigationController?.delegate = self
    NotificationCenter.default.addObserver(self, selector: #selector(pictureCaptured), name: NSNotification.Name(rawValue: "_UIImagePickerControllerUserDidCaptureItem"), object: nil)
    NotificationCenter.default.addObserver(self, selector: #selector(pictureRejected), name: NSNotification.Name(rawValue: "_UIImagePickerControllerUserDidRejectItem"), object: nil)
}


@objc private func pictureCaptured()
{
    addRoundedEditLayer(to: ...your UIImagePickerController..., forCamera: true)
}


@objc private func pictureRejected()
{
    editLayer.removeFromSuperlayer()
    label.removeFromSuperview()
}


deinit
{
    NotificationCenter.default.removeObserver(self)
}    



// MARK: Navigation controller delegate

func navigationController(_ navigationController: UINavigationController, willShow viewController: UIViewController, animated: Bool)
{
    // Image picker in edit mode
    if let imageVC = NSClassFromString("PUUIImageViewController")
    {
        if viewController.isKind(of: imageVC) {
            addRoundedEditLayer(to: viewController, forCamera: false)
        }
    }
}


private func addRoundedEditLayer(to viewController: UIViewController, forCamera: Bool)
{
    hideDefaultEditOverlay(view: viewController.view)

    // Circle in edit layer - y position
    let bottomBarHeight: CGFloat = 72.0
    let position = (forCamera) ? viewController.view.center.y - viewController.view.center.x - bottomBarHeight/2 : viewController.view.center.y - viewController.view.center.x

    let viewWidth = viewController.view.frame.width
    let viewHeight = viewController.view.frame.height

    let emptyShapePath = UIBezierPath(ovalIn: CGRect(x: 0, y: position, width: viewWidth, height: viewWidth))
    emptyShapePath.usesEvenOddFillRule = true

    let filledShapePath = UIBezierPath(roundedRect: CGRect(x: 0, y: 0, width: viewWidth, height: viewHeight - bottomBarHeight), cornerRadius: 0)
    filledShapePath.append(emptyShapePath)
    filledShapePath.usesEvenOddFillRule = true

    editLayer = CAShapeLayer()
    editLayer.path = filledShapePath.cgPath
    editLayer.fillRule = kCAFillRuleEvenOdd
    editLayer.fillColor = UIColor.black.cgColor
    editLayer.opacity = 0.5
    viewController.view.layer.addSublayer(editLayer)

    // Move and Scale label
    label = UILabel(frame: CGRect(x: 0, y: 10, width: viewWidth, height: 50))
    label.text = "Move and Scale"
    label.textAlignment = .center
    label.textColor = UIColor.white
    viewController.view.addSubview(label)
}


private func hideDefaultEditOverlay(view: UIView)
{
    for subview in view.subviews
    {
        if let cropOverlay = NSClassFromString("PLCropOverlayCropView")
        {
            if subview.isKind(of: cropOverlay) {
                subview.isHidden = true
                break
            }
            else {
                hideDefaultEditOverlay(view: subview)
            }
        }
    }
}
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/20794187

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档