Tworzenie rozmytego widoku nakładki


Odpowiedzi:


552

Możesz użyć, UIVisualEffectViewaby osiągnąć ten efekt. Jest to natywny interfejs API, który został precyzyjnie dostrojony pod kątem wydajności i żywotności baterii, a ponadto jest łatwy do wdrożenia.

Szybki:

//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
}

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

Jeśli prezentujesz ten kontroler widoku modalnie, aby rozmyć zawartą pod nim zawartość, musisz ustawić modalny styl prezentacji na Over Current Context i ustawić kolor tła, aby wyczyścić, aby upewnić się, że bazowy kontroler widoku pozostanie widoczny, gdy zostanie on zaprezentowany na wierzchu.


7
Jako wyjaśnienie insertSubView:belowSubView:komentarza w tym kodzie użyłem następującego ustawienia, aby ustawić rozmycie jako tło widoku:view.insertSubview(blurEffectView, atIndex: 0)
Michael Voccola

2
W odniesieniu do powyższej odpowiedzi, czy konieczne jest sprawdzenie „if (! UIAccessibilityIsReduceTransparencyEnabled ())” czy możemy to pominąć?
GKK

3
Jeśli prezentujesz swój kontroler widoku, upewnij się, że zmieniłeś modalPresentationStyle = .overCurrentContext wraz z ustawieniem koloru tła jako wyraźnego
Shardul,

3
Działa świetnie !!! Potrzebujesz pojedynczej zmiany: [self.view insertSubview: blurEffectView atIndex: 1];
Abhishek Thapliyal

2
W iOS 11 uważam, że nie trzeba ręcznie sprawdzać UIAccessibilityIsReduceTransparencyEnabled().
Nate Whittaker,

284

Obraz podstawowy

Ponieważ ten obraz na zrzucie ekranu jest statyczny, możesz użyć go CIGaussianBlurz Core Image (wymaga iOS 6). Oto przykład: https://github.com/evanwdavis/Fun-with-Masks/blob/master/Fun%20with%20Masks/EWDBlurExampleVC.m

Pamiętaj, że jest to wolniejsze niż inne opcje na tej stronie.

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

Rozmycie stosu (pudełko + gaussa)

  • StackBlur Implementuje połączenie rozmycia pola i gaussa . 7 razy szybszy niż nieprzyspieszony gaussian, ale nie tak brzydki jak rozmycie pola. Zobacz wersję demo tutaj (wersja wtyczki Java) lub tutaj (wersja JavaScript). Ten algorytm jest używany w KDE i Camera + i innych. Nie korzysta z Accelerate Framework, ale jest szybki.

Accelerate Framework

  • W sesji „Implementing Engaging UI na iOS” z WWDC 2013 Apple wyjaśnia, jak utworzyć rozmyte tło (o 14:30) i wspomina o metodzie applyLightEffectzaimplementowanej w przykładowym kodzie przy użyciu Accelerate.framework.

  • GPUImage używa shaderów OpenGL do tworzenia dynamicznych rozmyt. Ma kilka rodzajów rozmycia: GPUImageBoxBlurFilter, GPUImageFastBlurFilter, GaussianSelectiveBlur, GPUImageGaussianBlurFilter. Istnieje nawet GPUImageiOSBlurFilter, który „powinien w pełni powielać efekt rozmycia zapewniany przez panel sterowania iOS 7” ( tweet , artykuł ). Artykuł jest szczegółowy i zawiera wiele informacji.

    - (UIImage *) blurryGPUImage: (UIImage *) obraz z BlurLevel: (NSInteger) rozmycie {
        GPUImageFastBlurFilter * blurFilter = [GPUImageFastBlurFilter nowy];
        blurFilter.blurSize = rozmycie;
        UIImage * result = [blurFilter imageByFilteringImage: image];
        zwróć wynik;
    }

Inne rzeczy

Andy Matuschak powiedział na Twitterze: „Wiesz, w wielu miejscach, w których wygląda na to, że robimy to w czasie rzeczywistym, jest statyczny dzięki sprytnym sztuczkom”.

Na stronie doubleencore.com mówią: „stwierdziliśmy, że promień rozmycia 10 punktów plus wzrost nasycenia o 10 punktów najlepiej naśladuje efekt rozmycia w iOS 7 w większości przypadków”.

Rzut oka na prywatne nagłówki SBFProceduralWallpaperView firmy Apple .

Wreszcie, nie jest to prawdziwe rozmycie, ale pamiętaj, że możesz ustawić rasterizationScale, aby uzyskać obraz w pikselach: http://www.dimzzy.com/blog/2010/11/blur-effect-for-uiview/


Dziękuję za odpowiedź! Jeden problem został rozwiązany. Ale mamy jeszcze jeden problem. Jak uzyskać obraz okładki w iOS 7. Jeśli to możliwe?
kondratyevdev

Jeśli masz na myśli, jak uzyskać tapetę tła z telefonu, w tym momencie nie mam pojęcia. Nie widziałem tej funkcjonalności w różnicach API . Może używa prywatnego API.
Jano

Jedną rzeczą, którą zauważyłem (i mogę się całkowicie mylić) jest to, że rozmycie Apple wydaje się również dodawać trochę nasycenia kolorów. Więc nie sądzę, że to zwykła rozmycie gaussowskie.
xtravar

Zapamiętaj współczynnik skali przy zwrocie, w UIImageprzeciwnym razie będzie wyglądał zbyt duży na urządzeniu Retina ...
Stephen Darlington

Czy wiesz, czy taki efekt można zastosować do UITableViewCell bez obniżenia wydajności?
Leonardo

15

Postanowiłem opublikować pisemną wersję Objective-C z zaakceptowanej odpowiedzi, aby podać więcej opcji w tym pytaniu.

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

Ograniczenia można usunąć, jeśli chcesz zwiększyć, jeśli obsługujesz tylko tryb pionowy lub po prostu dodam flagę do tej funkcji, aby ich użyć, czy nie.


1
dla nowych ludzi (ja) jednym ze sposobów wywołania powyższej metody jest: [self applyBlurToView: self.view withEffectStyle: UIBlurEffectStyleDark andConstraints: YES]; (dziękuję NorthBlast)
tmr

14

Nie sądzę, że wolno mi opublikować kod, ale powyższy post wspominający o przykładowym kodzie WWDC jest poprawny. Oto link: https://developer.apple.com/downloads/index.action?name=WWDC%202013

Plik, którego szukasz, jest kategorią w UIImage, a metodą jest applyLightEffect.

Jak zauważyłem powyżej w komentarzu, Apple Blur ma nasycenie i inne rzeczy dzieją się poza rozmyciem. Proste rozmycie nie zadziała ... jeśli chcesz naśladować ich styl.


8
Ten link jest zepsuty. Oto poprawny link: developer.apple.com/downloads/index.action?name=WWDC%202013
olivaresF

Pamiętaj, że ten przykładowy kod wymaga XCode 5.0 i iOS SDK 7.0 (które nie zostały jeszcze publicznie wydane)
Mike Gledhill

Dzięki za stały link, ale jest w nim kilka przykładowych kodów, które zawierają odpowiednią kategorię UIImage?
Leonardo

1
@Leonardo iOS_RunningWithASnap.zip
John Starr Dewar

1
... lub iOS_UIImageEffects.zip jest właśnie to.
John Starr Dewar

9

Myślę, że najłatwiejszym rozwiązaniem jest zastąpienie paska narzędzi UIToolbar, który rozmywa wszystko za nim w systemie iOS 7. Jest dość podstępny, ale jego wdrożenie jest bardzo proste i szybkie!

Możesz to zrobić z dowolnym widokiem, po prostu uczyń go podklasą UIToolbarzamiast UIView. Można nawet zrobić z UIViewController„s viewnieruchomości, na przykład ...

1) utwórz nową klasę, która jest „podklasą” UIViewControlleri zaznacz pole „Z XIB dla interfejsu użytkownika”.

2) Wybierz Widok i przejdź do inspektora tożsamości w prawym panelu (alt-Command-3). Zmień „Klasa” naUIToolbar . Teraz przejdź do inspektora atrybutów (alt-Command-4) i zmień kolor „Tła” na „Wyczyść kolor”.

3) Dodaj widok podrzędny do widoku głównego i podłącz go do IBOutleta w interfejsie. Nazywają go backgroundColorView. Będzie to wyglądać mniej więcej tak, jako prywatna kategoria w .mpliku implementacji ( ).

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

4) Przejdź do implementacji kontrolera widoku (.m pliku ) i zmień -viewDidLoadmetodę, aby wyglądać następująco:

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

Daje to ciemnoszary widok, który rozmywa wszystko za nim. Żadnego śmiesznego biznesu, żadnego powolnego zamazania obrazu rdzenia, używając wszystkiego, co masz na wyciągnięcie ręki, dostarczonego przez OS / SDK.

Możesz dodać widok tego kontrolera widoku do innego widoku w następujący sposób:

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

// animate the self.blurViewController into view

Daj mi znać, jeśli coś będzie niejasne, chętnie pomogę!


Edytować

Pasek narzędzi UIToolbar został zmieniony w wersji 7.0.3, aby dać możliwie niepożądany efekt przy użyciu kolorowego rozmycia.

Kiedyś mogliśmy ustawić kolor za pomocą barTintColor , ale jeśli robiłeś to wcześniej, musisz ustawić składnik alfa na mniej niż 1. W przeciwnym razie pasek narzędzi UITool będzie całkowicie nieprzezroczysty - bez rozmycia.

Można to osiągnąć w następujący sposób: (mając na uwadze selfpodklasę UIToolbar)

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

To nada rozmytemu widokowi niebieskawy odcień.


1
Niezły człowiek. Moim zdaniem użyłem tych trzech linii: self.backgroundColorView.opaque = NO; self.backgroundColorView.alpha = 0.5; self.backgroundColorView.backgroundColor = [UIColor colorWithWhite:0.3 alpha:1];ale tło nie jest rozmyte, po prostu daj ładny efekt. i tak dziękuję!
IgniteCoders,

1
Nie widzę żadnego rozmycia przy użyciu tej techniki. Po prostu tworzy kolorową nakładkę.
MusiGenesis

upewnij się, że kolorowa nakładka alfa jest mniejsza niż 1. Możesz użyć paska narzędzi UITool bez kontrolera widoku, co może być prostsze w zależności od potrzeb.
Sam

schludny sztuczka. Przekształciłem mój widok na klasę UIToolbar w serii ujęć, a następnie zmieniłem tło widoku na czysty kolor. Dało białe niewyraźne tło. Jeśli sprawisz, że alfa będzie mniejsze niż 1, efekt rozmycia zniknie.
Badr

9

Oto szybka implementacja w Swift przy użyciu 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

Niestandardowa skala rozmycia

Możesz spróbować UIVisualEffectView z ustawieniem niestandardowym jako -

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)
    }   
}

Wyjście: - dla blurEffect.setValue(1...& blurEffect.setValue(2.. wprowadź opis zdjęcia tutaj wprowadź opis zdjęcia tutaj


3
Przestanie działać, jeśli w następnej wersji iOS nazwa tego parametru zostanie zmieniona.
Ariel Bogdziewicz

@ArielBogdziewicz obecnie działa. zaktualizuję, jeśli istnieje jakaś odmiana API w wwdc.
Jack

Ummm ... nie, nigdy nie chcesz uzyskać dostępu do prywatnych interfejsów API. Z jakiegoś powodu są prywatne. Zmienią się, pękną i / lub Apple odrzuci twoją aplikację. Użyj innej metody, jest mnóstwo. Wyrazy uznania za znalezienie hacka, ale niezalecane.
n13

@ Jack Bardzo dziękuję za tę odpowiedź! To jedyne rozwiązanie mojego problemu: rozmycie widoku zgodnie z pozycją innego widoku. Jednak wciąż mam inne pytanie. Czy jest jakiś sposób, aby dodać energii na moim UIBlurEffect? Jeśli tak to jak? Czy muszę utworzyć inny widok w tym celu na moim blurViewView? Próbowałem tak, ale zawsze się zawiesił, gdy użyłem (NSClassFromString("_UICustomVibrancyEffect") as! UIVibrancyEffect.Type).init()Naprawdę doceniłbym pomoc!
Moritz

@Moritz nie próbował. Ale powinno działać. Możesz spróbować i sprawdzić.
Jack

7

Oto prosty sposób na dodanie niestandardowego rozmycia bez targowania się za pomocą prywatnych interfejsów API za pomocą UIViewPropertyAnimator :

Najpierw zadeklaruj właściwość klasy:

var blurAnimator: UIViewPropertyAnimator!

Następnie ustaw widok rozmycia w 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.    

Uwaga: To rozwiązanie nie jest odpowiednie dla UICollectionView/ UITableViewkomórek


1
Jest to jedyne rozwiązanie, które znalazłem, jeśli chcesz kontrolować przezroczystość UIVisualEffectView.
Denis Kutlubaev

6

wprowadź opis zdjęcia tutaj

Z Xcode możesz to zrobić łatwo. Postępuj zgodnie z instrukcjami z xcode. Widok efektów wizualnych Drage na uiview lub imageview.

Happy Coding :)


5

Zaakceptowana odpowiedź jest poprawna, ale brakuje tutaj ważnego kroku, na wypadek gdyby ten widok - dla którego chcesz uzyskać rozmyte tło - jest prezentowany za pomocą

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

Domyślnie będzie to negować rozmycie, gdy UIKit usuwa widok prezentera, który faktycznie rozmazujesz. Aby uniknąć tego usunięcia, dodaj ten wiersz przed poprzednim

vc.modalPresentationStyle = UIModalPresentationOverFullScreen;

Lub użyj innych Overstylów.


3

CEL C

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)

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


2

Korzystanie z UIImageEffects

Dla osób, które chcą mieć większą kontrolę, możesz skorzystać z UIImageEffectsprzykładowego kodu Apple .

Możesz skopiować kod UIImageEffectsz Biblioteki programistów Apple: Rozmycie i zabarwienie obrazu

A oto jak go zastosować:

#import "UIImageEffects.h"
...

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

Jak korzystać z tego w szybki
devjme

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

Znalazłem to przez przypadek, daje mi naprawdę świetne (prawie duplikaty z Apple) wyniki i używa frameworka. - http://pastebin.com/6cs6hsyQ * Nie napisane przeze mnie


8
W rzeczywistości jest to kod Apple z WWDC 2013 ze złym prawem autorskim.
Shmidt,

kody nie są chronione prawami autorskimi WWDC i dostęp jest dozwolony tylko dla członków z płatnymi subskrypcjami?
SAFAD

1
Być może, ale powyższy kod znalazłem za pomocą Google. Nie zmieniłem prawa autorskiego i założyłem (i nadal zakładam), że ma ono prawną własność. Jeśli Apple się nie zgadza, powinni dołożyć starań, aby go usunąć. Nie widzę znaczenia.
Jake

1

Ta odpowiedź jest oparta na doskonałej wcześniejszej odpowiedzi Mitji Semolic . Przekształciłem go w swift 3, dodałem wyjaśnienie tego, co dzieje się w komentach, uczyniłem go rozszerzeniem UIViewController, aby każdy VC mógł go wywoływać do woli, dodał niewyraźny widok, aby pokazać selektywną aplikację, i dodał blok uzupełniający, aby wywołujący kontroler widoku może zrobić, co chce, po zakończeniu rozmycia.

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

Potwierdziłem, że działa zarówno z iOS 10.3.1, jak i iOS 11


1

Ważny dodatek do odpowiedzi @ Joeya

Odnosi się to do sytuacji, w której chcesz przedstawić niewyraźne-background UIViewControllerz 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];

Cieszyć się!


1

Wersja Swift 3 odpowiedzi Kev, aby zwrócić nieostry obraz -

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

Kod 2019

Oto pełniejszy przykład z wykorzystaniem niesamowitej techniki @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
    }

{Poza tym: ogólnie rzecz biorąc, inżynieria iOS didMoveToWindowmoże być dla Ciebie bardziej odpowiedniadidMoveToSuperview . Po drugie, możesz użyć innego sposobu wykonania porzucenia, ale porzucenie to dwie linie kodu tam pokazane.}

BlurryBalljest po prostu UIVisualEffectView. Zwróć uwagę na widok efektów wizualnych. Jeśli potrzebujesz zaokrąglonych rogów lub cokolwiek innego, zrób to w tej klasie.

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

Oto kod Swift 2.0 dla rozwiązania dostarczonego w zaakceptowanej odpowiedzi :

    //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

Jeśli doda widok ciemnego rozmycia dla tableView, to pięknie sprawi, że:

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

Możesz bezpośrednio rozmyć tło za pomocą „Widoku efektu wizualnego z rozmyciem” i „Widoku efektu wizualnego z rozmyciem i jaskrawością”.

Aby zrobić Rozmycie tła w aplikacji na iOS, wystarczy ...

  1. Idź i wyszukaj „Widok efektu wizualnego z rozmyciem” w bibliotece obiektów

Krok 1 Obraz

  1. Przeciągnij „Widok efektu wizualnego z rozmyciem” na swojej Storyboard i skonfiguruj go ...

Krok 2 Obraz

  1. Wreszcie ... Sprawiasz, że Twoje tło aplikacji się rozmywa!

Układ aplikacji przed kliknięciem dowolnego przycisku!

Widok aplikacji po kliknięciu przycisku, który rozmywa całe tło aplikacji!


0

Na wypadek, gdyby komukolwiek to pomogło, oto szybkie rozszerzenie, które stworzyłem na podstawie odpowiedzi Jordana H. Jest napisane w Swift 5 i może być używane z Celu 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
        }
    }

}

UWAGA: Jeśli chcesz rozmazać tło UILabel bez wpływu na tekst, powinieneś utworzyć UIView kontenera, dodać UILabel do UIView kontenera jako widok podrzędny, ustawić backgroundColor UILabel na UIColor.clear, a następnie wywołać blurBackground (styl : UIBlurEffect.Style, fallbackColor: UIColor) na UIView kontenera. Oto szybki przykład tego napisanego w 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

Swift 4:

Aby dodać nakładkę lub widok wyskakujący Możesz również użyć widoku kontenera, za pomocą którego otrzymujesz bezpłatny kontroler widoku (widok kontenera otrzymujesz ze zwykłej palety / biblioteki obiektów)

Kroki:

Posiadaj widok (ViewForContainer na zdjęciu), który zawiera ten widok kontenera, aby go przyciemnić, gdy wyświetlana jest zawartość widoku kontenera. Podłącz gniazdo do pierwszego kontrolera widoku

Ukryj ten widok po załadowaniu 1. VC

Pokaż po kliknięciu przycisku wprowadź tutaj opis obrazu

Aby przyciemnić ten widok, gdy wyświetlana jest zawartość widoku kontenera, ustaw Tło widoków na Czarne, a krycie na 30%

Dodałem odpowiedź do tworzenia widoku popview w innym pytaniu Stackoverflow https://stackoverflow.com/a/49729431/5438240


-3

Prosta odpowiedź brzmi: dodaj widok podrzędny i zmień go na alfa.

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];
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.