Unschärfeansicht im iOS 7-Stil

113

Kennt jemand Steuerelemente, die die Unschärfeansichten im iOS7-Stil replizieren?

Ich gehe davon aus, dass es eine Art UIView-Unterklasse geben kann, die das Verhalten repliziert.

Ich spreche von diesen Typansichten, die den Hintergrund extrem stark verwischen, so dass sie Pull-Effekte aus der Hintergrundansicht haben.

Geben Sie hier die Bildbeschreibung ein

endy
quelle
6
GPUImage könnte helfen.
Maarten
@Anil dann wird die Frage sein, wann das ios7 SDK veröffentlicht wird, wie ich das tun kann, ohne meine App nur auf ios7 zu beschränken;).
Endy
1
Apple hat eine UIImage-Kategorie veröffentlicht, die genau dies tut. Ich versuche nur, es zu finden.
Fogmeister
1
Der Code ist von der WWDC-Sitzung 201 verlinkt. Er ist auf Github öffentlich. Ich kann ihn einfach nicht finden.
Fogmeister

Antworten:

40

Möglicherweise können Sie dazu etwas wie Bin Zhangs RWBlurPopover ändern . Diese Komponente verwendet mein GPUI-Bild, um eine Gaußsche Unschärfe auf darunter liegende Komponenten anzuwenden, aber Sie können genauso gut eine CIGaussianBlur für dieselbe verwenden. GPUImage könnte jedoch ein Haar schneller sein .

Diese Komponente setzt voraus, dass Sie die Ansicht hinter der von Ihnen präsentierten erfassen können, und hat möglicherweise Probleme mit Ansichten, die hinter diesem Inhalt animiert sind. Die Notwendigkeit, eine Reise durch Core Graphics zu unternehmen, um die Hintergrundansicht zu rastern, verlangsamt die Arbeit, sodass wir wahrscheinlich keinen ausreichend direkten Zugriff haben, um dies auf performante Weise für Überlagerungen von animierten Ansichten tun zu können.

Als Update zu den oben genannten Themen habe ich kürzlich die Unschärfen in GPUImage überarbeitet, um variable Radien zu unterstützen, sodass die Unschärfegröße in der Control Center-Ansicht von iOS 7 vollständig repliziert werden kann. Daraus habe ich die GPUImageiOS7BlurFilter-Klasse erstellt, die die richtige Unschärfegröße und Farbkorrektur enthält, die Apple hier anscheinend verwendet. So wird die Unschärfe von GPUImage (rechts) mit der eingebauten Unschärfe (links) verglichen:

Apples Unschärfe Die Unschärfe von GPUImage

Ich verwende ein 4-faches Downsampling / Upsampling, um die Anzahl der Pixel zu reduzieren, über die die Gaußsche Unschärfe arbeiten muss, sodass ein iPhone 4S mit dieser Operation den gesamten Bildschirm in ungefähr 30 ms verwischen kann.

Sie haben immer noch die Herausforderung, Inhalte auf performante Weise aus Ansichten dahinter in diese Unschärfe zu ziehen.

Brad Larson
quelle
Wie glaubst du, schafft Apple das? Wenn Sie die Kamera-App öffnen und das Control Center (den Einstellungsbildschirm von unten) aufrufen, folgt die Unschärfe dem, was die Kamera sieht.
Schneemann
2
@maq - Es ist hilfreich, unter der Haube Zugriff auf alles im System zu haben. Was jemand, der das Betriebssystem entwickelt, tun kann, unterscheidet sich sehr von dem, was die öffentlichen Schnittstellen uns erlauben.
Brad Larson
3
@maq - Kamera-Feeds speziell, ja. Eine Möglichkeit, dies zu tun, besteht darin, GPUImage zum Einziehen der Kamerarahmen (über AV Foundation) zu verwenden und diese Ausgabe dann sowohl für die Live-Kameraausgabe in eine GPUImageView zu übertragen als auch parallel in eine Gaußsche Unschärfe (und möglicherweise einen Zuschnitt) einzuspeisen um die Position der unscharfen Ansicht abzugleichen) und diese Ausgabe an eine andere GPUImageView, die den unscharfen Inhalt hinter Ihren Steuerelementen anzeigt. Dies ist möglich, weil wir einen schnellen Weg von Kamerabildern zu OpenGL ES haben, aber wir haben nichts Ähnliches für generische UI-Elemente.
Brad Larson
1
Ich mache programmgesteuert einen Screenshot eines UIView und verwende GPUImageGaussianBlurFilter, um einen ähnlichen Effekt zu erzielen, aber das Ergebnis unterscheidet sich stark vom Apple-Stil. Der Filter scheint in einem Raster zu verschwimmen, mit sichtbaren Quadraten überall, wo Apple nur ein glattes Blatt ist.
Schneemann
1
@maq - Stellen Sie sicher, dass Sie den neuesten Code aus dem Repository verwenden, da zuvor ein Fehler bei hohen Unschärferadien aufgetreten ist. Die Unschärfe tastet jedoch standardmäßig nur einen 9-Pixel-Bereich ab. Wenn Sie also den Multiplikator für die Unschärfe über diesen Punkt hinaus erhöhen, werden Artefakte beim Überspringen von Pixeln angezeigt. Dies erfolgt aus Leistungsgründen. Sie können jedoch die Scheitelpunkt- und Fragment-Shader ändern, um eine größere Anzahl von Pixeln abzutasten. Das, oder versuchen Sie, eine CIGaussianBlur anzuwenden, die eine allgemeinere Unschärfeimplementierung aufweist. Eines Tages werde ich diese Unschärfe auf größere Radien ausweiten.
Brad Larson
28

Ich benutze, FXBlurViewwas unter iOS5 + großartig funktioniert

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]

Ich habe es hinzugefügt mit:

FXBlurView *blurView = [[FXBlurView alloc] initWithFrame:CGRectMake(50, 50, 150, 150)];
[self.blurView setDynamic:YES];
[self.view addSubview:self.blurView];
Paul Peelen
quelle
2
Gibt es einen Trick bei der Verwendung von FXBlurView? Ich habe es versucht, aber wir haben auf einem iPhone 5 zu verzögerten Ansichten geführt. Ihr Demo-Projekt funktioniert einwandfrei. Ziemlich seltsam.
Cris
Es hängt davon ab, was Sie tun möchten. Als ich das FXBlurViewauf ein legte, UIScrollViewbekam ich auch ein verzögertes Ergebnis. Ich glaube, das hat damit zu tun, wie die Unschärfe hinzugefügt wird. Apple greift, wenn ich mich nicht irre, direkt auf die GPU zu, wenn es eine eigene Unschärfe verwendet, was wir als Entwickler nicht tun können. Daher ist die @ cprcrack-Lösung hier tatsächlich die beste Lösung.
Paul Peelen
2
Wie haben Sie mit FXBlurView mit Gerätedrehungen umgegangen? Ich präsentiere gerade einen modalen Dialog. Der Dialog selbst dreht sich gut, aber der Hintergrund wird falsch gequetscht (er muss grundsätzlich nach der Drehung aktualisiert werden).
Fatuhoku
1
Natürlich ist FXBlurView eine gute Option, aber wenn es um die CPU-Auslastung geht. als ich andere blurView bevorzuge. Ich verwende dies in meiner UICollectionVIew und UITableView, aber es erhöht meine CPU-Auslastung. Im nächsten Lauf kommentiere ich diese Zuordnungen und es wird normal. Ich hoffe, das wird jemandem helfen.
Vatsal Shukla
27

WARNUNG: In den Kommentaren gab jemand an, dass Apple Apps mit dieser Technik ablehnt. Das ist mir NICHT passiert, sondern nur für Ihre Überlegung.

Dies mag Sie überraschen, aber Sie können eine UIToolbar verwenden , die diesen Standardeffekt bereits enthält (nur iOS 7+). In der Ansicht viewDidLoad des Controllers:

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
quelle
1
Ja, es hat mich überrascht. Ich habe überprüft, dass diese Idee funktioniert. Ich habe nur eine Zeile so geändert viewDidLoad. - (void) viewDidLoad {[super viewDidLoad]; self.view = [[UIToolbar-Zuweisung] initWithFrame: CGRectZero]; } In meinem Fall gestalte ich meine Ansichten programmgesteuert (alter Stil). Ich stimme dieser Lösung zu, da UIToolbar UIView so grundlegend erbt, dass ich in dieser Lösung kein Problem sehe. Ich werde im Laufe der Entwicklung mehr testen und diese Lösung testen.
Ashok
Dies ist eine großartige Idee und scheint wirklich gut zu funktionieren. Ich wünschte, ich hätte mehr Kontrolle, aber das ist so gut wie es nur geht! Das heißt, @SudhirJonathan erwähnte oben einen Link, über den der Autor dies auf die nächste Ebene bringt - ER STEHLT DEN KALAYER von einer UIToolBar und verwendet ihn erneut! Brillant!
David H
2
"Ja wirklich?" Aus welchen Gründen? Es wird keine private API verwendet, und wenn alle innovativen Methoden abgelehnt würden, wären viele Effekte nicht möglich ...
TheEye
Arbeitete auf meinem iOS 7.1 iPhone
Marsant
Gibt es eine Möglichkeit, die Unschärfe zu "lindern"?
Maxisme
13

Seit iOS8 können Sie UIBlurEffect verwenden .

Es gibt gute Beispiele für iOS8Sampler mit UIBlurEffect und UIVibrancyEffect .

VivienCormier
quelle
2
Für die Faulen: UIVisualEffect *blurEffect = [UIBlurEffect effectWithStyle:UIBlurEffectStyleDark]; UIVisualEffectView *blurView = [[UIVisualEffectView alloc] initWithEffect:blurEffect];
Ric Santos
13

Der beste neue Weg, um ein verschwommenes Overlay zu erhalten, ist die Verwendung der neuen iOS 8-Funktion UIVisualEffectView.

UIBlurEffect *effect = [UIBlurEffect effectWithStyle:UIBlurEffectStyleLight];

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

bluredView.frame = self.view.bounds;

[self.view addSubview:bluredView];

Der UIBlurEffect unterstützt drei Arten von Stilen. Dunkel, Hell und ExtraLight.

Jeanette Müller
quelle
1

Sie können eine Klasse mit einer UIToolBar erstellen, die eine Unterklasse von UIView ist, und sie in einem separaten Ansichtscontroller instanziieren. Dieser Ansatz demonstriert eine durchscheinende UIToolBar (von UIView untergeordnet), die Live-Feedback liefert (in diesem Fall für eine 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

Nachdem die obige UIView angepasst wurde, erstellen Sie eine Klasse, die eine Unterklasse eines ViewControllers ist. Unten habe ich eine Klasse erstellt, die eine AVCapture-Sitzung verwendet. Sie müssen AVCaptureSession verwenden, um die in Apple integrierte Kamerakonfiguration zu überschreiben. Auf diese Weise können Sie die durchscheinende UIToolBar aus der YourUIView- Klasse überlagern .

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 n3U7r1no
quelle
Die Antwort scheint völlig unabhängig von der Frage zu sein.
kombinatorisch
@combinatorial Dies ist eine der effizienteren Möglichkeiten, einer anderen Ansichtssteuerung eine transparente Ansicht hinzuzufügen. Ich habe AVCapture-Code eingefügt, um zu zeigen, dass er für Live-Feedback verwendet werden kann, anstatt nur ein verschwommenes Hintergrundbild hinzuzufügen, wie andere Benutzer empfohlen haben.
74U n3U7r1no
Ok, Entschuldigung, vielleicht möchten Sie am Anfang etwas hinzufügen, das den Ansatz und die Gründe für die Verwendung zusammenfasst.
kombinatorischer
@combinatorial Danke
74U n3U7r1no