Створення розмитого подання накладання


375

У додатку "Музика" нового iOS ми бачимо обкладинку альбому за поданням, яке розмиває його.

Як можна щось подібне здійснити? Я прочитав документацію, але нічого там не знайшов.


Відповіді:


552

Ви можете використовувати UIVisualEffectViewдля досягнення цього ефекту. Це вбудований API, який був чітко налаштований на продуктивність та великий термін служби акумулятора, плюс це легко реалізувати.

Швидкий:

//only apply the blur if the user hasn't disabled transparency effects
if !UIAccessibility.isReduceTransparencyEnabled {
    view.backgroundColor = .clear

    let blurEffect = UIBlurEffect(style: .dark)
    let blurEffectView = UIVisualEffectView(effect: blurEffect)
    //always fill the view
    blurEffectView.frame = self.view.bounds
    blurEffectView.autoresizingMask = [.flexibleWidth, .flexibleHeight]

    view.addSubview(blurEffectView) //if you have more UIViews, use an insertSubview API to place it where needed
} else {
    view.backgroundColor = .black
}

Завдання-C:

//only apply the blur if the user hasn't disabled transparency effects
if (!UIAccessibilityIsReduceTransparencyEnabled()) {
    self.view.backgroundColor = [UIColor clearColor];

    UIBlurEffect *blurEffect = [UIBlurEffect effectWithStyle:UIBlurEffectStyleDark];
    UIVisualEffectView *blurEffectView = [[UIVisualEffectView alloc] initWithEffect:blurEffect];
    //always fill the view
    blurEffectView.frame = self.view.bounds;
    blurEffectView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;

    [self.view addSubview:blurEffectView]; //if you have more UIViews, use an insertSubview API to place it where needed
} else {
    self.view.backgroundColor = [UIColor blackColor];
}

Якщо ви подаєте цей контролер подання в режимі мода, щоб розмити базовий вміст, вам потрібно встановити стиль модального подання на "Над поточним контекстом" і встановити колір тла для очищення, щоб гарантувати, що базовий контролер перегляду буде залишатися видимим, як тільки це буде представлено на вершині.


7
В якості уточнення до insertSubView:belowSubView:коментаря до цього коду я використав наступне, щоб встановити розмиття як фон перегляду:view.insertSubview(blurEffectView, atIndex: 0)
Michael Voccola

2
Посилаючись на вищезазначену відповідь, чи потрібно поставити галочку "if (! UIAccessibilityIsReduceTransparencyEnabled ())" чи Чи можемо ми пропустити це?
GKK

3
Якщо ви представляєте свій контролер подання даних, переконайтеся, що ви змінили modalPresentationStyle = .overCurrentContext разом із встановленням кольору фону як чіткого
Shardul

3
Працює дивовижно !!! Потрібна одна зміна: [self.view insertSubview: blurEffectView atIndex: 1];
Абхішек Тапліял

2
В iOS 11 я вважаю, що не потрібно вручну перевіряти UIAccessibilityIsReduceTransparencyEnabled().
Нейт Уіттакер

284

Основне зображення

Оскільки це зображення на скріншоті є статичним, ви можете використовувати CIGaussianBlurз Core Image (потрібен iOS 6). Ось зразок: https://github.com/evanwdavis/Fun-with-Masks/blob/master/Fun%20with%20Masks/EWDBlurExampleVC.m

Зауважте, це повільніше, ніж інші параметри на цій сторінці.

#import <QuartzCore/QuartzCore.h>

- (UIImage*) blur:(UIImage*)theImage
{   
    // ***********If you need re-orienting (e.g. trying to blur a photo taken from the device camera front facing camera in portrait mode)
    // theImage = [self reOrientIfNeeded:theImage];

    // create our blurred image
    CIContext *context = [CIContext contextWithOptions:nil];
    CIImage *inputImage = [CIImage imageWithCGImage:theImage.CGImage];

    // setting up Gaussian Blur (we could use one of many filters offered by Core Image)
    CIFilter *filter = [CIFilter filterWithName:@"CIGaussianBlur"];
    [filter setValue:inputImage forKey:kCIInputImageKey];
    [filter setValue:[NSNumber numberWithFloat:15.0f] forKey:@"inputRadius"];
    CIImage *result = [filter valueForKey:kCIOutputImageKey];

    // CIGaussianBlur has a tendency to shrink the image a little, 
    // this ensures it matches up exactly to the bounds of our original image
    CGImageRef cgImage = [context createCGImage:result fromRect:[inputImage extent]];

    UIImage *returnImage = [UIImage imageWithCGImage:cgImage];//create a UIImage for this function to "return" so that ARC can manage the memory of the blur... ARC can't manage CGImageRefs so we need to release it before this function "returns" and ends.
    CGImageRelease(cgImage);//release CGImageRef because ARC doesn't manage this on its own.

    return returnImage;

    // *************** if you need scaling
    // return [[self class] scaleIfNeeded:cgImage];
}

+(UIImage*) scaleIfNeeded:(CGImageRef)cgimg {
    bool isRetina = [[[UIDevice currentDevice] systemVersion] intValue] >= 4 && [[UIScreen mainScreen] scale] == 2.0;
    if (isRetina) {
        return [UIImage imageWithCGImage:cgimg scale:2.0 orientation:UIImageOrientationUp];
    } else {
        return [UIImage imageWithCGImage:cgimg];
    }
}

- (UIImage*) reOrientIfNeeded:(UIImage*)theImage{

    if (theImage.imageOrientation != UIImageOrientationUp) {

        CGAffineTransform reOrient = CGAffineTransformIdentity;
        switch (theImage.imageOrientation) {
            case UIImageOrientationDown:
            case UIImageOrientationDownMirrored:
                reOrient = CGAffineTransformTranslate(reOrient, theImage.size.width, theImage.size.height);
                reOrient = CGAffineTransformRotate(reOrient, M_PI);
                break;
            case UIImageOrientationLeft:
            case UIImageOrientationLeftMirrored:
                reOrient = CGAffineTransformTranslate(reOrient, theImage.size.width, 0);
                reOrient = CGAffineTransformRotate(reOrient, M_PI_2);
                break;
            case UIImageOrientationRight:
            case UIImageOrientationRightMirrored:
                reOrient = CGAffineTransformTranslate(reOrient, 0, theImage.size.height);
                reOrient = CGAffineTransformRotate(reOrient, -M_PI_2);
                break;
            case UIImageOrientationUp:
            case UIImageOrientationUpMirrored:
                break;
        }

        switch (theImage.imageOrientation) {
            case UIImageOrientationUpMirrored:
            case UIImageOrientationDownMirrored:
                reOrient = CGAffineTransformTranslate(reOrient, theImage.size.width, 0);
                reOrient = CGAffineTransformScale(reOrient, -1, 1);
                break;
            case UIImageOrientationLeftMirrored:
            case UIImageOrientationRightMirrored:
                reOrient = CGAffineTransformTranslate(reOrient, theImage.size.height, 0);
                reOrient = CGAffineTransformScale(reOrient, -1, 1);
                break;
            case UIImageOrientationUp:
            case UIImageOrientationDown:
            case UIImageOrientationLeft:
            case UIImageOrientationRight:
                break;
        }

        CGContextRef myContext = CGBitmapContextCreate(NULL, theImage.size.width, theImage.size.height, CGImageGetBitsPerComponent(theImage.CGImage), 0, CGImageGetColorSpace(theImage.CGImage), CGImageGetBitmapInfo(theImage.CGImage));

        CGContextConcatCTM(myContext, reOrient);

        switch (theImage.imageOrientation) {
            case UIImageOrientationLeft:
            case UIImageOrientationLeftMirrored:
            case UIImageOrientationRight:
            case UIImageOrientationRightMirrored:
                CGContextDrawImage(myContext, CGRectMake(0,0,theImage.size.height,theImage.size.width), theImage.CGImage);
                break;

            default:
                CGContextDrawImage(myContext, CGRectMake(0,0,theImage.size.width,theImage.size.height), theImage.CGImage);
                break;
        }

        CGImageRef CGImg = CGBitmapContextCreateImage(myContext);
        theImage = [UIImage imageWithCGImage:CGImg];

        CGImageRelease(CGImg);
        CGContextRelease(myContext);
    }

    return theImage;
}

Розмиття стека (поле + гауссова)

  • StackBlur Це реалізує поєднання розмиття Box та Gaussian. 7 разів швидше, ніж неприскорений гаусс, але не такий потворний, як розмиття коробки. Дивіться демонстрацію тут (версія плагіна Java) або тут (версія JavaScript). Цей алгоритм використовується в KDE і Camera + та інших. Він не використовує Accelerate Framework, але це швидко.

Прискорити рамки

  • У сесії "Реалізація залучення інтерфейсу користувача на iOS" від WWDC 2013 Apple пояснює, як створити розмитий фон (о 14:30) та згадує метод, applyLightEffectреалізований у зразковому коді за допомогою Accelerate.framework.

  • GPUImage використовує шейдери OpenGL для створення динамічного розмиття. Він має кілька типів розмиття: GPUImageBoxBlurFilter, GPUImageFastBlurFilter, GaussianSelectiveBlur, GPUImageGaussianBlurFilter. Існує навіть GPUImageiOSBlurFilter, який "повинен повністю повторити ефект розмиття, який надає панель управління iOS 7" ( твіт , стаття ). Стаття детальна та інформативна.

    - (UIImage *) розмиттяGPUImage: (UIImage *) зображення зBlurLevel: (NSInteger) розмиття {
        GPUImageFastBlurFilter * blurFilter = [GPUImageFastBlurFilter new];
        blurFilter.blurSize = розмиття;
        UIImage * результат = [blurFilter imageByFilteringImage: image];
        повернутий результат;
    }
  • З indieambitions.com: виконайте розмиття за допомогою vImage . Алгоритм також використовується в iOS-RealTimeBlur .

  • Від Ніка Локвуда: https://github.com/nicklockwood/FXBlurView Приклад показує розмиття над поданням прокрутки. Він розмивається з dispatch_async, потім синхронізує виклики оновлень за допомогою UITrackingRunLoopMode, щоб розмиття не відставало, коли UIKit надає більше пріоритету прокрутці UIScrollView. Це пояснено в книзі Ніка iOS Core Animation , яка все-таки чудово.

  • iOS-blur Це займає розмиття шару панелі UITool і розміщує його в іншому місці. Якщо ви використовуєте цей метод, Apple відхилить вашу програму. Дивіться https://github.com/mochidev/MDBlurView/isissue/4

  • З блогу Evadne: LiveFrost: Швидкий, синхронний знімок UIView . Чудовий код та чудове читання. Деякі ідеї з цієї публікації:

    • Використовуйте послідовну чергу, щоб заглушити оновлення з CADisplayLink.
    • Використовуйте контексти растрових зображень, якщо не змінюються межі.
    • Малюйте менші зображення за допомогою - [CALayer renderInContext:] з коефіцієнтом масштабу 0,5f.

Інші речі

Енді Матущак сказав у Twitter: "Ви знаєте, багато місць, де схоже, що ми це робимо в режимі реального часу, це статично з розумними хитрощами".

На сайті Doubleencore.com кажуть: "Ми виявили, що радіус розмиття на 10 пт плюс збільшення насичення на 10 пт найкраще імітує ефект розмиття iOS 7 за більшості обставин".

Зазирнути до приватних заголовків Apple SBFProceduralWallpaperView від Apple .

Нарешті, це не справжнє розмиття, але пам’ятайте, що ви можете встановити rasterizationScale, щоб отримати піксельне зображення: http://www.dimzzy.com/blog/2010/11/blur-effect-for-uiview/


Дякуємо за відповідь! Одна проблема вирішена. Але у нас є ще одна проблема. Як отримати зображення обкладинки в iOS 7. Якщо це можливо?
кондратьевдев

Якщо ви маєте на увазі, як отримати фонове зображення шпалери з телефону, наразі ідеї немає. Я не бачив, що функціональність в API відрізняється . Можливо, він використовує приватний API.
Яно

Одне, що я помітив (і я можу бути абсолютно невірним) - це те, що розмиття Apple, як видається, також додає трохи насиченості кольорів. Отже, я не думаю, що це проста гауссова розмитість.
xtravar

Пам’ятайте про коефіцієнт масштабу, повертаючи UIImageінакше, він буде виглядати занадто великим на пристрої Retina ...
Стівен Дарлінгтон

Чи знаєте ви, чи можна застосувати такий ефект до UITableViewCell без погіршення продуктивності?
Леонардо

15

Я вирішив опублікувати письмову версію Objective-C із прийнятої відповіді, просто щоб надати більше варіантів цього питання.

- (UIView *)applyBlurToView:(UIView *)view withEffectStyle:(UIBlurEffectStyle)style andConstraints:(BOOL)addConstraints
{
  //only apply the blur if the user hasn't disabled transparency effects
  if(!UIAccessibilityIsReduceTransparencyEnabled())
  {
    UIBlurEffect *blurEffect = [UIBlurEffect effectWithStyle:style];
    UIVisualEffectView *blurEffectView = [[UIVisualEffectView alloc] initWithEffect:blurEffect];
    blurEffectView.frame = view.bounds;

    [view addSubview:blurEffectView];

    if(addConstraints)
    {
      //add auto layout constraints so that the blur fills the screen upon rotating device
      [blurEffectView setTranslatesAutoresizingMaskIntoConstraints:NO];

      [view addConstraint:[NSLayoutConstraint constraintWithItem:blurEffectView
                                                       attribute:NSLayoutAttributeTop
                                                       relatedBy:NSLayoutRelationEqual
                                                          toItem:view
                                                       attribute:NSLayoutAttributeTop
                                                      multiplier:1
                                                        constant:0]];

      [view addConstraint:[NSLayoutConstraint constraintWithItem:blurEffectView
                                                       attribute:NSLayoutAttributeBottom
                                                       relatedBy:NSLayoutRelationEqual
                                                          toItem:view
                                                       attribute:NSLayoutAttributeBottom
                                                      multiplier:1
                                                        constant:0]];

      [view addConstraint:[NSLayoutConstraint constraintWithItem:blurEffectView
                                                       attribute:NSLayoutAttributeLeading
                                                       relatedBy:NSLayoutRelationEqual
                                                          toItem:view
                                                       attribute:NSLayoutAttributeLeading
                                                      multiplier:1
                                                        constant:0]];

      [view addConstraint:[NSLayoutConstraint constraintWithItem:blurEffectView
                                                       attribute:NSLayoutAttributeTrailing
                                                       relatedBy:NSLayoutRelationEqual
                                                          toItem:view
                                                       attribute:NSLayoutAttributeTrailing
                                                      multiplier:1
                                                        constant:0]];
    }
  }
  else
  {
    view.backgroundColor = [[UIColor blackColor] colorWithAlphaComponent:0.7];
  }

  return view;
}

Обмеження можуть бути усунені, якщо ви хочете мати обробку, якщо ви підтримуєте лише портретний режим або я просто додаю прапор до цієї функції, щоб використовувати їх чи ні.


1
для нових людей (мене), одним із способів викликати вищевказаний метод є: [self applyBlurToView: self.view withEffectStyle: UIBlurEffectStyleDark andConstraints: YES]; (дякую
NorthBlast

14

Я не думаю, що мені дозволено публікувати код, але вищезгаданий пост із згадкою коду зразка WWDC є правильним. Ось посилання: https://developer.apple.com/downloads/index.action?name=WWDC%202013

Файл, який ви шукаєте, є категорією на UIImage, а метод - ApplyLightEffect.

Як я вже зазначав вище в коментарі, Apple Blur має насичення та інші речі, крім розмитості. Просте розмиття не обійдеться ... якщо ви хочете наслідувати їхній стиль.


8
Це посилання розірвано. Ось правильне посилання: developer.apple.com/downloads/index.action?name=WWDC%202013
olivaresF

Зауважте, що для цього прикладу коду потрібні XCode 5.0 та iOS SDK 7.0 (які ще не оприлюднені)
Майк Гледхілл

Дякую за виправлене посилання, проте в ньому є кілька зразкових кодів, який містить відповідну категорію UIImage?
Леонардо

1
@Leonardo iOS_RunningWithASnap.zip
John Starr Dewar

1
... або iOS_UIImageEffects.zip конкретніше саме це.
Джон Старр Девар

9

Я думаю, що найпростішим рішенням цього є перекриття UIToolbar, який розмиває все, що знаходиться за ним в iOS 7. Це досить проникливо, але для вас це дуже просто, і це швидко!

Ви можете зробити це з будь-яким видом, просто перетворіть його в підклас UIToolbarзамість UIView. Ви навіть можете це зробити із властивістю UIViewController' view, наприклад, ...

1) створити новий клас, який є "підкласом", UIViewControllerі встановіть прапорець "З XIB для інтерфейсу користувача".

2) Виберіть Перегляд та перейдіть до інспектора посвідчення особи на правій панелі (alt-command-3). Змініть "Клас" на UIToolbar. Тепер перейдіть до інспектора атрибутів (alt-command-4) і змініть колір "Фон" на "Очистити колір".

3) Додайте підзор до основного виду та підключіть його до IBOutlet у своєму інтерфейсі. Назвіть це backgroundColorView. Це буде виглядати приблизно так, як приватна категорія у .mфайлі реалізації ( ).

@interface BlurExampleViewController ()
@property (weak, nonatomic) IBOutlet UIView *backgroundColorView;
@end

4) Перейдіть до .mфайлу реалізації ( ) контролера перегляду та змініть -viewDidLoadметод, щоб виглядати наступним чином:

- (void)viewDidLoad
{
    [super viewDidLoad];
    self.view.barStyle = UIBarStyleBlack; // this will give a black blur as in the original post
    self.backgroundColorView.opaque = NO;
    self.backgroundColorView.alpha = 0.5;
    self.backgroundColorView.backgroundColor = [UIColor colorWithWhite:0.3 alpha:1];
}

Це дасть вам темно-сірий вигляд, який розмиває все за ним. Немає смішного бізнесу, жодного повільного розмивання основного зображення, використовуючи все, що під рукою, передбачене ОС / SDK.

Ви можете додати погляд цього контролера подання до іншого виду, як показано нижче:

[self addChildViewController:self.blurViewController];
[self.view addSubview:self.blurViewController.view];
[self.blurViewController didMoveToParentViewController:self];

// animate the self.blurViewController into view

Повідомте мене, якщо щось незрозуміле, я з радістю допоможу!


Редагувати

Панель UITool була змінена в 7.0.3, щоб дати можливий небажаний ефект при використанні кольорової розмитості.

Раніше ми могли встановлювати колір за допомогою barTintColor, але якщо ви робили це раніше, вам потрібно буде встановити альфа-компонент менше 1. Інакше панель UITool буде повністю непрозорим кольором - без розмиття.

Цього можна досягти так: (маючи на увазі selfпідклас UIToolbar)

UIColor *color = [UIColor blueColor]; // for example
self.barTintColor = [color colorWithAlphaComponent:0.5];

Це додасть блакитного відтінку розмитому вигляду.


1
Непогана людина. Я використовував ці три рядки на мою думку: self.backgroundColorView.opaque = NO; self.backgroundColorView.alpha = 0.5; self.backgroundColorView.backgroundColor = [UIColor colorWithWhite:0.3 alpha:1];Але фон не розмитий, просто приємний ефект. дякую все одно!
IgniteCoders

1
Я взагалі не бачу розмиття, використовуючи цю техніку. Це просто створює кольорову накладку.
MusiGenesis

переконайтеся, що кольоровий альфа-накладення менше 1. Ви можете використовувати панель UITool без контролера перегляду, що може бути простішим залежно від того, що вам потрібно.
Сам

акуратний трюк людини. Я перетворив свій погляд на клас UIToolbar на аркуші розкадрування, а потім змінив фон подання на чіткий колір. Це дало білий розмитий фон. Якщо альфа зробити менше 1, ефект розмитості зникне.
Бадр

9

Ось швидка реалізація в Swift за допомогою CIGaussianBlur:

func blur(image image: UIImage) -> UIImage {
    let radius: CGFloat = 20;
    let context = CIContext(options: nil);
    let inputImage = CIImage(CGImage: image.CGImage!);
    let filter = CIFilter(name: "CIGaussianBlur");
    filter?.setValue(inputImage, forKey: kCIInputImageKey);
    filter?.setValue("\(radius)", forKey:kCIInputRadiusKey);
    let result = filter?.valueForKey(kCIOutputImageKey) as! CIImage;
    let rect = CGRectMake(radius * 2, radius * 2, image.size.width - radius * 4, image.size.height - radius * 4)
    let cgImage = context.createCGImage(result, fromRect: rect);
    let returnImage = UIImage(CGImage: cgImage);

    return returnImage;
}

7

Спеціальна шкала розмиття

Ви можете спробувати UIVisualEffectView зі спеціальним налаштуванням як -

class BlurViewController: UIViewController {
    private let blurEffect = (NSClassFromString("_UICustomBlurEffect") as! UIBlurEffect.Type).init()

    override func viewDidLoad() {
        super.viewDidLoad()
        let blurView = UIVisualEffectView(frame: UIScreen.main.bounds)
        blurEffect.setValue(1, forKeyPath: "blurRadius")
        blurView.effect = blurEffect
        view.addSubview(blurView)
    }   
}

Вихід: - для blurEffect.setValue(1...& blurEffect.setValue(2.. введіть тут опис зображення введіть тут опис зображення


3
Він припинить роботу, якщо в наступній версії iOS ім'я цього параметра буде змінено.
Аріель Богдзевич

@ArielBogdziewicz наразі працює. я оновлю, якщо в wwdc є будь-які варіанти API.
Джек

Гм ... ні, ви ніколи не хочете отримувати доступ до приватних API. Вони приватні чомусь. Вони зміниться, вони зламаються, та / або Apple відхилить ваш додаток. Скористайтеся іншим методом, є багато. Кудо для пошуку зламу, але, не рекомендується.
n13

@Jack Дякую вам за цю відповідь! Це єдине рішення, яке я знайшов у своїй проблемі: розмивання подання відповідно до положення іншого погляду. Однак у мене все ще є інше питання. Чи є спосіб, щоб я міг додати яскравість поверх мого UIBlurEffect? Якщо так, то як? Чи потрібно мені створити інший вигляд для цього поверх мого blurView? Я намагався так, але це завжди виходило з ладу, коли я користувався, (NSClassFromString("_UICustomVibrancyEffect") as! UIVibrancyEffect.Type).init()дійсно оцінив би допомогу!
Моріц

@Moritz не пробував. Але це має працювати. Ви можете спробувати перевірити.
Джек

7

Ось простий спосіб додати нестандартну розмитість, не торкаючись приватних API за допомогою UIViewPropertyAnimator :

По-перше, оголосити властивість класу:

var blurAnimator: UIViewPropertyAnimator!

Потім встановіть перегляд розмиття в viewDidLoad():

let blurEffectView = UIVisualEffectView()
blurEffectView.backgroundColor = .clear
blurEffectView.frame = view.bounds
blurEffectView.autoresizingMask = [.flexibleWidth, .flexibleHeight]
view.addSubview(blurEffectView)

blurAnimator = UIViewPropertyAnimator(duration: 1, curve: .linear) { [blurEffectView] in
    blurEffectView.effect = UIBlurEffect(style: .light)
}

blurAnimator.fractionComplete = 0.15 // set the blur intensity.    

Примітка. Цей розчин не підходить для UICollectionView/ UITableViewклітин


1
Це єдине рішення, яке я знайшов, якщо ви хочете контролювати прозорість UIVisualEffectView.
Денис Кутлубаєв

6

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

З Xcode ви можете це легко зробити. Виконайте кроки з xcode. Драговий візуальний ефект на ваш uiview або перегляд зображення.

Щасливе кодування :)


5

Прийнята відповідь правильна, але тут відсутній важливий крок, якщо цей вид - для якого потрібно розмитий фон - представлений за допомогою

[self presentViewController:vc animated:YES completion:nil]

За замовчуванням це зменшить розмиття, оскільки UIKit видаляє подання презентатора, яке ви насправді розмиває. Щоб уникнути цього видалення, додайте цей рядок перед попереднім

vc.modalPresentationStyle = UIModalPresentationOverFullScreen;

Або використовувати інші Overстилі.


3

ЗАВДАННЯ-С

UIVisualEffect *blurEffect;
blurEffect = [UIBlurEffect effectWithStyle:UIBlurEffectStyleDark];
UIVisualEffectView *visualEffectView;
visualEffectView = [[UIVisualEffectView alloc] initWithEffect:blurEffect];
visualEffectView.frame = self.accessImageView.bounds;
[self.accessImageView addSubview:visualEffectView];

SWIFT 3.0

let blurEffect = UIBlurEffect(style: UIBlurEffectStyle.dark)
let blurEffectView = UIVisualEffectView(effect: blurEffect)
blurEffectView.frame = view.bounds
blurEffectView.autoresizingMask = [.flexibleWidth, .flexibleHeight]
view.addSubview(blurEffectView)

з: https://stackoverflow.com/a/24083728/4020910


2

Використання UIImageEffects

Для людей, які хочуть більшого контролю, ви можете використати UIImageEffectsзразок коду Apple .

Ви можете скопіювати код UIImageEffectsз бібліотеки розробників Apple: Розмивання та тонування зображення

А ось як його застосувати:

#import "UIImageEffects.h"
...

self.originalImageView.image = [UIImageEffects imageByApplyingLightEffectToImage:[UIImage imageNamed:@"yourImage.png"]];

Як мені це
скоріше

2
func blurBackgroundUsingImage(image: UIImage)
{
    var frame                   = CGRectMake(0, 0, self.view.frame.width, self.view.frame.height)
    var imageView               = UIImageView(frame: frame)
    imageView.image             = image
    imageView.contentMode       = .ScaleAspectFill
    var blurEffect              = UIBlurEffect(style: .Light)
    var blurEffectView          = UIVisualEffectView(effect: blurEffect)
    blurEffectView.frame        = frame
    var transparentWhiteView    = UIView(frame: frame)
    transparentWhiteView.backgroundColor = UIColor(white: 1.0, alpha: 0.30)
    var viewsArray              = [imageView, blurEffectView, transparentWhiteView]

    for index in 0..<viewsArray.count {
        if let oldView = self.view.viewWithTag(index + 1) {
            var oldView         = self.view.viewWithTag(index + 1)
            // Must explicitly unwrap oldView to access its removeFromSuperview() method as of Xcode 6 Beta 5
            oldView!.removeFromSuperview()
        }
        var viewToInsert        = viewsArray[index]
        self.view.insertSubview(viewToInsert, atIndex: index + 1)
        viewToInsert.tag        = index + 1
    }
}

1

Виявлений це випадково, дає мені справді чудові (майже дублікат з Apple) результати та використовує рамку Acceleration. - http://pastebin.com/6cs6hsyQ * Не написано мною


8
Це насправді код Apple від WWDC 2013 з неправильним авторським правом.
Шмідт

Чи не коди від WWDC захищені авторським правом, і доступ дозволений лише учасникам з платними підписками?
SAFAD

1
Можливо, але код вище я знайшов за допомогою Google. Я не змінив авторське право, і я припустив (і досі припускаю), що він має правильну претензію на авторське право. Якщо Apple не погоджується, вони повинні докласти зусиль, щоб зняти це. Я не бачу відповідності.
Джейк

1

Ця відповідь ґрунтується на чудовій попередній відповіді Мітья Семоліча . Я перетворив його на швидкий 3, додав пояснення до того, що відбувається в коментарях, зробив це розширенням UIViewController, щоб будь-який ВК міг викликати його за бажанням, додав незрозумілий вигляд для показу селективного додатка та додав блок завершення, щоб Після завершення розмиття контролер подання виклику може робити все, що завгодно.

    import UIKit
//This extension implements a blur to the entire screen, puts up a HUD and then waits and dismisses the view.
    extension UIViewController {
        func blurAndShowHUD(duration: Double, message: String, completion: @escaping () -> Void) { //with completion block
            //1. Create the blur effect & the view it will occupy
            let blurEffect = UIBlurEffect(style: UIBlurEffectStyle.light)
            let blurEffectView = UIVisualEffectView()//(effect: blurEffect)
            blurEffectView.frame = self.view.bounds
            blurEffectView.autoresizingMask = [.flexibleWidth, .flexibleHeight]

        //2. Add the effect view to the main view
            self.view.addSubview(blurEffectView)
        //3. Create the hud and add it to the main view
        let hud = HudView.getHUD(view: self.view, withMessage: message)
        self.view.addSubview(hud)
        //4. Begin applying the blur effect to the effect view
        UIView.animate(withDuration: 0.01, animations: {
            blurEffectView.effect = blurEffect
        })
        //5. Halt the blur effects application to achieve the desired blur radius
        self.view.pauseAnimationsInThisView(delay: 0.004)
        //6. Remove the view (& the HUD) after the completion of the duration
        DispatchQueue.main.asyncAfter(deadline: .now() + duration) {
            blurEffectView.removeFromSuperview()
            hud.removeFromSuperview()
            self.view.resumeAnimationsInThisView()
            completion()
        }
    }
}

extension UIView {
    public func pauseAnimationsInThisView(delay: Double) {
        let time = delay + CFAbsoluteTimeGetCurrent()
        let timer = CFRunLoopTimerCreateWithHandler(kCFAllocatorDefault, time, 0, 0, 0, { timer in
            let layer = self.layer
            let pausedTime = layer.convertTime(CACurrentMediaTime(), from: nil)
            layer.speed = 0.0
            layer.timeOffset = pausedTime
        })
        CFRunLoopAddTimer(CFRunLoopGetCurrent(), timer, CFRunLoopMode.commonModes)
    }
    public func resumeAnimationsInThisView() {
        let pausedTime  = layer.timeOffset

        layer.speed = 1.0
        layer.timeOffset = 0.0
        layer.beginTime = layer.convertTime(CACurrentMediaTime(), from: nil) - pausedTime
    }
}

Я підтвердив, що він працює як з iOS 10.3.1, так і з iOS 11


1

Важливе доповнення до відповіді @ Joey

Це відноситься до ситуації , коли ви хочете , щоб представити помутніння-фон UIViewControllerз UINavigationController.

// suppose you've done blur effect with your presented view controller
UINavigationController *nav = [[UINavigationController alloc] initWithRootViewController];

// this is very important, if you don't do this, the blur effect will darken after view did appeared
// the reason is that you actually present navigation controller, not presented controller
// please note it's "OverFullScreen", not "OverCurrentContext"
nav.modalPresentationStyle = UIModalPresentationOverFullScreen;

UIViewController *presentedViewController = [[UIViewController alloc] init]; 
// the presented view controller's modalPresentationStyle is "OverCurrentContext"
presentedViewController.modalPresentationStyle = UIModalPresentationOverCurrentContext;

[presentingViewController presentViewController:nav animated:YES completion:nil];

Насолоджуйтесь!


1

Swift 3 Версія відповіді Кева, щоб повернути розмите зображення -

func blurBgImage(image: UIImage) -> UIImage? {
        let radius: CGFloat = 20;
        let context = CIContext(options: nil);
        let inputImage = CIImage(cgImage: image.cgImage!);
        let filter = CIFilter(name: "CIGaussianBlur");
        filter?.setValue(inputImage, forKey: kCIInputImageKey);
        filter?.setValue("\(radius)", forKey:kCIInputRadiusKey);

        if let result = filter?.value(forKey: kCIOutputImageKey) as? CIImage{

            let rect = CGRect(origin: CGPoint(x: radius * 2,y :radius * 2), size: CGSize(width: image.size.width - radius * 4, height: image.size.height - radius * 4))

            if let cgImage = context.createCGImage(result, from: rect){
                return UIImage(cgImage: cgImage);
                }
        }
        return nil;
    }

1

Код 2019 року

Ось більш повний приклад використання дивовижної техніки @AdamBardon.

@IBDesignable class ButtonOrSomethingWithBlur: UIButton {

    var ba: UIViewPropertyAnimator?
    private lazy var blurry: BlurryBall = { return BlurryBall() }()

    override func didMoveToSuperview() {
        super.didMoveToSuperview()

        // Setup the blurry ball.  BE SURE TO TEARDOWN.
        // Use superb trick to access the internal guassian level of Apple's
        // standard gpu blurrer per stackoverflow.com/a/55378168/294884

        superview?.insertSubview(blurry, belowSubview: self)
        ba = UIViewPropertyAnimator(duration:1, curve:.linear) {[weak self] in
            // note, those duration/curve values are simply unusued
            self?.blurry.effect = UIBlurEffect(style: .extraLight)
        }
        ba?.fractionComplete = live.largeplaybutton_blurfactor
    }

    override func willMove(toSuperview newSuperview: UIView?) {

        // Teardown for the blurry ball - critical

        if newSuperview == nil { print("safe teardown")
            ba?.stopAnimation(true)
            ba?.finishAnimation(at: .current)
        }
    }

    override func layoutSubviews() { super.layoutSubviews()
        blurry.frame = bounds, your drawing frame or whatever
    }

{Убік: як загальна інженерна справа iOS, didMoveToWindowможливо, вам більше підходить, ніж didMoveToSuperview. По-друге, ви можете скористатися яким-небудь іншим способом здійснити скульптуру, але тереном є два рядки коду, показані там.}

BlurryBallце просто а UIVisualEffectView. Помітьте вставки для перегляду візуальних ефектів. Якщо вам потрібні закруглені куточки чи що завгодно, зробіть це в цьому класі.

class BlurryBall: UIVisualEffectView {

    override init(effect: UIVisualEffect?) { super.init(effect: effect)
        commonInit() }

    required init?(coder aDecoder: NSCoder) { super.init(coder: aDecoder)
        commonInit() }

    private func commonInit() {
        clipsToBounds = true
        backgroundColor = .clear
    }

    override func layoutSubviews() {
        super.layoutSubviews()
        layer.cornerRadius = bounds.width / 2
    }
}


0

Ось код Swift 2.0 для рішення, яке було надано у прийнятій відповіді :

    //only apply the blur if the user hasn't disabled transparency effects
    if !UIAccessibilityIsReduceTransparencyEnabled() {
        self.view.backgroundColor = UIColor.clearColor()

        let blurEffect = UIBlurEffect(style: UIBlurEffectStyle.Dark)
        let blurEffectView = UIVisualEffectView(effect: blurEffect)
        //always fill the view
        blurEffectView.frame = self.view.bounds
        blurEffectView.autoresizingMask = [.FlexibleWidth, .FlexibleHeight]

        self.view.addSubview(blurEffectView) //if you have more UIViews, use an insertSubview API to place it where needed
    } else {
        self.view.backgroundColor = UIColor.blackColor()
    }

0

Якщо ви додасте подання темного розмиття для tableView, це прекрасно зробить це:

tableView.backgroundColor = .clear
let blurEffect = UIBlurEffect(style: .dark)
let blurEffectView = UIVisualEffectView(effect: blurEffect)
blurEffectView.frame = tableView.bounds
blurEffectView.autoresizingMask = [.flexibleHeight, .flexibleWidth]


// Assigning blurEffectView to backgroundView instead of addSubview to tableView makes tableView cell not blocked by blurEffectView 
tableView.backgroundView = blurEffectView

0

Ви можете безпосередньо зробити розмитість фону, використовуючи "Перегляд візуальних ефектів із розмиттям" та "Перегляд візуальних ефектів із розмиттям та яскравістю".

Все, що вам потрібно зробити для створення розмиття фону в додатку iOS, це ...

  1. Перейдіть і шукайте "Перегляд візуальних ефектів із розмиттям" у бібліотеці об'єктів

Крок 1 Зображення

  1. Перетягніть "Перегляд візуальних ефектів із розмиттям" у вашій дошці та налаштуйте його ...

Крок 2 Зображення

  1. Нарешті ... Ви робите розмиття фону програми!

Макет програми перед натисканням будь-якої кнопки!

Перегляд програми після натискання на кнопку, яка робить розмиття всього фону програми!


0

Якщо це допомагає кому-небудь, ось швидке розширення, яке я створив на основі відповіді Джордана Х. Він написаний у Swift 5 і може бути використаний з Цілі C.

extension UIView {

    @objc func blurBackground(style: UIBlurEffect.Style, fallbackColor: UIColor) {
        if !UIAccessibility.isReduceTransparencyEnabled {
            self.backgroundColor = .clear

            let blurEffect = UIBlurEffect(style: style)
            let blurEffectView = UIVisualEffectView(effect: blurEffect)
            //always fill the view
            blurEffectView.frame = self.self.bounds
            blurEffectView.autoresizingMask = [.flexibleWidth, .flexibleHeight]

            self.insertSubview(blurEffectView, at: 0)
        } else {
            self.backgroundColor = fallbackColor
        }
    }

}

ПРИМІТКА. Якщо ви хочете розмити фон UILabel, не впливаючи на текст, вам слід створити контейнер UIView, додати UILabel до контейнера UIView як підпрез, встановити фон UILabelColor на UIColor.clear, а потім викликати blurBackground (стиль : UIBlurEffect.Style, backbackColor: UIColor) на контейнері UIView. Ось короткий приклад цього написаного в Swift 5:

let frame = CGRect(x: 50, y: 200, width: 200, height: 50)
let containerView = UIView(frame: frame)
let label = UILabel(frame: frame)
label.text = "Some Text"
label.backgroundColor = UIColor.clear
containerView.addSubview(label)
containerView.blurBackground(style: .dark, fallbackColor: UIColor.black)

-1

Швидкий 4:

Щоб додати накладення або спливаюче вікно Ви також можете скористатися переглядом контейнерів, за допомогою якого ви отримаєте безкоштовний контролер перегляду (ви отримаєте перегляд контейнера зі звичайної палітри об’єктів / бібліотеки)

Кроки:

Майте перегляд (ViewForContainer на знімку), який містить цей перегляд контейнерів, щоб затемнити його, коли відображається вміст перегляду контейнерів. Підключіть розетку всередині першого контролера подання

Сховати цей вид при завантаженні 1-го ВК

Відхиляйте, коли натискаєте кнопку, введіть тут опис зображення

Щоб затемнити цей вигляд, коли відображається вміст перегляду контейнера, встановіть «Перегляд фону» на чорний, а непрозорість - 30%

Я додав відповідь на створення перегляду popview в іншому запитанні Stackoverflow https://stackoverflow.com/a/49729431/5438240


-3

Проста відповідь - Додайте підвід і змініть його на альфа.

UIView *mainView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 200, 200)];
UIView *subView = [[UIView alloc] initWithFrame:popupView.frame];
UIColor * backImgColor = [UIColor colorWithPatternImage:[UIImage imageNamed:@"blue_Img.png"]];
subView.backgroundColor = backImgColor;
subView.alpha = 0.5;
[mainView addSubview:subView];
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.