隐藏/显示 iPhone 相机光圈/快门动画

发布于 2024-09-07 14:21:25 字数 1715 浏览 2 评论 0原文

我无法隐藏我的应用程序的 iPhone 相机快门打开动画。 我正在使用 UIImagePickerController 访问 iphone 相机并使用我自己的覆盖控制器。 有没有办法在相机启动时删除初始快门(也称为虹膜)动画。 谢谢

[编辑]

对于那些想知道如何更改相机虹膜动画的人。

在相机虹膜动画开始之前调用以下函数。

- (void)navigationController:(UINavigationController *)navigationController willShowViewController:(UIViewController *)viewController animated:(BOOL)animated
{
    // Here is were I make the camera preview fit the entire screen. 
    // This might violate the "don't change the view hierarchy"-rule. 
    // So I am not sure if it is valid for App Store commitment.
    // However, the NSLogs are used to
    // figure out which subview is the actual Camera Preview which turns out 
    // to be the PLPreviewView. (uncomment to se the printouts).
    // Change it's size to fit the entire screen (and scale it accordingly
    // to avoid distorted image

    NSLog(@"WillShowViewController called...");

    NSLog(@"VC:view:subviews\n %@\n\n", [[viewController view] subviews]);

    NSLog(@"VC:view:PLCameraView:subviews\n %@\n\n", [[[[viewController view] subviews] objectAtIndex: 0] subviews]);

    NSLog(@"VC:view:PLCameraView:PLPreviewView:subviews\n %@\n\n", [[[[[[viewController view] subviews] objectAtIndex: 0] subviews] objectAtIndex: 0] subviews]);
    NSLog(@"VC:view:PLCameraView:PLCropOverLay:subviews\n %@\n\n", [[[[[[viewController view] subviews] objectAtIndex: 0] subviews] objectAtIndex: 1] subviews]);
    NSLog(@"VC:view:PLCameraView:UIImageView:subviews\n %@\n\n", [[[[[[viewController view] subviews] objectAtIndex: 0] subviews] objectAtIndex: 2] subviews]);

}

在上面的函数中,您可以使用普通的 NSMuatableArray 语法(如 objectAtIndex)来遍历每一层,

希望这可以帮助您。

问候,

安库尔

I am not able to Hide the iphone Camera shutter opening animation for my app.
I am using UIImagePickerController to access iphone camera and using my own overlay controllers.
Is there a way to remove the initial shutter(also known as Iris) animation as the camera starts.
Thank You

[EDIT]

For those who wants to know the way to change the camera iris animation.

The below function is called before the camera iris animation starts.

- (void)navigationController:(UINavigationController *)navigationController willShowViewController:(UIViewController *)viewController animated:(BOOL)animated
{
    // Here is were I make the camera preview fit the entire screen. 
    // This might violate the "don't change the view hierarchy"-rule. 
    // So I am not sure if it is valid for App Store commitment.
    // However, the NSLogs are used to
    // figure out which subview is the actual Camera Preview which turns out 
    // to be the PLPreviewView. (uncomment to se the printouts).
    // Change it's size to fit the entire screen (and scale it accordingly
    // to avoid distorted image

    NSLog(@"WillShowViewController called...");

    NSLog(@"VC:view:subviews\n %@\n\n", [[viewController view] subviews]);

    NSLog(@"VC:view:PLCameraView:subviews\n %@\n\n", [[[[viewController view] subviews] objectAtIndex: 0] subviews]);

    NSLog(@"VC:view:PLCameraView:PLPreviewView:subviews\n %@\n\n", [[[[[[viewController view] subviews] objectAtIndex: 0] subviews] objectAtIndex: 0] subviews]);
    NSLog(@"VC:view:PLCameraView:PLCropOverLay:subviews\n %@\n\n", [[[[[[viewController view] subviews] objectAtIndex: 0] subviews] objectAtIndex: 1] subviews]);
    NSLog(@"VC:view:PLCameraView:UIImageView:subviews\n %@\n\n", [[[[[[viewController view] subviews] objectAtIndex: 0] subviews] objectAtIndex: 2] subviews]);

}

In the above function you can go through each layer by using the normal NSMuatableArray syntax like objectAtIndex

hope this might help you.

Regards,

Ankur

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(7

丢了幸福的猪 2024-09-14 14:21:25

使用这个答案作为起点,我终于解决了这个问题:

注意:这显然不符合 3.3.1 标准。

  1. 监听 UIImagePickerController 上的 UINavigationControllerDidShowViewControllerNotification >,以及全局的 PLCameraViewIrisAnimationDidEndNotification

  2. 遍历视图层次结构(从主 UIWindow 开始)寻找 PLCameraView。保存主 UIWindow 视图的索引,因为稍后您将需要它。

  3. 从其superView 中删除PLCameraView。如果需要,可在全局索引 0 处插入您自己的视图。

  4. 虹膜动画完成后,删除您的视图并在其原始索引处重新添加 PLCameraView

Using this answer as a starting point, I've finally solved this problem:

NOTE: This is obviously not 3.3.1-compliant.

  1. Listen for the UINavigationControllerDidShowViewControllerNotification on your UIImagePickerController, and the PLCameraViewIrisAnimationDidEndNotification globally.

  2. Traverse the view hierarchy (starting at the main UIWindow) looking for the PLCameraView. Save the index of the view against the main UIWindow, as you'll need it later.

  3. Remove the PLCameraView from its superView. If desired, insert your own view at global index 0.

  4. When the iris animation is finished, remove your view and re-add the PLCameraView at its original index.

牵强ㄟ 2024-09-14 14:21:25

遇到类似的情况:我希望当我拍摄由 UIImagePickerController 的 self.cameraOverlayView 中的按钮触发的照片时出现快门。到达此页面,做了一些额外的研究并得出了这个解决方案。

概要:

@interface MyController : UIImagePickerController
...    
- (id) init {
...
    self.cameraOverlayView = _my_overlay_;
    self.showsCameraControls = NO;
...
}
... 
- (void) onMyShutterButton {
    [self takePicture]; 
        // You want the shutter animation to happen now.
        // .. but it does not.
}

解决方案:

// Some constants for the iris view and selector
NSString* kIrisViewClassName = @"PLCameraIrisAnimationView";
SEL kIrisSelector = NSSelectorFromString(@"animateIrisOpen");

@implementation MyController {
...
    UIView* iris_;
}
- (void) viewDidAppear:(BOOL)animated {
    [super viewDidAppear:animated];
    // Find the iris view in the siblings of your overlay view
    for (UIView* view in self.cameraOverlayView.superview.subviews) {
        if ([kIrisViewClassName isEqualToString:[[view class] description]]) {
            // It will be hidden by 'self.showsCameraControls = NO'.
            view.hidden = false;   
            // Extra precautions - as this is undocumented.  
            if ([view respondsToSelector:kIrisSelector]) {
                iris_ = view;
            }
            break;
        }
    }
}
- (void) animateIrisOpen {
    if (iris_) {
        [iris_ performSelector:kIrisSelector];
    }
}
...
- (void) onMyShutterButton {
    [self takePicture]; 
    [self animateIrisOpen];   // Voila - the shutter happens
}

Came across a similar: I wanted to have the shutter appear when I take the picture triggered by a button in a self.cameraOverlayView of a UIImagePickerController. Arrived to this page, did some extra research and came to this solution.

Synopsis:

@interface MyController : UIImagePickerController
...    
- (id) init {
...
    self.cameraOverlayView = _my_overlay_;
    self.showsCameraControls = NO;
...
}
... 
- (void) onMyShutterButton {
    [self takePicture]; 
        // You want the shutter animation to happen now.
        // .. but it does not.
}

Solution:

// Some constants for the iris view and selector
NSString* kIrisViewClassName = @"PLCameraIrisAnimationView";
SEL kIrisSelector = NSSelectorFromString(@"animateIrisOpen");

@implementation MyController {
...
    UIView* iris_;
}
- (void) viewDidAppear:(BOOL)animated {
    [super viewDidAppear:animated];
    // Find the iris view in the siblings of your overlay view
    for (UIView* view in self.cameraOverlayView.superview.subviews) {
        if ([kIrisViewClassName isEqualToString:[[view class] description]]) {
            // It will be hidden by 'self.showsCameraControls = NO'.
            view.hidden = false;   
            // Extra precautions - as this is undocumented.  
            if ([view respondsToSelector:kIrisSelector]) {
                iris_ = view;
            }
            break;
        }
    }
}
- (void) animateIrisOpen {
    if (iris_) {
        [iris_ performSelector:kIrisSelector];
    }
}
...
- (void) onMyShutterButton {
    [self takePicture]; 
    [self animateIrisOpen];   // Voila - the shutter happens
}
偷得浮生 2024-09-14 14:21:25

我对此进行了一些混乱,但将视图生命周期方法的各种组合发送到图像选择器。 (viewWillAppear、viewDidAppear 等)但我不记得哪些最终起作用了。

I've messed around with this a bit, but sending various combinations of the view lifecycle methods to the image picker. (viewWillAppear, viewDidAppear, etc.) But I don't remember which ones ended up working.

柠檬色的秋千 2024-09-14 14:21:25

抱歉这么晚才回复。我找到了解决方案,我玩弄了cameraView的视图层次结构,并在所有内容的顶部添加了我自己的层。动画在那里发生,一旦快门打开,最顶层就被移除。如果有人需要有关代码的任何进一步帮助,请告诉我,我将提供确切的步骤和语法。

-安库尔

Sorry for replying getting back so late. I found out the solution for that well I played around with the view hierarchy of the cameraView and added my own layer at the top of everything. The animation took place there and once the shutter was open the top most layer was removed. If someone need any further help with the code please let me know, I will provide with the exact steps and syntax.

-Ankur

傲鸠 2024-09-14 14:21:25

joshwa 的答案在虹膜动画期间完全隐藏了整个相机视图。出于我的目的,我需要可见的相机视图,但没有虹膜动画。通过对他的方法进行一些调整,我能够实现这一目标。正如其他人所指出的,这在应用程序商店中可能允许也可能不允许,因为我们正在扰乱视图层次结构并监听未记录的通知。

需要 3 个 ivars:

UIImagePickerController *imagePickerController;
UIView *plCameraIrisAnimationView;  // view that animates the opening/closing of the iris
UIImageView *cameraIrisImageView;  // static image of the closed iris

隐藏关闭的虹膜图像并删除动画视图。我也尝试简单地隐藏动画视图,但动画仍然可见:

- (void)receivedNavigationControllerDidShowViewControllerNotification:(NSNotification *)notification {
    UIView *view = imagePickerController.view;
    [plCameraIrisAnimationView release];
    plCameraIrisAnimationView = nil;
    cameraIrisImageView = nil;
    while (view.subviews.count && (view = [view.subviews objectAtIndex:0])) {
        if ([[[view class] description] isEqualToString:@"PLCameraView"]) {
            for (UIView *subview in view.subviews) {
                if ([subview isKindOfClass:[UIImageView class]]) {
                    cameraIrisImageView = (UIImageView *)subview;
                }
                else if ([[[subview class] description] isEqualToString:@"PLCropOverlay"]) {
                    for (UIView *subsubview in subview.subviews) {
                        if ([[[subsubview class] description] isEqualToString:@"PLCameraIrisAnimationView"]) {
                            plCameraIrisAnimationView = [subsubview retain];
                        }
                    }
                }
            }
        }
    }
    cameraIrisImageView.hidden = YES;
    [plCameraIrisAnimationView removeFromSuperview];
    [[NSNotificationCenter defaultCenter] removeObserver:self name:@"UINavigationControllerDidShowViewControllerNotification" object:nil];
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(receivedPLCameraViewIrisAnimationDidEndNotification:) name:@"PLCameraViewIrisAnimationDidEndNotification" object:nil];
}

当动画结束时,取消隐藏虹膜图像并重新添加动画视图:

- (void)receivedPLCameraViewIrisAnimationDidEndNotification:(NSNotification *)notification {
    cameraIrisImageView.hidden = NO;

    UIView *view = imagePickerController.view;
    while (view.subviews.count && (view = [view.subviews objectAtIndex:0])) {
        if ([[[view class] description] isEqualToString:@"PLCameraView"]) {
            for (UIView *subview in view.subviews) {
                if ([[[subview class] description] isEqualToString:@"PLCropOverlay"]) {
                    [subview insertSubview:plCameraIrisAnimationView atIndex:1];
                    [plCameraIrisAnimationView release];
                    plCameraIrisAnimationView = nil;
                    break;
                }
            }
        }
    }

    [[NSNotificationCenter defaultCenter] removeObserver:self name:@"PLCameraViewIrisAnimationDidEndNotification" object:nil];
}

joshwa's answer completely hides the entire camera view for the duration of the iris animation. For my purposes, I needed the camera view visible, just without the iris animation. I was able to accomplish this with a little tweaking of his method. As others have noted, this may or may not be allowed on the app store since we're messing with the view hierarchy as well as listening for undocumented notifications.

3 ivars are needed:

UIImagePickerController *imagePickerController;
UIView *plCameraIrisAnimationView;  // view that animates the opening/closing of the iris
UIImageView *cameraIrisImageView;  // static image of the closed iris

Hide the closed iris image and remove the animation view. I tried simply hiding the animation view as well, but the animation was still visible:

- (void)receivedNavigationControllerDidShowViewControllerNotification:(NSNotification *)notification {
    UIView *view = imagePickerController.view;
    [plCameraIrisAnimationView release];
    plCameraIrisAnimationView = nil;
    cameraIrisImageView = nil;
    while (view.subviews.count && (view = [view.subviews objectAtIndex:0])) {
        if ([[[view class] description] isEqualToString:@"PLCameraView"]) {
            for (UIView *subview in view.subviews) {
                if ([subview isKindOfClass:[UIImageView class]]) {
                    cameraIrisImageView = (UIImageView *)subview;
                }
                else if ([[[subview class] description] isEqualToString:@"PLCropOverlay"]) {
                    for (UIView *subsubview in subview.subviews) {
                        if ([[[subsubview class] description] isEqualToString:@"PLCameraIrisAnimationView"]) {
                            plCameraIrisAnimationView = [subsubview retain];
                        }
                    }
                }
            }
        }
    }
    cameraIrisImageView.hidden = YES;
    [plCameraIrisAnimationView removeFromSuperview];
    [[NSNotificationCenter defaultCenter] removeObserver:self name:@"UINavigationControllerDidShowViewControllerNotification" object:nil];
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(receivedPLCameraViewIrisAnimationDidEndNotification:) name:@"PLCameraViewIrisAnimationDidEndNotification" object:nil];
}

When the animation is over, unhide the iris image and re-add the animation view:

- (void)receivedPLCameraViewIrisAnimationDidEndNotification:(NSNotification *)notification {
    cameraIrisImageView.hidden = NO;

    UIView *view = imagePickerController.view;
    while (view.subviews.count && (view = [view.subviews objectAtIndex:0])) {
        if ([[[view class] description] isEqualToString:@"PLCameraView"]) {
            for (UIView *subview in view.subviews) {
                if ([[[subview class] description] isEqualToString:@"PLCropOverlay"]) {
                    [subview insertSubview:plCameraIrisAnimationView atIndex:1];
                    [plCameraIrisAnimationView release];
                    plCameraIrisAnimationView = nil;
                    break;
                }
            }
        }
    }

    [[NSNotificationCenter defaultCenter] removeObserver:self name:@"PLCameraViewIrisAnimationDidEndNotification" object:nil];
}
还在原地等你 2024-09-14 14:21:25

在相机虹膜动画开始之前调用以下函数。

- (void)navigationController:(UINavigationController *)navigationController willShowViewController:(UIViewController *)viewController animated:(BOOL)animated
{
    // Here is were I make the camera preview fit the entire screen. 
    // This might violate the "don't change the view hierarchy"-rule. 
    // So I am not sure if it is valid for App Store commitment.
    // However, the NSLogs are used to
    // figure out which subview is the actual Camera Preview which turns out 
    // to be the PLPreviewView. (uncomment to se the printouts).
    // Change it's size to fit the entire screen (and scale it accordingly
    // to avoid distorted image

    NSLog(@"WillShowViewController called...");

    NSLog(@"VC:view:subviews\n %@\n\n", [[viewController view] subviews]);

    NSLog(@"VC:view:PLCameraView:subviews\n %@\n\n", [[[[viewController view] subviews] objectAtIndex: 0] subviews]);

    NSLog(@"VC:view:PLCameraView:PLPreviewView:subviews\n %@\n\n", [[[[[[viewController view] subviews] objectAtIndex: 0] subviews] objectAtIndex: 0] subviews]);
    NSLog(@"VC:view:PLCameraView:PLCropOverLay:subviews\n %@\n\n", [[[[[[viewController view] subviews] objectAtIndex: 0] subviews] objectAtIndex: 1] subviews]);
    NSLog(@"VC:view:PLCameraView:UIImageView:subviews\n %@\n\n", [[[[[[viewController view] subviews] objectAtIndex: 0] subviews] objectAtIndex: 2] subviews]);

}

在上面的函数中,您可以使用普通的 NSMuatableArray 语法(如 objectAtIndex)来遍历每一层,

希望这可以帮助您。

问候,

安库尔

The below function is called before the camera iris animation starts.

- (void)navigationController:(UINavigationController *)navigationController willShowViewController:(UIViewController *)viewController animated:(BOOL)animated
{
    // Here is were I make the camera preview fit the entire screen. 
    // This might violate the "don't change the view hierarchy"-rule. 
    // So I am not sure if it is valid for App Store commitment.
    // However, the NSLogs are used to
    // figure out which subview is the actual Camera Preview which turns out 
    // to be the PLPreviewView. (uncomment to se the printouts).
    // Change it's size to fit the entire screen (and scale it accordingly
    // to avoid distorted image

    NSLog(@"WillShowViewController called...");

    NSLog(@"VC:view:subviews\n %@\n\n", [[viewController view] subviews]);

    NSLog(@"VC:view:PLCameraView:subviews\n %@\n\n", [[[[viewController view] subviews] objectAtIndex: 0] subviews]);

    NSLog(@"VC:view:PLCameraView:PLPreviewView:subviews\n %@\n\n", [[[[[[viewController view] subviews] objectAtIndex: 0] subviews] objectAtIndex: 0] subviews]);
    NSLog(@"VC:view:PLCameraView:PLCropOverLay:subviews\n %@\n\n", [[[[[[viewController view] subviews] objectAtIndex: 0] subviews] objectAtIndex: 1] subviews]);
    NSLog(@"VC:view:PLCameraView:UIImageView:subviews\n %@\n\n", [[[[[[viewController view] subviews] objectAtIndex: 0] subviews] objectAtIndex: 2] subviews]);

}

In the above function you can go through each layer by using the normal NSMuatableArray syntax like objectAtIndex

hope this might help you.

Regards,

Ankur

攀登最高峰 2024-09-14 14:21:25

为了阐述 Catalin 的答案(顺便说一句,这很棒),我发现如果您稍微更改方法“animateIrisOpen”,演示文稿会好一点……但很明显。

- (void) animateIrisOpen {
    if (iris_) {
        iris_.hidden = NO;
        [iris_ performSelector:kIrisSelector];
    }
}

To expound on Catalin's answer, (which was great btw), I found if you change the method "animateIrisOpen" slightly, the presentation is a fraction better... but noticeable.

- (void) animateIrisOpen {
    if (iris_) {
        iris_.hidden = NO;
        [iris_ performSelector:kIrisSelector];
    }
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文