Làm cách nào để làm mờ UIVisualEffectView và / hoặc UIBlurEffect vào và ra?


92

Tôi muốn làm mờ UIVisualEffectsView bằng UIBlurEffect vào và ra:

var blurEffectView = UIVisualEffectView()
blurEffectView = UIVisualEffectView(effect: UIBlurEffect(style: .dark))

Tôi sử dụng một hoạt ảnh bình thường trong một hàm được gọi bởi a UIButtonđể làm mờ nó trong, tương tự để làm mờ dần nhưng .alpha = 0& hidden = true:

blurEffectView.hidden = false
UIView.animate(withDuration: 1, delay: 0, options: .curveEaseOut) {
    self.blurEffectView.alpha = 1
}

Bây giờ, mờ dần theo cả hai chiều không làm việc nhưng nó mang lại cho tôi một lỗi khi mờ dần ra :

<UIVisualEffectView 0x7fdf5bcb6e80>đang được yêu cầu làm hoạt hình độ mờ của nó. Điều này sẽ làm cho hiệu ứng có vẻ bị hỏng cho đến khi độ mờ trở về 1.

Câu hỏi

Làm cách nào để tôi làm mờ thành công đoạn UIVisualEffectViewtrong và ngoài mà không bị vỡ và có quá trình chuyển đổi mờ dần?

Ghi chú

  • Tôi đã cố gắng đưa UIVisualEffectViewvào một UIViewvà làm mờ đi cái đó, không thành công

Bạn có thể tránh Lỗi bằng cách: 1. KHÔNG gán một kiểu ban đầu cho blurEffect. tức là, var BlurEffectView = UIVisualEffectView () và sau đó 2. gán BlurEffect cho BlurEffectView INSIDE khối hoạt hình. 3. tạo hiệu ứng hoạt ảnh "gán mờEffect cho mờEffectView" được thực hiện thay cho các điều chỉnh cho mờEffectView.alpha. ** Lỗi sẽ xuất hiện ngay cả khi bạn chỉ định một giá trị ban đầu, bỏ đi, sau đó thêm lại. Vì vậy, chìa khóa để ngăn chặn lỗi là không gán hiệu ứng cho blurEffectView cho đến khi khối hoạt ảnh.
ObjectiveTC

Cũng cần nói thêm, mờEffectView phải có alpha = 1.0 để tránh lỗi. Giả mạo alpha theo bất kỳ cách nào sẽ tạo ra lỗi. Ví dụ: trước khi khối hoạt ảnh, bạn đặt mờEffectView.alpha = 0,7, sau đó trong khối hoạt ảnh bạn gán mờEffectView.effect = mờEffect, lỗi được tạo ra.
ObjectiveTC

Câu trả lời:


185

Tôi nghĩ điều này là mới trong iOS9, nhưng bây giờ bạn có thể đặt hiệu ứng của một UIVisualEffectViewkhối hoạt hình bên trong:

let overlay = UIVisualEffectView()
// Put it somewhere, give it a frame...
UIView.animate(withDuration: 0.5) {
    overlay.effect = UIBlurEffect(style: .light)
}

Đặt nó nilđể loại bỏ.

RẤT QUAN TRỌNG - Khi kiểm tra điều này trên trình mô phỏng, hãy đảm bảo đặt Ghi đè chất lượng đồ họa của trình mô phỏng thành Chất lượng cao để tính năng này hoạt động.


1
Hoạt động hoàn hảo. Cảm ơn.
Baza207

Tuyệt quá! Như bạn đã nói, không hoạt động cho iOS 8 mặc dù: /
LinusGeffarth

Chính xác là vì những gì tôi đã viết ở trên. Tôi đã chấp thuận nó bây giờ dù sao. @jpros
LinusGeffarth

10
Bạn cũng có thể đặt hiệu ứng thành nil để có được một "hiệu ứng mờ" khá đẹp
jpros

1
@jpros Bạn có vui lòng giải thích ý bạn bằng cách "làm mờ đi?"
ndmeiri

19

Các tài liệu hướng dẫn của Apple (hiện tại) khẳng định ...

Khi sử dụng lớp UIVisualEffectView, hãy tránh các giá trị alpha nhỏ hơn 1.

Đặt alpha thành nhỏ hơn 1 trên chế độ xem hiệu ứng hình ảnh hoặc bất kỳ chế độ xem siêu cấp nào của nó khiến nhiều hiệu ứng trông không chính xác hoặc hoàn toàn không hiển thị.

Tôi tin rằng một số bối cảnh quan trọng bị thiếu ở đây ...

Tôi đề nghị rằng mục đích là tránh các giá trị alpha nhỏ hơn 1 để có chế độ xem liên tục. Theo ý kiến ​​khiêm tốn của tôi, điều này không áp dụng cho hoạt ảnh của một chế độ xem.

Quan điểm của tôi - Tôi đề nghị rằng các giá trị alpha nhỏ hơn 1 có thể chấp nhận được cho các hoạt ảnh.

Thông báo đầu cuối cho biết:

UIVisualEffectView đang được yêu cầu để tạo hiệu ứng cho độ mờ của nó. Điều này sẽ làm cho hiệu ứng có vẻ bị hỏng cho đến khi độ mờ trở về 1.

Đọc kỹ điều này, hiệu ứng sẽ có vẻ bị phá vỡ. Quan điểm của tôi về vấn đề này:

  • sự phá vỡ rõ ràng chỉ thực sự quan trọng đối với một quan điểm tồn tại - không thay đổi;
  • một UIVisualEffectchế độ xem liên tục / không thay đổi với giá trị alpha nhỏ hơn 1 sẽ không hiển thị như dự kiến ​​/ thiết kế của Apple; và
  • thông báo trong thiết bị đầu cuối không phải là lỗi, chỉ là một cảnh báo.

Để mở rộng câu trả lời của @ jrturton ở trên đã giúp tôi giải quyết vấn đề của mình, tôi muốn thêm ...

Để xóa mờ việc UIVisualEffectsử dụng mã (Objective-C) sau:

UIView.animateWithDuration(1.0, animations: {
//  EITHER...
    self.blurEffectView.effect = UIBlurEffect(nil)
//  OR...
    self.blurEffectView.alpha = 0
}, completion: { (finished: Bool) -> Void in
    self.blurEffectView.removeFromSuperview()
} )

Tôi sử dụng thành công cả hai phương pháp: đặt thuộc effecttính thành nilvà đặt thuộc alphatính thành 0.

Lưu ý rằng cài đặt effectđể niltạo ra "đèn flash đẹp" (vì muốn có mô tả tốt hơn) ở cuối hoạt ảnh, trong khi cài đặt alphađể 0tạo chuyển tiếp mượt mà.

(Hãy cho tôi biết bất kỳ lỗi cú pháp nào ... Tôi viết bằng obj-c.)


Cảm ơn sự đóng góp của bạn. Tôi hiểu ý bạn; các lỗi được giải quyết đối với tôi đã w / chính xác những gì bạn đề cập :)
LinusGeffarth

14

Đây là giải pháp mà tôi đã kết thúc, hoạt động trên cả iOS10 và các phiên bản trước đó bằng Swift 3

extension UIVisualEffectView {

    func fadeInEffect(_ style:UIBlurEffectStyle = .light, withDuration duration: TimeInterval = 1.0) {
        if #available(iOS 10.0, *) {
            let animator = UIViewPropertyAnimator(duration: duration, curve: .easeIn) {
                self.effect = UIBlurEffect(style: style)
            }

            animator.startAnimation()
        }else {
            // Fallback on earlier versions
            UIView.animate(withDuration: duration) {
                self.effect = UIBlurEffect(style: style)
            }
        }
    }

    func fadeOutEffect(withDuration duration: TimeInterval = 1.0) {
        if #available(iOS 10.0, *) {
            let animator = UIViewPropertyAnimator(duration: duration, curve: .linear) {
                self.effect = nil
            }

            animator.startAnimation()
            animator.fractionComplete = 1
        }else {
            // Fallback on earlier versions
            UIView.animate(withDuration: duration) {
                self.effect = nil
            }
        }
    }

}

Bạn cũng có thể kiểm tra ý chính này để tìm cách sử dụng ví dụ.


Sử dụng UIViewPropertyAnimatorlà thứ duy nhất có vẻ hoạt động trong iOS 11. Cảm ơn vì điều này!
LinusGeffarth

Đừng quên thêm: nhập UIKit
Oleksandr

8

Chỉ là một cách giải quyết - đưa UIVisualEffectViewvào chế độ xem vùng chứa và thay đổi thuộc alphatính cho vùng chứa đó. Cách tiếp cận đó hoạt động hoàn hảo đối với tôi trên iOS 9. Có vẻ như nó không còn hoạt động trong iOS 10 nữa.


Mát mẻ. Cảm ơn, sẽ cố gắng mà :)
LinusGeffarth

1
Bạn có thể cung cấp mã mẫu. Điều này dường như không hoạt động.
cnotethegr8

Hoạt động cho tôi trong iOS 9
5hrp

@DerrickHunt Tương tự ở đây. Bạn đã tìm thấy một giải pháp?
damirstuhec 27/09/2016

2
@damirstuhec Nếu dự án của bạn chỉ là iOS 10, bạn có thể sử dụng lớp UIViewPropertyAnimator mới để tạo hiệu ứng cho sức mạnh UIBlurView. Nếu bạn cần hỗ trợ các phiên bản cũ hơn, bạn có thể sử dụng mã trên và sử dụng từ khóa #available để sử dụng UIViewPropertyAnimator cho các thiết bị chạy 10. Hy vọng điều này sẽ hữu ích!
Derrick Hunt

5

Bạn có thể thay đổi alpha của chế độ xem hiệu ứng hình ảnh mà không gặp bất kỳ sự cố nào, ngoài cảnh báo trong bảng điều khiển. Chế độ xem có thể chỉ đơn giản là trong suốt một phần thay vì bị mờ. Nhưng điều này thường không thành vấn đề nếu bạn chỉ thay đổi alpha trong hoạt ảnh.

Ứng dụng của bạn sẽ không gặp sự cố hoặc bị từ chối vì điều này. Kiểm tra nó trên một thiết bị thực (hoặc tám). Nếu bạn hài lòng với cách nó trông và hoạt động, thì tốt thôi. Apple vừa cảnh báo bạn rằng nó có thể không có giao diện hoặc hoạt động tốt như chế độ xem hiệu ứng hình ảnh với giá trị alpha là 1.


5

Bạn có thể chụp nhanh một chế độ xem bên dưới tĩnh và làm mờ dần nó ra mà không cần chạm vào độ mờ của chế độ xem mờ. Giả sử một ivar của blurView:

func addBlur() {
    guard let blurEffectView = blurEffectView else { return }

    //snapShot = UIScreen.mainScreen().snapshotViewAfterScreenUpdates(false)
    let snapShot = self.view.snapshotViewAfterScreenUpdates(false)
    view.addSubview(blurEffectView)
    view.addSubview(snapShot)

    UIView.animateWithDuration(0.25, animations: {
        snapShot.alpha = 0.0
    }, completion: { (finished: Bool) -> Void in
        snapShot.removeFromSuperview()
    } )
}

func removeBlur() {
    guard let blurEffectView = blurEffectView else { return }

    let snapShot = self.view.snapshotViewAfterScreenUpdates(false)
    snapShot.alpha = 0.0
    view.addSubview(snapShot)

    UIView.animateWithDuration(0.25, animations: {
        snapShot.alpha = 1.0
    }, completion: { (finished: Bool) -> Void in
        blurEffectView.removeFromSuperview()
        snapShot.removeFromSuperview()
    } )
}

Ý tưởng hay nhưng điều đó sẽ không hoạt động tốt đối với nội dung không tĩnh (chuyển động / hoạt ảnh) bên dưới chế độ xem mờ.
LinusGeffarth

@LinusG. Vâng, Apple nói rằng không nên chơi xung quanh alpha xem mờ. Bạn có thể sử dụng liên kết CADisplayLink để chụp ảnh màn hình của chế độ xem cơ sở của bạn, sau đó hiển thị chúng ở chế độ xem hình ảnh (có thể là bạn đã làm - thực sự nhẹ) - và hiển thị những ảnh đó ở chế độ xem trên cùng trong khi thay đổi độ mờ của nó thành 0. Có thể nhưng rất nhiều công việc.
David H

1
Đây là cách duy nhất (cho đến nay) tôi có thể đạt được những gì tôi muốn trong iOS 10 - mờ dần ở chế độ toàn màn hình, với hiệu ứng mờ rất tối. Cảm ơn!
Graham

3

Nếu bạn muốn mờ dần trong UIVisualEffectView - đối với ios10, hãy sử dụng UIViewPropertyAnimator

    UIVisualEffectView *blurEffectView = [[UIVisualEffectView alloc] initWithEffect:nil];
    blurEffectView.frame = self.view.frame;
    blurEffectView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;

    UIView *blackUIView = [[UIView alloc]initWithFrame:self.view.frame];
    [bacgroundImageView addSubview:blackUIView];
    [blackUIView addSubview:blurEffectView];
    UIViewPropertyAnimator *animator  = [[UIViewPropertyAnimator alloc] initWithDuration:4.f curve:UIViewAnimationCurveLinear animations:^{
        [blurEffectView setEffect:[UIBlurEffect effectWithStyle:UIBlurEffectStyleDark]];
    }];

sau đó bạn có thể đặt phần trăm

[animator setFractionComplete:percent];

đối với ios9, bạn có thể sử dụng thành phần alpha


2
Câu hỏi được gắn thẻ cụ thể là "swift", không phải "obj-c": vui lòng cung cấp câu trả lời bằng Swift. Cảm ơn!
Eric Aya

1
Cảm ơn vì Mã Objective C. Tôi thấy nó hữu ích vì không có nhiều ví dụ khác được liệt kê.
Adam Ware

2

Alpha của UIVisualEffectView luôn phải là 1. Tôi nghĩ bạn có thể đạt được hiệu ứng bằng cách đặt alpha của màu nền.

Nguồn: https://developer.apple.com/library/ios/documentation/UIKit/Reference/UIVisualEffectView/index.html


Peter, bạn có thể vui lòng giải thích cách đặt alpha của màu nền không?
Boris Y.

@borisy sử dụng colorWithAlphaComponent:phương thức trên các UIColortrường hợp. Tuy nhiên, bạn không chắc chắn làm thế nào để đạt được hiệu ứng tương tự khi thiết lập màu nền.
nemesis

Bằng cách thay đổi thành phần alpha nền không hoạt động như mong đợi
Honghao Zhang

1

Tôi tạo một uiview mà alpha là 0 và thêm dimview làm chế độ xem phụ của cái đó. Vì vậy, tôi có thể ẩn / hiện hoặc làm tròn các góc của nó bằng hoạt ảnh.


1

Tôi đã kết thúc với giải pháp sau, sử dụng các hình ảnh động riêng biệt cho UIVisualEffectViewnội dung và nội dung. Tôi đã sử dụng viewWithTag()phương thức này để lấy tham chiếu đến UIViewbên trong UIVisualEffectView.

let blurEffectView = UIVisualEffectView()
// Fade in
UIView.animateWithDuration(1) { self.blurEffectView.effect = UIBlurEffect(style: .Light) }    
UIView.animateWithDuration(1) { self.blurEffectView.viewWithTag(1)?.alpha = 1 }
// Fade out
UIView.animateWithDuration(1) { self.blurEffectView.effect = nil }    
UIView.animateWithDuration(1) { self.blurEffectView.viewWithTag(1)?.alpha = 0 }

Tôi muốn hoạt ảnh đơn lẻ thay đổi alpha, nhưng điều này tránh được lỗi và dường như hoạt động tốt.


1

Tôi vừa gặp sự cố này và cách tôi giải quyết nó là đặt UIVisualEffectsView trong một UIView và tạo hiệu ứng cho alpha của UIView đó.

Điều này hoạt động tốt, ngoại trừ việc ngay sau khi alpha thay đổi dưới 1.0, nó chuyển sang màu trắng đặc và trông rất chói tai. Để giải quyết vấn đề này, bạn phải đặt thuộc tính lớp của UIView containerView.layer.allowsGroupOpacity = falsevà điều này sẽ ngăn nó nhấp nháy màu trắng.

Giờ đây, bạn có thể tạo hoạt ảnh trong / làm mờ UIView chứa chế độ xem hiệu ứng hình ảnh và bất kỳ chế độ xem phụ nào khác bằng cách sử dụng thuộc tính alpha của nó và không phải lo lắng về bất kỳ trục trặc đồ họa nào hoặc nó ghi lại thông báo cảnh báo.


0
_visualEffectView.contentView.alpha = 0;

Để thay đổi alpha của UIVisualEffectView, bạn nên thay đổi contentView của _visualEffectView. Nếu bạn thay đổi alpha của _visualEffectView, bạn sẽ nhận được điều này

<UIVisualEffectView 0x7ff7bb54b490> is being asked to animate its opacity. This will cause the effect to appear broken until opacity returns to 1.

0

Thông thường, tôi chỉ muốn tạo hiệu ứng mờ khi tôi đang trình bày bộ điều khiển chế độ xem trên màn hình và muốn làm mờ bộ điều khiển chế độ xem trình bày. Đây là một tiện ích mở rộng thêm làm mờ () và bỏ làm mờ () vào bộ điều khiển chế độ xem để tạo điều kiện:

extension UIViewController {

   func blur() {
       //   Blur out the current view
       let blurView = UIVisualEffectView(frame: self.view.frame)
       self.view.addSubview(blurView)
       UIView.animate(withDuration:0.25) {
           blurView.effect = UIBlurEffect(style: .light)
       }
   }

   func unblur() {
       for childView in view.subviews {
           guard let effectView = childView as? UIVisualEffectView else { continue }
           UIView.animate(withDuration: 0.25, animations: {
                effectView.effect = nil
           }) {
               didFinish in
               effectView.removeFromSuperview()
           }
       }
   }
}

Tất nhiên, bạn có thể làm cho điều này mạnh mẽ hơn bằng cách cho phép người dùng chọn kiểu hiệu ứng, sửa đổi thời lượng, gọi một cái gì đó khi hoạt ảnh hoàn thành, gắn thẻ chế độ xem hiệu ứng hình ảnh được thêm vào ở chế độ mờ () để đảm bảo đó là chế độ duy nhất bị xóa khi bạn bỏ làm mờ ( ), v.v., nhưng cho đến nay tôi vẫn chưa thấy cần thiết phải làm những việc này, vì đây có xu hướng là kiểu hoạt động "cháy và quên".


"lửa và quên" là rất liên quan! Ha
LinusGeffarth

0

dựa trên câu trả lời của @ cc, tôi đã sửa đổi phần mở rộng của anh ấy để làm mờ một chế độ xem

tiện ích mở rộng UIView {

    func mờ () {
        // Làm mờ chế độ xem hiện tại
        let fadeView = UIVisualEffectView (frame: self.bounds)
        self.addSubview (dimView)
        UIView.animate (với Độ bão hòa: 0,25) {
            mờView.effect = UIBlurEffect (kiểu: .dark)
        }
    }

    func unblur () {
        cho childView trong lượt xem phụ {
            bảo vệ let effectView = childView as? UIVisualEffectView khác {tiếp tục}
            UIView.animate (withDuration: 2.5, hoạt ảnh: {
                effectView.effect = nil
            }) {
                didFinish trong
                effectView.removeFromSuperview ()
            }
        }
    }
}

0

Cải thiện phản hồi @ Tel4tel và @cc, đây là phần mở rộng với các tham số và giải thích ngắn gọn.

extension UIView {

    // Perform a blur animation in the whole view
    // Effect tone can be .light, .dark, .regular...
    func blur(duration inSeconds: Double, effect tone: UIBlurEffectStyle) {
        let blurView = UIVisualEffectView(frame: self.bounds)
        self.addSubview(blurView)
        UIView.animate(withDuration: inSeconds) {
            blurView.effect = UIBlurEffect(style: tone)
        }
    }

    // Perform an unblur animation in the whole view
    func unblur(duration inSeconds: Double) {
        for childView in subviews {
            guard let effectView = childView as? UIVisualEffectView else { continue 
        }
            UIView.animate(withDuration: inSeconds, animations: {
                effectView.effect = nil
            }){
                didFinish in effectView.removeFromSuperview()
            }
        }
    }
}

Sau đó, bạn có thể sử dụng nó như: view.blur(duration: 5.0, effect: .light) hoặc view.unblur(duration: 3.0)

Hãy nhớ KHÔNG sử dụng nó trong viewDidLoad()vì nó sẽ ghi đè hoạt ảnh. Ngoài ra, khi chạy trên Trình mô phỏng, hãy chuyển đồ họa lên Mức cao hơn để có thể xem hoạt ảnh (Gỡ lỗi> Ghi đè chất lượng đồ họa> Chất lượng cao).

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.