Chế độ xem mờ kiểu iOS 7


113

Có ai biết về bất kỳ điều khiển nào sẽ tái tạo chế độ xem mờ kiểu iOS7 không.

Tôi giả định có thể có một số loại lớp con UIView sẽ sao chép hành vi.

Tôi đang nói về những chế độ xem kiểu này làm mờ nền cực kỳ dày để chúng có hiệu ứng kéo từ chế độ xem nền.

nhập mô tả hình ảnh ở đây


6
GPUImage có thể hữu ích.
Maarten

@Anil vậy, câu hỏi sẽ là khi ios7 SDK được phát hành, làm cách nào để tôi có thể thực hiện việc này mà không giới hạn ứng dụng của mình chỉ ở ios7;).
endy


1
Apple đã phát hành danh mục UIImage thực hiện chính xác điều này. Chỉ cố gắng tìm nó.
Fogmeister

1
Mã được liên kết từ phiên WWDC 201. Nó công khai trên github, tôi chỉ không thể tìm thấy nó atm.
Fogmeister

Câu trả lời:


40

Bạn có thể sửa đổi một cái gì đó như RWBlurPopover của Bin Zhang để làm điều này. Thành phần đó sử dụng GPUImage của tôi để áp dụng hiệu ứng mờ Gaussian cho các thành phần bên dưới nó, nhưng bạn cũng có thể dễ dàng sử dụng CIGaussianBlur cho điều tương tự. GPUImage có thể nhanh hơn một chút .

Tuy nhiên, thành phần đó dựa vào việc bạn có thể nắm bắt được chế độ xem đằng sau hình ảnh bạn đang trình bày và có thể gặp sự cố với các chế độ xem tạo hoạt ảnh đằng sau nội dung này. Việc phải sử dụng Core Graphics để sắp xếp lại chế độ xem nền sẽ làm mọi thứ chậm lại, vì vậy chúng tôi có thể không có đủ quyền truy cập trực tiếp để có thể thực hiện điều này một cách hiệu quả đối với các lớp phủ trên chế độ xem hoạt ảnh.

Như một bản cập nhật ở trên, gần đây tôi đã làm lại các vết mờ trong GPUImage để hỗ trợ bán kính thay đổi, cho phép sao chép hoàn toàn kích thước mờ trong chế độ xem trung tâm điều khiển của iOS 7. Từ đó, tôi đã tạo lớp GPUImageiOS7BlurFilter đóng gói kích thước mờ và hiệu chỉnh màu thích hợp mà Apple dường như đang sử dụng ở đây. Đây là cách độ mờ của GPUImage (ở bên phải) so với độ mờ được tích hợp sẵn (ở bên trái):

Sự mờ nhạt của Apple Hình ảnh mờ của GPUI

Tôi sử dụng lấy mẫu xuống / lấy mẫu lên 4X để giảm số điểm ảnh mà tính năng làm mờ Gaussian phải hoạt động, vì vậy iPhone 4S có thể làm mờ toàn bộ màn hình trong khoảng 30 mili giây sử dụng thao tác này.

Bạn vẫn gặp khó khăn trong việc làm thế nào để kéo nội dung vào vùng mờ này từ các góc nhìn phía sau màn hình này một cách hiệu quả.


Vậy bạn nghĩ Apple sẽ làm như thế nào? Nếu bạn mở ứng dụng Máy ảnh và kéo Trung tâm điều khiển lên (màn hình cài đặt từ dưới cùng), hiện tượng mờ sẽ theo sau những gì Máy ảnh nhìn thấy.
Snowman

2
@maq - Giúp có quyền truy cập sâu vào mọi thứ trên hệ thống. Những gì ai đó phát triển hệ điều hành có thể làm rất khác với những gì các giao diện công cộng cho phép chúng tôi làm.
Brad Larson

3
@maq - Nguồn cấp dữ liệu máy ảnh cụ thể, có. Một cách để làm điều này sẽ là sử dụng GPUImage để kéo các khung hình máy ảnh (thông qua AV Foundation) và sau đó đưa cả hai đầu ra đó đến GPUImageView cho đầu ra camera trực tiếp và sau đó song song được đưa vào hiệu ứng mờ gaussian (và có thể là cắt để khớp với vị trí của chế độ xem bị mờ) và đầu ra đó tới một GPUImageView khác sẽ hiển thị nội dung bị mờ đằng sau các điều khiển của bạn. Điều đó có thể thực hiện được vì chúng tôi có một đường dẫn nhanh từ khung hình máy ảnh đến OpenGL ES, nhưng chúng tôi không có bất kỳ điều gì tương tự cho các phần tử giao diện người dùng chung.
Brad Larson

1
Tôi đang chụp ảnh màn hình của UIView theo lập trình và sử dụng GPUImageGaussianBlurFilter để cố gắng tạo ra hiệu ứng tương tự, nhưng kết quả rất khác so với kiểu của Apple. Bộ lọc dường như bị mờ trong một lưới, với các ô vuông có thể nhìn thấy ở khắp mọi nơi, trong đó Apple chỉ là một tờ giấy trơn.
Snowman

1
@maq - Đảm bảo rằng bạn đang sử dụng mã mới nhất từ ​​kho lưu trữ vì trước đó đã có lỗi ở bán kính mờ cao. Điều đó nói rằng, độ mờ chỉ lấy mẫu một khu vực 9 pixel theo mặc định, và vì vậy nếu bạn tăng hệ số nhân cho vùng mờ quá điểm đó, bạn sẽ bắt đầu thấy các hiện vật từ việc bỏ qua pixel. Điều này được thực hiện vì lý do hiệu suất, nhưng bạn có thể sửa đổi các trình tạo bóng đỉnh và phân mảnh để lấy mẫu số lượng pixel lớn hơn. Điều đó hoặc cố gắng áp dụng CIGaussianBlur, có triển khai làm mờ tổng quát hơn. Một trong những ngày này, tôi sẽ mở rộng độ mờ này đến bán kính lớn hơn.
Brad Larson

28

Tôi đang sử dụng FXBlurViewnó hoạt động tốt trên iOS5 +

https://github.com/nicklockwood/FXBlurView

CacaoPods:

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

Tôi đã thêm nó bằng cách sử dụng:

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

2
Có một số thủ thuật để sử dụng FXBlurView? Tôi đã thử nó, nhưng chúng tôi đã dẫn đến việc xem chậm trên iPhone 5. Dự án demo của họ hoạt động tốt. Khá kỳ quặc.
Cris

Nó phụ thuộc vào những gì bạn muốn làm. Khi tôi đặt FXBlurViewtrên đầu một, UIScrollViewtôi cũng nhận được một kết quả trễ. Tôi tin rằng điều này liên quan đến cách làm mờ được thêm vào. Apple, nếu tôi không nhầm, đang truy cập trực tiếp vào GPU khi sử dụng tính năng mờ của chính nó, điều mà chúng tôi không thể làm với tư cách là nhà phát triển. Do đó, giải pháp @cprcrack thực sự là giải pháp tốt nhất ở đây.
Paul Peelen

2
Bạn đã xử lý việc xoay thiết bị như thế nào với FXBlurView? Tôi đang trình bày một hộp thoại phương thức vào lúc này; hộp thoại tự xoay tốt nhưng phông nền bị bóp méo sai cách (về cơ bản nó cần được cập nhật sau khi xoay).
fatuhoku

1
tất nhiên, FXBlurView là một lựa chọn tốt, nhưng khi có vấn đề về việc sử dụng CPU. hơn tôi thích các màn hình mờ khác. tôi sử dụng cái này trong UICollectionVIew và UITableView nhưng nó làm tăng mức sử dụng CPU của tôi. trong lần chạy tiếp theo, tôi nhận xét những phân bổ đó và nó trở nên bình thường. tôi hy vọng, điều này sẽ giúp một ai đó.
Vatsal Shukla

27

CẢNH BÁO: một người nào đó trong các nhận xét đã nói rằng Apple từ chối các ứng dụng sử dụng kỹ thuật này. Điều đó KHÔNG xảy ra với tôi, nhưng chỉ để bạn xem xét.

Điều này có thể làm bạn ngạc nhiên, nhưng bạn có thể sử dụng UIToolbar , thanh này đã bao gồm hiệu ứng tiêu chuẩn đó (chỉ iOS 7+). Trong bạn xem viewDidLoad của bộ điều khiển:

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

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

1
Vâng, nó làm tôi ngạc nhiên. Tôi đã xác minh, ý tưởng này không hoạt động. Tôi chỉ thực hiện một thay đổi dòng viewDidLoadnhư thế này. - (void) viewDidLoad {[super viewDidLoad]; self.view = [[Thanh công cụ phân bổ] initWithFrame: CGRectZero]; } Trong trường hợp của tôi, tôi sắp xếp các chế độ xem của mình theo chương trình (kiểu cũ). Tôi ủng hộ giải pháp này vì UIToolbar kế thừa UIView nên về cơ bản tôi không thấy bất kỳ vấn đề nào trong giải pháp này. Tôi sẽ thử nghiệm nhiều hơn khi tôi phát triển và thử nghiệm giải pháp này.
Ashok

Đây là một ý tưởng tuyệt vời và nó có vẻ hoạt động rất hiệu quả. Ước gì tôi có nhiều quyền kiểm soát hơn, nhưng điều này càng tốt! Điều đó nói rằng, @SudhirJonathan đã đề cập đến một liên kết ở trên, nơi tác giả đưa điều này lên cấp độ tiếp theo - ÔNG BẮT ĐẦU NGƯỜI CALAYER từ một UIToolBar và tái sử dụng nó! Xuất sắc!
David H

2
Có thật không? Dựa trên những cơ sở nào? Nó không sử dụng bất kỳ API riêng tư nào và nếu tất cả các cách làm việc sáng tạo sẽ bị từ chối thì rất nhiều hiệu ứng sẽ không thể thực hiện được ...
TheEye 24/02

Làm việc trên iPhone iOS 7.1 của tôi
marsant

Có cách nào để "khai tử" độ mờ?
maxisme


13

Cách tốt nhất mới để có được Lớp phủ mờ là sử dụng Chế độ xem tính năng iOS 8 mới UIVisualEffectView.

UIBlurEffect *effect = [UIBlurEffect effectWithStyle:UIBlurEffectStyleLight];

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

bluredView.frame = self.view.bounds;

[self.view addSubview:bluredView];

UIBlurEffect hỗ trợ ba loại Style. Dark, Light và ExtraLight.


1

Bạn có thể tạo một lớp với UIToolBar là một lớp con của UIView và khởi tạo nó trong một bộ điều khiển chế độ xem riêng biệt. Cách tiếp cận này thể hiện một UIToolBar trong suốt (phân lớp bởi UIView) cung cấp phản hồi trực tiếp (trong trường hợp này là 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

Khi UIView ở trên đã được tùy chỉnh, hãy tiếp tục và tạo một lớp là lớp con của ViewController. Dưới đây, tôi đã tạo một lớp đang sử dụng phiên AVCapture. Bạn phải sử dụng AVCaptureSession để ghi đè cấu hình camera tích hợp của apple. Vì vậy, bạn có thể phủ UIToolBar tranclucent từ lớp 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

Câu trả lời dường như hoàn toàn không liên quan đến câu hỏi.
tổ hợp

@combinatorial Đây là một trong những cách hiệu quả hơn để thêm chế độ xem trong suốt vào bộ điều khiển chế độ xem khác. Tôi đã bao gồm mã AVCapture để cho thấy rằng nó có thể được sử dụng để phản hồi trực tiếp thay vì chỉ thêm hình nền mờ như những người dùng khác đã khuyến nghị.
74U n3U7r1no

Ok, xin lỗi, bạn có thể muốn thêm một cái gì đó ở đầu tóm tắt cách tiếp cận và lý do sử dụng nó.
tổ hợp

@combinatorial Cảm ơn
74U n3U7r1no
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.