iOS 7样式的模糊视图


113

是否有人知道将复制iOS7样式模糊视图的任何控件。

我假设可以存在某种UIView子类来复制行为。

我说的是这些类型的视图,它们会使背景变得非常模糊,以至于它们从背景视图中产生拉动效果。

在此处输入图片说明


6
GPUImage可能会有所帮助。
Maarten 2013年

@Anil好了,问题将是在发布ios7 SDK时如何做到这一点,而又不将我的应用程序限制为仅ios7;)。
2013年


1
苹果公司已经发布了一个UIImage类别来实现这一目的。只是试图找到它。
Fogmeister

1
该代码是从WWDC会话201链接的。它在github上公开,我只是找不到atm。
Fogmeister

Answers:


40

您可以修改Bin Zhang的RWBlurPopover之类的方法来执行此操作。该组件使用我的GPUImage将高斯模糊应用于其下面的组件,但是您也可以轻松地使用CIGaussianBlur对其进行处理。不过GPUImage可能快了一点

但是,该组件依赖于您能够捕获正在呈现的视图后面的视图,并且可能无法为该内容后面的动画设置视图。需要通过Core Graphics来光栅化背景视图会减慢速度,因此我们可能没有足够的直接访问权限,无法以高性能的方式在动画视图上进行叠加。

作为对上述内容的更新,我最近重新处理了GPUImage中的模糊以支持可变半径,从而可以在iOS 7的控制中心视图中完全复制模糊大小。由此,我创建了GPUImageiOS7BlurFilter类,该类封装了Apple似乎在此处使用的适当的模糊大小和颜色校正。这就是GPUImage的模糊(右侧)与内置模糊(左侧)的比较方式:

苹果的模糊 GPUImage的模糊

我使用4倍下采样/上采样来减少需要进行高斯模糊处理的像素数,因此iPhone 4S使用此操作可以在大约30毫秒内使整个屏幕模糊。

您仍然面临着如何以高效的方式将内容从该视图后面的模糊中拉出的挑战。


那么您如何看待苹果公司将其实现呢?如果打开“相机”应用程序,然后拉起“控制中心”(底部的设置屏幕),则模糊会跟随相机看到的内容。
雪人2013年

2
@maq-可以在后台访问系统上的所有内容。开发操作系统的人可以做的事情与公共接口允许我们做的事情有很大不同。
布拉德·拉尔森

3
@maq-相机专门供稿,是的。一种实现方法是使用GPUImage(通过AV Foundation)拉入摄像机帧,然后将其输出都输出到GPUImageView中以进行实时摄像机输出,然后并行地馈入高斯模糊(可能还有裁剪)以匹配模糊视图的位置),然后输出到另一个GPUImageView,它将在控件后面显示模糊内容。这是可能的,因为我们有从相机框架到OpenGL ES的快速路径,但是对于通用UI元素没有类似的东西。
布拉德·拉尔森

1
我正在以编程方式截取UIView的屏幕截图,并使用GPUImageGaussianBlurFilter尝试创建类似的效果,但是结果与Apple风格截然不同。滤镜似乎在网格中模糊,到处都有可见的正方形,而Apple的滤色器只是一张光滑的纸。
雪人2013年

1
@maq-确保您使用的是存储库中的最新代码,因为以前存在高半径模糊的错误。也就是说,默认情况下,模糊仅采样9个像素的区域,因此,如果您增加模糊的乘数,超过该点,您将开始看到由于跳过像素而产生的伪像。这样做是出于性能方面的考虑,但是您可以修改顶点和片段着色器以对大量像素进行采样。那,或者尝试应用CIGaussianBlur,它具有更通用的模糊实现。这些日子之一,我将把这种模糊扩大到更大的半径。
布拉德·拉尔森

28

我正在使用FXBlurView哪个在iOS5 +上效果很好

https://github.com/nicklockwood/FXBlurView

CocoaPods:

-> FXBlurView (1.3.1)
   UIView subclass that replicates the iOS 7 realtime background blur effect, but works on iOS 5 and above.
   pod 'FXBlurView', '~> 1.3.1'
   - Homepage: http://github.com/nicklockwood/FXBlurView
   - Source:   https://github.com/nicklockwood/FXBlurView.git
   - Versions: 1.3.1, 1.3, 1.2, 1.1, 1.0 [master repo]

我通过使用添加它:

FXBlurView *blurView = [[FXBlurView alloc] initWithFrame:CGRectMake(50, 50, 150, 150)];
[self.blurView setDynamic:YES];
[self.view addSubview:self.blurView];

2
使用FXBlurView有一些技巧吗?我已经尝试过了,但是在iPhone 5上我们产生了滞后的视图。他们的演示项目效果很好。相当奇怪。
2014年

这取决于您想做什么。当我躺在A的FXBlurView顶部时,UIScrollView我的成绩也很差。我相信这与添加模糊的方式有关。如果我没记错的话,Apple是在使用自己的模糊功能时直接访问GPU,这是我们开发人员无法做到的。因此,@ cprcrack解决方案实际上是这里的最佳解决方案。
Paul Peelen 2014年

2
您如何使用FXBlurView处理设备旋转?我现在正在呈现一个模式对话框。对话框本身可以很好地旋转,但是背景以错误的方式被挤压(基本上需要在旋转之后进行更新)。
fatuhoku 2014年

1
当然,FXBlurView是一个不错的选择,但是当有CPU使用问题时。比我更喜欢其他blurView。我在UICollectionVIew和UITableView中使用了它,但是它增加了我的CPU使用率。在下一轮中,我评论这些分配,并且这变得正常。我希望这会帮助某人。
Vatsal Shukla 2015年

27

警告:评论中的某人指出Apple拒绝使用此技术的应用程序。那对我没有发生,只是供您考虑。

这可能会让您感到惊讶,但是您可以使用UIToolbar,该工具包已经包含该标准效果(仅iOS 7+)。在您查看控制器的viewDidLoad中:

self.view.opaque = NO;
self.view.backgroundColor = [UIColor clearColor]; // Be sure in fact that EVERY background in your view's hierarchy is totally or at least partially transparent for a kind effect!

UIToolbar *fakeToolbar = [[UIToolbar alloc] initWithFrame:self.view.bounds];
fakeToolbar.autoresizingMask = self.view.autoresizingMask;
// fakeToolbar.barTintColor = [UIColor white]; // Customize base color to a non-standard one if you wish
[self.view insertSubview:fakeToolbar atIndex:0]; // Place it below everything

1
是的,这让我感到惊讶。我验证了,这个想法确实可行。我只做了这样的一行更改viewDidLoad。-(void)viewDidLoad {[super viewDidLoad]; self.view = [[UIToolbar alloc] initWithFrame:CGRectZero]; 在我的情况下,我以编程方式(旧样式)布局视图。我赞成这种解决方案,因为UIToolbar继承了UIView,所以从根本上讲,我在此解决方案中看不到任何问题。在进行开发和测试此解决方案时,我将进行更多测试。
Ashok 2013年

这是个好主意,似乎效果很好。希望我能有更多的控制权,但这已尽其所能!就是说,@ SudhirJonathan在上面提到了一个链接,作者将其带到了更高的层次-他从UIToolBar窃取CALAYER并重新利用它!辉煌!
David H

2
真?基于什么理由?它没有使用任何私有API,并且如果所有创新的处理方式都将被拒绝,那么将不会产生很多效果……
TheEye 2014年

在我的iOS 7.1 iPhone上工作
marsant,2014年

有没有办法“消除”模糊性?
maxisme


13

获得模糊叠加层的最佳新方法是使用新的iOS 8功能UIVisualEffectView。

UIBlurEffect *effect = [UIBlurEffect effectWithStyle:UIBlurEffectStyleLight];

UIVisualEffectView *bluredView = [[UIVisualEffectView alloc] initWithEffect:effect];

bluredView.frame = self.view.bounds;

[self.view addSubview:bluredView];

UIBlurEffect支持三种样式。黑暗,光明和超轻。


1

您可以使用UIToolBar创建一个类,该类是UIView的子类,并在单独的视图控制器中实例化它。此方法演示了提供实时反馈(在这种情况下为AVCaptureSession)的半透明UIToolBar(由UIView子类化)。

YourUIView.h

#import <UIKit/UIKit.h>

@interface YourUIView : UIView
@property (nonatomic, strong) UIColor *blurTintColor;
@property (nonatomic, strong) UIToolbar *toolbar;
@end

YourUIView.m

#import "YourUIView.h"

@implementation YourUIView

- (instancetype)init
{
    self = [super init];
    if (self) {
        [self setup];
    }
    return self;
}

- (void)setup {
    // If we don't clip to bounds the toolbar draws a thin shadow on top
    [self setClipsToBounds:YES];

    if (![self toolbar]) {
        [self setToolbar:[[UIToolbar alloc] initWithFrame:[self bounds]]];
        [self.toolbar setTranslatesAutoresizingMaskIntoConstraints:NO];
        [self insertSubview:[self toolbar] atIndex:0];

        [self addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|[_toolbar]|"
                                                                     options:0
                                                                     metrics:0
                                                                       views:NSDictionaryOfVariableBindings(_toolbar)]];
        [self addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|[_toolbar]|"
                                                                     options:0
                                                                     metrics:0
                                                                       views:NSDictionaryOfVariableBindings(_toolbar)]];
    }
}

- (void) setBlurTintColor:(UIColor *)blurTintColor {
    [self.toolbar setBarTintColor:blurTintColor];
}

@end

定制完上述UIView后,继续创建一个类,该类是ViewController的子类。下面,我创建了一个使用AVCapture会话的类。您必须使用AVCaptureSession才能覆盖Apple的内置摄像头配置。因此,您可以覆盖YourUIView类中的半透明UIToolBar

YourViewController.h

#import <UIKit/UIKit.h>

@interface YourViewController : UIViewController
@property (strong, nonatomic) UIView *frameForCapture;
@end

YourViewController.m

#import "YourViewController.h"
#import <AVFoundation/AVFoundation.h>
#import "TestView.h"

@interface YourViewController ()
@property (strong, nonatomic) UIButton *displayToolBar;

@end

@implementation YourViewController


AVCaptureStillImageOutput *stillImageOutput;
AVCaptureSession *session;

- (void) viewWillAppear:(BOOL)animated
{
    session = [[AVCaptureSession alloc] init];
    [session setSessionPreset:AVCaptureSessionPresetPhoto];

    AVCaptureDevice *inputDevice = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];
    NSError *error;
    AVCaptureDeviceInput *deviceInput = [AVCaptureDeviceInput deviceInputWithDevice:inputDevice error:&error];

    if ([session canAddInput:deviceInput]) {
        [session addInput:deviceInput];
    }

    AVCaptureVideoPreviewLayer *previewLayer = [[AVCaptureVideoPreviewLayer alloc] initWithSession:session];
    [previewLayer setVideoGravity:AVLayerVideoGravityResizeAspectFill];
    CALayer *rootLayer = [[self view] layer];
    [rootLayer setMasksToBounds:YES];
    CGRect frame = [[UIScreen mainScreen] bounds];

    self.frameForCapture.frame = frame;

    [previewLayer setFrame:frame];

    [rootLayer insertSublayer:previewLayer atIndex:0];

    stillImageOutput = [[AVCaptureStillImageOutput alloc] init];
    NSDictionary *outputSettings = [[NSDictionary alloc] initWithObjectsAndKeys:AVVideoCodecJPEG, AVVideoCodecKey, nil];
    [stillImageOutput setOutputSettings:outputSettings];

    [session addOutput:stillImageOutput];

    [session startRunning];

    [self.navigationController setNavigationBarHidden:YES animated:animated];
    [super viewWillAppear:animated];
}


- (void)viewDidLoad
{
    [super viewDidLoad];

    /* Open button */

    UIButton *button = [[UIButton alloc] initWithFrame:CGRectMake(0, 350, self.view.bounds.size.width, 50)];
    [button addTarget:self action:@selector(showYourUIView:) forControlEvents:UIControlEventTouchUpInside];
    [button setTitle:@"Open" forState:UIControlStateNormal];
    [button setTitleColor:[UIColor redColor] forState:UIControlStateNormal];
    button.backgroundColor = [UIColor greenColor];
    [self.view addSubview:button];

    UIButton *anotherButton = [[UIButton alloc] initWithFrame:CGRectMake(0, 50, self.view.bounds.size.width, 50)];
    [anotherButton addTarget:self action:@selector(showYourUIView:) forControlEvents:UIControlEventTouchUpInside];
    [anotherButton setTitle:@"Open" forState:UIControlStateNormal];
    [anotherButton setTitleColor:[UIColor greenColor] forState:UIControlStateNormal];
    anotherButton.backgroundColor = [UIColor redColor];
    [self.view addSubview:anotherButton];

}

- (void) showYourUIView:(id) sender
{
    TestView *blurView = [TestView new];
    [blurView setFrame:self.view.bounds];
    [self.view addSubview:blurView];
}


@end

答案似乎与问题完全无关。
组合

@combinatorial这是将透明视图添加到另一个视图控制器的更有效的方法之一。我包含了AVCapture代码,以显示该代码可用于实时反馈,而不是像其他用户所建议的那样仅添加模糊的背景图像。
74U n3U7r1no 2014年

抱歉,您可能想在开始时添加一些内容,以总结该方法及其使用原因。
组合

@combinatorial Thank
74U n3U7r1no 2014年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.