Tạo chế độ xem lớp phủ mờ


Câu trả lời:


552

Bạn có thể sử dụng UIVisualEffectViewđể đạt được hiệu ứng này. Đây là một API nguyên gốc đã được tinh chỉnh cho hiệu năng và tuổi thọ pin tuyệt vời, cộng với việc dễ thực hiện.

Nhanh:

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

Mục tiêu-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];
}

Nếu bạn đang trình bày bộ điều khiển chế độ xem này một cách vừa phải để làm mờ nội dung bên dưới, bạn sẽ cần đặt kiểu trình bày phương thức thành Bối cảnh hiện tại và đặt màu nền thành rõ ràng để đảm bảo bộ điều khiển chế độ xem bên dưới sẽ vẫn hiển thị khi điều này được trình bày ở trên.


7
Để làm rõ insertSubView:belowSubView:nhận xét trong mã này, tôi đã sử dụng cách sau để đặt độ mờ làm nền của chế độ xem:view.insertSubview(blurEffectView, atIndex: 0)
Michael Voccola

2
Với tham chiếu đến câu trả lời ở trên, Có cần thiết phải kiểm tra "if (! UIAccessibilityIsReduceTrans minhEnables ())" hoặc chúng ta có thể bỏ qua điều đó không?
GKK

3
Nếu bạn đang trình bày trình điều khiển chế độ xem của mình, hãy đảm bảo bạn thay đổi modalPftimeationStyle = .overCienContext cùng với cài đặt màu nền rõ ràng
Shardul

3
Hoạt động tuyệt vời !!! Cần một thay đổi duy nhất: [self.view insertSubview: BlurEffectView at Index: 1];
Abhishek Thapliyal

2
Trong iOS 11, tôi thấy không cần thiết phải kiểm tra thủ công UIAccessibilityIsReduceTransparencyEnabled().
Nate Whittaker

284

Hình ảnh cốt lõi

Vì hình ảnh trong ảnh chụp màn hình là tĩnh, bạn có thể sử dụng CIGaussianBlurtừ Core Image (yêu cầu iOS 6). Dưới đây là mẫu: https://github.com/evanwdavis/Fun-with-M task / blob / master / Fin% 20with% 20M task /EWDBlurExampleVC.m

Nhắc bạn, điều này chậm hơn các tùy chọn khác trên trang này.

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

Ngăn xếp mờ (Hộp + Gaussian)

  • StackBlur Điều này thực hiện kết hợp mờ Box và Gaussian. Nhanh hơn 7 lần so với gaussian không tăng tốc, nhưng không quá xấu như làm mờ hộp. Xem bản demo tại đây (phiên bản plugin Java) hoặc tại đây (phiên bản JavaScript). Thuật toán này được sử dụng trong KDE và Camera + và các thuật toán khác. Nó không sử dụng Khung tăng tốc nhưng nhanh.

Tăng tốc khung

  • Trong phiên giao dịch Giao diện người dùng thực hiện trên iOS WWDC 2013, Apple giải thích cách tạo nền mờ (lúc 14:30) và đề cập đến một phương thức được applyLightEffecttriển khai trong mã mẫu bằng cách sử dụng Accelerate.framework.

  • GPUImage sử dụng các shader OpenGL để tạo mờ động. Nó có một số loại mờ: GPUImageBoxBlurFilter, GPUImageFastBlurFilter, GaussianSelectiveBlur, GPUImageGaussianBlurFilter. Thậm chí còn có một GPUImageiOSBlurFilter mà nên sao chép hoàn toàn hiệu ứng làm mờ được cung cấp bởi bảng điều khiển của iOS 7 ( tweet , bài viết ). Bài viết chi tiết và nhiều thông tin.

    - (UIImage *) BlurryGPUImage: (UIImage *) hình ảnh vớiBlurLevel: (NSInteger) Blur {
        GPUImageFastBlurFilter * BlurFilter = [GPUImageFastBlurFilter mới];
        BlurFilter.blurSize = Blur;
        UIImage * result = [BlurFilter imageByFilteringImage: image];
        kết quả trả về;
    }
  • Từ indieambitions.com: Thực hiện làm mờ bằng vImage . Thuật toán cũng được sử dụng trong iOS-RealTimeBlur .

  • Từ Nick Lockwood: https://github.com/nicklockwood/FXBlurView Ví dụ cho thấy độ mờ trên chế độ xem cuộn. Nó làm mờ với Clark_async, sau đó đồng bộ hóa để gọi các bản cập nhật với UITrackingRunLoopMode để độ mờ không bị trễ khi UIKit ưu tiên hơn cho cuộn UIScrollView. Điều này được giải thích trong cuốn sách Hoạt hình cốt lõi iOS của Nick , điều đó thật tuyệt vời.

  • iOS-Blur Điều này lấy lớp làm mờ của UIToolbar và đặt nó ở nơi khác. Apple sẽ từ chối ứng dụng của bạn nếu bạn sử dụng phương pháp này. Xem https://github.com/mochidev/MDBlurView/issues/4

  • Từ blog Evadne: LiveFrost: Chuyển đổi ảnh chụp nhanh UIView đồng bộ, nhanh chóng . Mã tuyệt vời và đọc tuyệt vời. Một số ý tưởng từ bài viết này:

    • Sử dụng hàng đợi nối tiếp để tăng tốc cập nhật từ CADisplayLink.
    • Tái sử dụng bối cảnh bitmap trừ khi giới hạn thay đổi.
    • Vẽ các hình ảnh nhỏ hơn bằng cách sử dụng - [CALayer renderInContext:] với hệ số tỷ lệ 0,5f.

Những thứ khác

Andy Matuschak đã nói trên Twitter: Bạn biết đấy, rất nhiều nơi có vẻ như chúng ta đang làm điều đó trong thời gian thực, nó tĩnh với những mánh khóe thông minh.

Tại doubleencore.com, họ nói rằng chúng tôi đã phát hiện ra rằng bán kính mờ 10 pt cộng với tăng 10 pt trong độ bão hòa tốt nhất bắt chước hiệu ứng làm mờ của iOS 7 trong hầu hết các trường hợp.

Xem qua các tiêu đề riêng của SBFProceduralWallapersView của Apple .

Cuối cùng, đây không phải là một vệt mờ thực sự, nhưng hãy nhớ rằng bạn có thể đặt rasterizationScale để có được một hình ảnh pixelated: http://www.dimzzy.com/blog/2010/11/blur-effect-for-uiview/


Cảm ơn về câu trả lời! Một vấn đề được giải quyết. Nhưng chúng ta có một vấn đề nữa. Làm cách nào để có ảnh bìa trong iOS 7. Nếu có thể?
kondratyevdev

Nếu bạn có nghĩa là làm thế nào để có được hình nền hình nền từ điện thoại của bạn, không có ý tưởng tại thời điểm này. Tôi không thấy chức năng đó trong API khác . Có lẽ nó sử dụng API riêng.
Jano

Một điều tôi nhận thấy (và tôi có thể hoàn toàn sai) là sự mờ ảo của Apple cũng xuất hiện để thêm vào một chút bão hòa màu. Vì vậy, tôi không nghĩ đó là một gaussian mờ đơn giản.
xtravar

Hãy nhớ yếu tố tỷ lệ khi trả lại UIImagenếu không nó sẽ trông quá lớn trên thiết bị Retina ...
Stephen Darlington

Bạn có biết liệu hiệu ứng đó có thể được áp dụng cho UITableViewCell mà không làm giảm hiệu suất không?
Leonardo

15

Tôi quyết định đăng một phiên bản Objective-C bằng văn bản từ câu trả lời được chấp nhận chỉ để cung cấp thêm tùy chọn trong câu hỏi này ..

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

Các ràng buộc có thể được loại bỏ nếu bạn muốn kích hoạt nếu bạn chỉ hỗ trợ chế độ dọc hoặc tôi chỉ cần thêm một cờ vào chức năng này để sử dụng chúng hay không ..


1
đối với những người mới (tôi), một cách để gọi phương thức trên là: [self applicationBlurToView: self.view withEffectStyle: UIBlurEffectStyleDark vàConstraint: YES]; (cảm ơn bạn NorthBlast)
tmr

14

Tôi không nghĩ rằng tôi được phép đăng mã, nhưng bài viết trên có đề cập đến mã mẫu WWDC là chính xác. Đây là liên kết: https://developer.apple.com/doads/index.action?name=WWDC%202013

Tệp bạn đang tìm kiếm là danh mục trên UIImage và phương thức này là áp dụngLightEffect.

Như tôi đã lưu ý ở trên trong một bình luận, Apple Blur có độ bão hòa và những thứ khác đang diễn ra bên cạnh mờ. Một vệt mờ đơn giản sẽ không làm ... nếu bạn đang muốn mô phỏng phong cách của họ.


8
Liên kết đó bị hỏng. Đây là liên kết chính xác: developer.apple.com/doads/index.action?name=WWDC%202013
olivaresF

Lưu ý rằng mã ví dụ này yêu cầu XCode 5.0 và iOS SDK 7.0 (chưa được phát hành công khai)
Mike Gledhill

Cảm ơn vì liên kết cố định, tuy nhiên có một vài mã mẫu trong đó, mã nào chứa danh mục UIImage có liên quan?
Leonardo

1
@Leonardo iOS_RastyWithASnap.zip
John Starr Dewar

1
... Hoặc iOS_UIImageEffects.zip chỉ cụ thể hơn thế này.
John Starr Dewar

9

Tôi nghĩ giải pháp đơn giản nhất cho việc này là ghi đè UIToolbar, làm mờ mọi thứ đằng sau nó trong iOS 7. Nó khá lén lút, nhưng nó rất đơn giản để bạn thực hiện và nhanh chóng!

Bạn có thể làm điều đó với bất kỳ chế độ xem nào, chỉ cần biến nó thành một lớp con UIToolbarthay vì UIView. Bạn thậm chí có thể làm điều đó với một UIViewController's viewtài sản, ví dụ ...

1) tạo một lớp mới là "Lớp con của" UIViewControllervà đánh dấu vào ô "Với XIB cho giao diện người dùng".

2) Chọn Chế độ xem và chuyển đến trình kiểm tra danh tính trong bảng điều khiển bên phải (alt-lệnh-3). Thay đổi "Lớp" thành UIToolbar. Bây giờ, hãy chuyển đến trình kiểm tra thuộc tính (alt-lệnh-4) và thay đổi màu "Nền" thành "Xóa màu".

3) Thêm một khung nhìn vào khung nhìn chính và nối nó với IBOutlet trong giao diện của bạn. Gọi nó backgroundColorView. Nó sẽ trông giống như thế này, như là một thể loại riêng tư trong .mtệp thực hiện ( ).

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

4) Chuyển đến .mtệp thực thi trình điều khiển xem ( ) và thay đổi -viewDidLoadphương thức, để xem như sau:

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

Điều này sẽ cung cấp cho bạn một cái nhìn màu xám đen, làm mờ mọi thứ đằng sau nó. Không kinh doanh hài hước, không làm mờ hình ảnh lõi chậm, sử dụng mọi thứ trong tầm tay của bạn do OS / SDK cung cấp.

Bạn có thể thêm chế độ xem của trình điều khiển chế độ xem này vào chế độ xem khác, như sau:

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

// animate the self.blurViewController into view

Hãy cho tôi biết nếu có gì không rõ ràng, tôi sẽ sẵn lòng giúp đỡ!


Biên tập

UIToolbar đã được thay đổi trong 7.0.3 để mang lại hiệu quả không mong muốn khi sử dụng hiệu ứng nhòe màu.

Chúng tôi đã từng có thể đặt màu bằng cách sử dụng barTintColor, nhưng nếu bạn đã làm điều này trước đây, bạn sẽ cần đặt thành phần alpha nhỏ hơn 1. Nếu không, thanh UIToolbar của bạn sẽ có màu mờ hoàn toàn - không bị mờ.

Điều này có thể đạt được như sau: (ghi nhớ selflà một lớp con của UIToolbar)

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

Điều này sẽ cung cấp một màu xanh lam cho chế độ xem mờ.


1
Người đàn ông không tệ. Tôi đã sử dụng ba dòng này trong quan điểm của mình: self.backgroundColorView.opaque = NO; self.backgroundColorView.alpha = 0.5; self.backgroundColorView.backgroundColor = [UIColor colorWithWhite:0.3 alpha:1];Nhưng nền không bị mờ, chỉ tạo hiệu ứng đẹp hơn. dù sao cũng cảm ơn bạn
IgniteCoders

1
Tôi không thấy bất kỳ mờ nào khi sử dụng kỹ thuật này. Nó chỉ tạo ra một lớp phủ màu.
MusiGenesis

đảm bảo lớp phủ alpha màu nhỏ hơn 1. Bạn có thể sử dụng thanh UITool mà không cần bộ điều khiển xem, có thể đơn giản hơn tùy thuộc vào những gì bạn cần.
Sam

người đàn ông lừa gọn gàng. Tôi đã chuyển đổi chế độ xem của mình sang lớp UIToolbar trong bảng phân cảnh, sau đó thay đổi nền xem thành màu rõ ràng. Nó cho một nền mờ trắng. Nếu bạn tạo alpha dưới 1, hiệu ứng mờ sẽ biến mất.
Badr

9

Đây là một triển khai nhanh trong Swift bằng 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

Tùy chỉnh tỷ lệ mờ

Bạn có thể thử UIVisualEffectView với cài đặt tùy chỉnh như -

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

Đầu ra: - cho blurEffect.setValue(1...& blurEffect.setValue(2.. nhập mô tả hình ảnh ở đây nhập mô tả hình ảnh ở đây


3
Nó sẽ ngừng hoạt động nếu trong phiên bản tiếp theo của tên iOS của tham số này bị thay đổi.
Ariel Bogdziewicz

@ArielBogdziewicz hiện đang hoạt động. tôi sẽ cập nhật nếu có bất kỳ biến thể API nào trong wwdc.
Jack

Ummm ... không, bạn không bao giờ muốn truy cập API riêng. Họ riêng tư vì một lý do. Họ sẽ thay đổi, họ sẽ phá vỡ và / hoặc Apple sẽ từ chối ứng dụng của bạn. Sử dụng phương pháp khác, có rất nhiều. Kudos cho việc tìm kiếm hack, nhưng, không được khuyến khích.
n13

@Jack Cảm ơn bạn rất nhiều vì câu trả lời này! Đó là giải pháp duy nhất tôi tìm thấy cho vấn đề của mình: làm mờ một khung nhìn theo vị trí của một khung nhìn khác. Tuy nhiên, tôi vẫn có một câu hỏi khác. Có cách nào để tôi có thể thêm sự sinh động lên trên UIBlurEffect của mình không? Nếu vậy thì thế nào? Tôi có cần tạo chế độ xem khác cho mục này trên màn hình mờ của mình không? Tôi đã cố gắng như vậy nhưng nó luôn bị sập khi tôi sử dụng (NSClassFromString("_UICustomVibrancyEffect") as! UIVibrancyEffect.Type).init()Sẽ thực sự đánh giá cao sự giúp đỡ!
Moritz

@Moritz chưa thử. Nhưng nó sẽ hoạt động. Bạn có thể thử và kiểm tra.
Jack

7

Đây là một cách dễ dàng để thêm mờ tùy chỉnh mà không mặc cả với các API riêng bằng UIViewPropertyAnimator :

Đầu tiên, khai báo tài sản lớp:

var blurAnimator: UIViewPropertyAnimator!

Sau đó, đặt chế độ xem mờ của bạn trong 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.    

Lưu ý: Giải pháp này không phù hợp với UICollectionView/ UITableViewô


1
Đây là giải pháp duy nhất mà tôi tìm thấy, nếu bạn muốn kiểm soát tính minh bạch của UIVisualEffectView.
Denis Kutlubaev

6

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

Từ Xcode bạn có thể làm điều đó một cách dễ dàng. Thực hiện theo các bước từ xcode. Drage xem hiệu ứng hình ảnh trên uiview hoặc tưởng tượng của bạn.

Chúc mừng mã hóa :)


5

Câu trả lời được chấp nhận là chính xác nhưng có một bước quan trọng bị thiếu ở đây, trong trường hợp chế độ xem này - mà bạn muốn làm mờ nền - được trình bày bằng cách sử dụng

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

Theo mặc định, điều này sẽ phủ nhận mờ khi UIKit xóa chế độ xem của người trình bày mà bạn đang thực sự làm mờ. Để tránh việc xóa đó, hãy thêm dòng này trước dòng trước

vc.modalPresentationStyle = UIModalPresentationOverFullScreen;

Hoặc sử dụng các Overphong cách khác .


3

MỤC TIÊU-C

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

Chuyển đổi 3.0

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

từ: https://stackoverflow.com/a/24083728/4020910


2

Sử dụng UIImageEffects

Đối với những người muốn kiểm soát nhiều hơn, bạn có thể sử dụng UIImageEffectsmã mẫu của Apple .

Bạn có thể sao chép mã UIImageEffectstừ Thư viện nhà phát triển của Apple: Làm mờ và tô màu hình ảnh

Và đây là cách áp dụng nó:

#import "UIImageEffects.h"
...

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

Làm thế nào để tôi sử dụng điều này trong swift
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

Tìm thấy điều này một cách tình cờ, mang lại cho tôi kết quả thực sự tuyệt vời (gần trùng lặp với Apple) và sử dụng khung Gia tốc. - http://pastebin.com/6cs6hsyQ * Không phải do tôi viết


8
Đó thực sự là mã Apple từ WWDC 2013 với bản quyền sai.
Shmidt

các mã từ WWDC có bản quyền và quyền truy cập chỉ được phép cho các thành viên có đăng ký trả phí?
SAFAD

1
Có thể, nhưng mã ở trên tôi tìm thấy bằng Google. Tôi đã không thay đổi Bản quyền và tôi giả định (và vẫn cho rằng) nó có khiếu nại bản quyền chính xác. Nếu Apple không đồng ý, họ nên nỗ lực hạ gục nó. Tôi không thấy sự liên quan.
Jake

1

Câu trả lời này dựa trên câu trả lời xuất sắc trước đó của Mitja Semolic . Tôi đã chuyển đổi nó thành swift 3, thêm một lời giải thích cho những gì đang xảy ra trong coments, biến nó thành một phần mở rộng của UIViewContoder để bất kỳ VC nào cũng có thể gọi nó theo ý muốn, thêm một chế độ xem không bị mờ để hiển thị ứng dụng chọn lọc và thêm một khối hoàn thành để bộ điều khiển xem cuộc gọi có thể làm bất cứ điều gì nó muốn khi hoàn thành mờ.

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

Tôi đã xác nhận rằng nó hoạt động với cả iOS 10.3.1 và iOS 11


1

Một bổ sung quan trọng cho câu trả lời của @ Joey

Điều này áp dụng cho một tình huống mà bạn muốn trình bày một nền mờ UIViewControllervới 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];

Thưởng thức!


1

Phiên bản Swift 3 của câu trả lời của Kev để trả lại hình ảnh mờ -

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

Mã 2019

Đây là một ví dụ đầy đủ hơn bằng cách sử dụng kỹ thuật @AdamBardon tuyệt vời.

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

{Ngoài ra: là một vấn đề kỹ thuật chung của iOS, didMoveToWindowcó thể phù hợp với bạn hơn didMoveToSuperview. Thứ hai, bạn có thể sử dụng một số cách khác để thực hiện phân tách, nhưng phân tách là hai dòng mã được hiển thị ở đó.}

BlurryBallchỉ là một UIVisualEffectView. Chú ý các điểm vào để xem hiệu ứng hình ảnh. Nếu bạn tình cờ cần các góc tròn hoặc bất cứ điều gì, hãy làm điều đó trong lớp này.

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

Đây là mã Swift 2.0 cho giải pháp đã được cung cấp trong câu trả lời được chấp nhận :

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

Nếu thêm chế độ xem mờ tối cho bảng Xem, điều này sẽ làm cho nó đẹp:

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

Bạn có thể trực tiếp tạo nền Blur cho mình bằng cách sử dụng "Chế độ xem hiệu ứng hình ảnh với độ mờ" và "Chế độ xem hiệu ứng hình ảnh với độ mờ và độ rung".

Tất cả những gì bạn phải làm để tạo Blur Background trong Ứng dụng iOS là ...

  1. Đi và tìm kiếm "Chế độ xem hiệu ứng hình ảnh với Blur" trong Thư viện đối tượng

Bước 1 Hình ảnh

  1. Kéo "Chế độ xem hiệu ứng hình ảnh với độ mờ" trong Storyboard của bạn và thiết lập nó ...

Bước 2 Hình ảnh

  1. Cuối cùng ... Bạn làm mờ nền ứng dụng của bạn!

Bố trí ứng dụng trước khi nhấp vào bất kỳ nút nào!

Chế độ xem ứng dụng sau khi nhấp vào nút làm cho toàn bộ nền ứng dụng bị mờ!


0

Trong trường hợp điều này giúp được bất cứ ai, đây là một phần mở rộng nhanh chóng mà tôi đã tạo dựa trên câu trả lời của Jordan H. Nó được viết bằng Swift 5 và có thể được sử dụng từ Objective 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
        }
    }

}

LƯU Ý: Nếu bạn muốn làm mờ nền của UILabel mà không ảnh hưởng đến văn bản, bạn nên tạo UIView chứa, thêm UILabel vào vùng chứa UIView dưới dạng một khung nhìn phụ, đặt nền của UILabel thành UIColor.clear, sau đó gọi BlurBackground (kiểu : UIBlurEffect.Style, fallbackColor: UIColor) trên container UIView. Dưới đây là một ví dụ nhanh về điều này được viết trong 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:

Để thêm lớp phủ hoặc chế độ xem cửa sổ bật lên Bạn cũng có thể sử dụng Chế độ xem Container mà bạn nhận được Trình điều khiển xem miễn phí (bạn có được Chế độ xem Container từ bảng màu / thư viện đối tượng thông thường)

Các bước:

Có Chế độ xem (ViewForContainer trong ảnh) giữ Chế độ xem Container này, để làm mờ nó khi nội dung của Chế độ xem Container được hiển thị. Kết nối ổ cắm bên trong Bộ điều khiển xem đầu tiên

Ẩn Chế độ xem này khi tải VC đầu tiên

Bỏ ẩn khi nhấn vào nút Nhập mô tả hình ảnh ở đây

Để làm mờ Chế độ xem này khi nội dung Chế độ xem Container được hiển thị, đặt Nền Chế độ xem thành Đen và độ mờ thành 30%

Tôi đã thêm câu trả lời cho việc tạo chế độ xem popview trong câu hỏi Stackoverflow khác https://stackoverflow.com/a/49729431/5438240


-3

Câu trả lời đơn giản là Thêm một khung nhìn phụ và thay đổi nó là alpha.

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