Размытие в стиле iOS 7

113

Кто-нибудь знает какие-либо элементы управления, которые будут копировать виды размытия в стиле iOS7.

Я предполагаю, что может быть какой-то подкласс UIView, который будет копировать поведение.

Я говорю об этих типовых представлениях, которые очень сильно размывают фон, так что они имеют эффекты вытягивания из фонового представления.

введите описание изображения здесь

Endy
источник
6
GPUImage может помочь.
Maarten
@Anil, тогда вопрос будет в том, когда будет выпущен ios7 SDK, как я могу сделать это, не ограничивая свое приложение только ios7;).
endy
1
Apple выпустила категорию UIImage, которая делает именно это. Просто пытаюсь его найти.
Fogmeister
1
Код связан с сеансом 201 WWDC. Он общедоступен на github, я просто не могу найти его на атм.
Fogmeister

Ответы:

40

Для этого вы могли бы изменить что-то вроде RWBlurPopover Бин Чжана . Этот компонент использует мой GPUImage для применения размытия по Гауссу к компонентам, находящимся под ним, но вы также можете легко использовать CIGaussianBlur для того же. Хотя GPUImage может быть на волосок быстрее .

Однако этот компонент полагается на то, что вы можете захватить представление, стоящее за тем, которое вы представляете, и могут иметь проблемы с представлениями, которые анимируются за этим содержимым. Необходимость пройти через Core Graphics для растеризации фонового представления замедлит работу, поэтому у нас, вероятно, не будет достаточно прямого доступа, чтобы иметь возможность делать это эффективным способом для наложений при анимации представлений.

В качестве обновления вышесказанного я недавно переработал размытие в GPUImage для поддержки переменных радиусов, что позволило полностью воспроизвести размер размытия в представлении центра управления iOS 7. Исходя из этого, я создал класс GPUImageiOS7BlurFilter, который инкапсулирует правильный размер размытия и коррекцию цвета, которые Apple, похоже, использует здесь. Вот как размытие GPUImage (справа) сравнивается со встроенным размытием (слева):

Размытие Apple Размытие GPUImage

Я использую 4-кратное понижение / повышающую дискретизацию, чтобы уменьшить количество пикселей, над которыми должно работать размытие по Гауссу, поэтому iPhone 4S может размыть весь экран примерно за 30 мс с помощью этой операции.

У вас все еще есть проблема, как эффективно вытащить контент из представлений, находящихся за ним, в это размытие.

Брэд Ларсон
источник
Как вы думаете, как Apple справляется с этим? Если вы откроете приложение «Камера» и откроете Центр управления (экран настроек снизу), размытие будет соответствовать тому, что видит камера.
Snowman
2
@maq - помогает получить доступ изнутри ко всему в системе. То, что могут делать разработчики ОС, сильно отличается от того, что позволяют нам делать общедоступные интерфейсы.
Брэд Ларсон
3
@maq - Камера специально подает, да. Один из способов сделать это - использовать GPUImage для извлечения кадров камеры (через AV Foundation), а затем выводить этот вывод как в GPUImageView для вывода прямой трансляции с камеры, а затем параллельно передавать в размытие по Гауссу (и, возможно, обрезку). чтобы соответствовать положению размытого представления) и этот вывод в другой GPUImageView, который будет отображать размытое содержимое за вашими элементами управления. Это возможно, потому что у нас есть быстрый путь от кадров камеры к OpenGL ES, но у нас нет ничего похожего для общих элементов пользовательского интерфейса.
Брэд Ларсон
1
Я программно делаю снимок экрана UIView и использую GPUImageGaussianBlurFilter, чтобы попытаться создать аналогичный эффект, но результат сильно отличается от стиля Apple. Кажется, что фильтр размывается в сетке с видимыми квадратами повсюду, тогда как у Apple это всего лишь один гладкий лист.
Snowman
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 наблюдаются задержки при просмотре. Их демонстрационный проект работает нормально. Довольно странно.
Cris
Это зависит от того, чем вы хотите заниматься. Когда я кладу FXBlurViewсверху, результат UIScrollViewтоже медленный. Я считаю, что это связано с тем, как добавлено размытие. Apple, если я не ошибаюсь, напрямую обращается к графическому процессору при использовании собственного размытия, чего мы, как разработчики, не можем. Следовательно, решение @cprcrack на самом деле является лучшим решением здесь.
Пол Пилен
2
Как вы справлялись с вращением устройства с помощью FXBlurView? В данный момент я представляю модальный диалог; сам диалог вращается нормально, но фон сжимается неправильно (в основном его нужно обновить после поворота).
fatuhoku
1
Конечно, FXBlurView - хороший вариант, но когда есть вопрос загрузки процессора. чем я предпочитаю другой blurView. Я использую это в своих UICollectionVIew и UITableView, но это увеличивает загрузку процессора. в следующем прогоне я прокомментирую эти распределения, и это станет нормальным. надеюсь, это кому-то поможет.
Ватсал Шукла
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
cprcrack
источник
1
Да, это меня удивило. Я проверил, эта идея действительно работает. Я сделал только одну замену строки viewDidLoadвот так. - (недействительно) viewDidLoad {[супер viewDidLoad]; self.view = [[UIToolbar alloc] initWithFrame: CGRectZero]; } В моем случае я размещаю свои представления программно (старый стиль). Я поддерживаю это решение, потому что UIToolbar наследует UIView, поэтому я не вижу в этом решении никаких проблем. Я буду тестировать больше по мере разработки и тестирования этого решения.
Ашок
Это отличная идея, и, похоже, она действительно хорошо работает. Хотелось бы, чтобы у меня было больше контроля, но это как никогда хорошо! Тем не менее, @SudhirJonathan упомянул ссылку выше, где автор переводит это на следующий уровень - ОН ВРАЩАЕТ КАЛЕР из UIToolBar и повторно его настраивает! Гениально!
Дэвид Х
2
В самом деле? На каком основании? Он не использует какой-либо частный API, и если бы все инновационные способы работы были бы отвергнуты, многие эффекты были бы невозможны ...
TheEye
Работал на моем iPhone с iOS 7.1
марсант
Есть ли способ «утихнуть» размытость?
maxisme
13

Начиная с iOS8 вы можете использовать UIBlurEffect .

На iOS8Sampler есть хорошие примеры с UIBlurEffect и UIVibrancyEffect .

Вивьен Кормье
источник
2
Для ленивых: UIVisualEffect *blurEffect = [UIBlurEffect effectWithStyle:UIBlurEffectStyleDark]; UIVisualEffectView *blurView = [[UIVisualEffectView alloc] initWithEffect:blurEffect];
Рик Сантос
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, и создать его экземпляр в отдельном контроллере представления. Этот подход демонстрирует полупрозрачный UIToolBar (унаследованный от UIView), который обеспечивает живую обратную связь (в данном случае для AVCaptureSession).

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. Таким образом, вы можете наложить скрытый UIToolBar из класса YourUIView .

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
74U н3у7р1нет
источник
Ответ кажется совершенно не связанным с вопросом.
комбинаторная
@combinatorial Это один из наиболее эффективных способов добавления прозрачного представления в другой контроллер представления. Я включил код AVCapture, чтобы показать, что его можно использовать для обратной связи, а не просто добавлять размытое фоновое изображение, как рекомендовали другие пользователи.
74U n3U7r1no
Хорошо, извиняюсь, вы можете добавить что-нибудь в начале, которое резюмирует подход и причины его использования.
комбинаторная
@combinatorial Спасибо
74U n3U7r1no