Меньше размытия с помощью "Визуального эффекта с размытием"?
Название в значительной степени просит все это...
Я играю с iOS8 Visual Effect View with Blur
. Это над UIImageView
, которое показывает пользовательскую фотографию. Представление, размещенное в самом содержимом contentView, является моим собственным пользовательским представлением, показывает вид графика/календаря. Большая часть графика календаря прозрачна. Размытие, которое оно применяет к фотографии за ней, действительно тяжело. Я бы хотел пропустить больше деталей. Но Apple только, кажется, дает три законченных значения:
typedef enum {
UIBlurEffectStyleExtraLight,
UIBlurEffectStyleLight,
UIBlurEffectStyleDark
} UIBlurEffectStyle;
Я общался с разными цветами альфа и фона UIVisualEffectView
(хотя документация предупреждает об этом), но это не делает ничего, кроме ухудшения.
Ответы
Ответ 1
Причина, по которой вы получаете сильное размытие, заключается в том, что стиль эффекта размытия влияет на уровень яркости изображения, а не на количество размытости.
![enter image description here]()
К сожалению, хотя Apple явно имеет возможность контролировать количество размытия, применяемого программным способом, - попробуйте медленно перемещаться по стартовой панели, чтобы посмотреть переход на размытие Spotlight - я не вижу, чтобы какой-либо публичный API передавал сумму размытия UIBlurEffect
.
В этом сообщении утверждается, что настройка цвета фона альфа приведет к увеличению размытости. Это стоит попробовать, но я не вижу, где это задокументировано: Как угасать UIVisualEffectView и/или UIBlurEffect?
Ответ 2
Жаль, что Apple не предоставила никаких вариантов эффекта размытия. Но это обходное решение сработало для меня - оживление эффекта размытия и приостановка его до завершения.
func blurEffectView(enable enable: Bool) {
let enabled = self.blurView.effect != nil
guard enable != enabled else { return }
switch enable {
case true:
let blurEffect = UIBlurEffect(style: .ExtraLight)
UIView.animateWithDuration(1.5) {
self.blurView.effect = blurEffect
}
self.blurView.pauseAnimation(delay: 0.3)
case false:
self.blurView.resumeAnimation()
UIView.animateWithDuration(0.1) {
self.blurView.effect = nil
}
}
}
и расширения UIView для приостановки (с задержкой) и возобновления анимации просмотров
extension UIView {
public func pauseAnimation(delay 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(), fromLayer: nil)
layer.speed = 0.0
layer.timeOffset = pausedTime
})
CFRunLoopAddTimer(CFRunLoopGetCurrent(), timer, kCFRunLoopCommonModes)
}
public func resumeAnimation() {
let pausedTime = layer.timeOffset
layer.speed = 1.0
layer.timeOffset = 0.0
layer.beginTime = layer.convertTime(CACurrentMediaTime(), fromLayer: nil) - pausedTime
}
}
Ответ 3
Это работает для меня.
Я помещаю UIVisualEffectView
в UIView
перед добавлением в мое представление.
Я делаю эту функцию более простой. Вы можете использовать эту функцию, чтобы размыть любую область в вашем представлении.
func addBlurArea(area: CGRect, style: UIBlurEffectStyle) {
let effect = UIBlurEffect(style: style)
let blurView = UIVisualEffectView(effect: effect)
let container = UIView(frame: area)
blurView.frame = CGRect(x: 0, y: 0, width: area.width, height: area.height)
container.addSubview(blurView)
container.alpha = 0.8
self.view.insertSubview(container, atIndex: 1)
}
Например, вы можете размыть все свое мнение, вызвав:
addBlurArea(self.view.frame, style: UIBlurEffectStyle.Dark)
Вы можете изменить Dark
на желаемый стиль размытия и 0.8
на нужное значение альфа
Ответ 4
Да, ты можешь.
Вот пример UIImageView с эффектом размытия на нем. Не забудьте добавить изображение в UIImageView.
Отрегулируйте степень размытия с помощью blurEffectView.alpha = 0,8 (от 0 до 1)
import UIKit
class BlurEffectImageView: UIImageView {
override func awakeFromNib() {
super.awakeFromNib()
addBlurEffect()
}
private func addBlurEffect(){
let blurEffect = UIBlurEffect(style: .light)
let blurEffectView = UIVisualEffectView(effect: blurEffect)
blurEffectView.alpha = 0.8
blurEffectView.autoresizingMask = [.flexibleWidth, .flexibleHeight]
blurEffectView.translatesAutoresizingMaskIntoConstraints = false
addSubview(blurEffectView)
NSLayoutConstraint(item: blurEffectView, attribute: .centerX, relatedBy: .equal, toItem: self, attribute: .centerX, multiplier: 1.0, constant: 0).isActive = true
NSLayoutConstraint(item: blurEffectView, attribute: .centerY, relatedBy: .equal, toItem: self, attribute: .centerY, multiplier: 1.0, constant: 0).isActive = true
NSLayoutConstraint(item: blurEffectView, attribute: .height, relatedBy: .equal, toItem: self, attribute: .height, multiplier: 1.0, constant: 0).isActive = true
NSLayoutConstraint(item: blurEffectView, attribute: .width, relatedBy: .equal, toItem: self, attribute: .width, multiplier: 1.0, constant: 0).isActive = true
}
}
Ответ 5
Решение похоже на какой - то здесь, но проще, является использование UIViewPropertyAnimator (IOS 10+) и установите его fractionComplete
свойство некоторого значения между 0 и 1.
// add blur view to image view
let imgBlur = UIVisualEffectView()
imgView.addSubview(imgBlur)
imgBlur.frame = imgView.bounds
// create animator to control blur strength
let imgBlurAnimator = UIViewPropertyAnimator()
imgBlurAnimator.addAnimations {
imgBlur.effect = UIBlurEffect(style: .dark)
}
// 50% blur
imgBlurAnimator.fractionComplete = 0.5
Обратите внимание, что если вы планируете изменять fractionComplete
зависимости от жеста панорамирования, вида прокрутки, ползунка и т.д., Вам нужно установить pausesOnCompletion = true
(iOS 11+).
Ответ 6
Добавьте BlurEffectView в представление с представлением alpha < 1
func addBlurEffectView() -> Void {
if !UIAccessibilityIsReduceTransparencyEnabled() {
let viewContainer = UIView()
viewContainer.frame = self.view.bounds
viewContainer.alpha = 0.5
let blurEffect = UIBlurEffect(style: .dark)
let blurEffectView = UIVisualEffectView(effect: blurEffect)
blurEffectView.layer.zPosition = -0.5;
blurEffectView.frame = self.view.bounds;
blurEffectView.autoresizingMask = [.flexibleWidth, .flexibleHeight]
viewContainer.addSubview(blurEffectView)
self.view.addSubview(viewContainer)
self.view.sendSubview(toBack: viewContainer)
}
}
Ответ 7
Я использую UIVisualEffectView, как это, чтобы получить регулируемые круги размытия. Уровень размытия контролируется ползунком, который контролирует альфа. Я также включу обработчик слайдера ниже. Размер круга размытия можно регулировать с помощью щепотки. Я включу это тоже. И вы можете перетаскивать круги размытия. Я оставлю это как упражнение для читателя. Если вы хотите размытый прямоугольник, просто не закругляйте углы. Чтобы увидеть этот дизайн кругов размытия в действии, загрузите приложение MemeSoEasy (бесплатно), добавьте фотографию (на которую можно поместить круг размытия), а затем добавьте круг размытия.
UIVisualEffectView *blurVisualEffectView;
UIVisualEffect *blurEffect;
blurEffect = [UIBlurEffect effectWithStyle:UIBlurEffectStyleLight];
blurVisualEffectView = [[UIVisualEffectView alloc] initWithEffect:blurEffect];
blurVisualEffectView.frame = lastChosenBlurCircleRect;
blurVisualEffectView.center = CGPointMake(halfScreenX, halfScreenY);
[self.view addSubview:blurVisualEffectView];
CGFloat blurCornerRadius = blurVisualEffectView.bounds.size.width/2;
[[blurVisualEffectView layer]setCornerRadius:blurCornerRadius];
[[blurVisualEffectView layer]setMasksToBounds:YES];
[[blurVisualEffectView layer] setBorderWidth:4.0f];
[[blurVisualEffectView layer] setBorderColor:[UIColor blueColor].CGColor];
blurVisualEffectView.userInteractionEnabled = NO;
blurVisualEffectView.alpha = 0.97;
[blurArray addObject:blurVisualEffectView];
Слайдер-обработчик:
Обратите внимание, что я храню свои объекты размытия в массиве, поэтому я могу позволить пользователям создавать столько, сколько нужно. Обработчик слайдера работает с последним объектом в массиве. Минимальное и максимальное значения ползунка - 0,0 и 1,0.
UISlider *slider_ = (UISlider *)sender;
CGFloat ourSliderValue = slider_.value;
UIVisualEffectView *currentBlurObject =
[blurArray objectAtIndex:blurArray.count - 1];
currentBlurObject.alpha = ourSliderValue;
Обработчик изменения размера для распространения щепотки
int changeInWidth = 0; // one pixel at a time
if (pinchGesture.scale > 1.0) {
changeInWidth++;
}
if (pinchGesture.scale < 1.0) {
changeInWidth--;
}
UIVisualEffectView *currentBlurObject =
[blurArray objectAtIndex:blurArray.count - 1];
CGPoint oldCenter = currentBlurObject.center;
currentBlurObject.frame = CGRectMake(0, 0, currentBlurObject.frame.size.width + changeInWidth, currentBlurObject.frame.size.width + changeInWidth);
currentBlurObject.center = oldCenter;
lastChosenBlurCircleRect = currentBlurObject.frame;
CGFloat blurCornerRadius = currentBlurObject.frame.size.width/2;
[[currentBlurObject layer]setCornerRadius:blurCornerRadius];
Ответ 8
Этот ответ основан на Mitja Semolic отличный предыдущий ответ. Я преобразовал его в swift 3, добавил объяснение тому, что происходит в коментах, сделал его расширением UIViewController, чтобы любой VC мог его вызвать по своему усмотрению, добавил неровное представление, чтобы показать выборочное приложение, и добавил блок завершения, чтобы контроллер вызова может делать все, что захочет, по завершении размытия.
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
}
}
Я подтвердил, что он работает как с iOS 10.3.1, так и с iOS 11
Ответ 9
Для того, чтобы использовать размытие с уровнем размытия - используйте мое расширение ниже:
public extension UIView {
func applyBlur(level: CGFloat) {
let context = CIContext(options: nil)
self.makeBlurredImage(with: level, context: context, completed: { processedImage in
let imageView = UIImageView(image: processedImage)
imageView.translatesAutoresizingMaskIntoConstraints = false
self.addSubview(imageView)
NSLayoutConstraint.activate([
imageView.topAnchor.constraint(equalTo: self.topAnchor),
imageView.leadingAnchor.constraint(equalTo: self.leadingAnchor),
imageView.trailingAnchor.constraint(equalTo: self.trailingAnchor),
imageView.bottomAnchor.constraint(equalTo: self.bottomAnchor),
])
})
}
private func makeBlurredImage(with level: CGFloat, context: CIContext, completed: @escaping (UIImage) -> Void) {
// screen shot
UIGraphicsBeginImageContextWithOptions(self.frame.size, false, 1)
self.layer.render(in: UIGraphicsGetCurrentContext()!)
let resultImage = UIGraphicsGetImageFromCurrentImageContext()!
UIGraphicsEndImageContext()
let beginImage = CIImage(image: resultImage)
// make blur
let blurFilter = CIFilter(name: "CIGaussianBlur")!
blurFilter.setValue(beginImage, forKey: kCIInputImageKey)
blurFilter.setValue(level, forKey: kCIInputRadiusKey)
// extend source image na apply blur to it
let cropFilter = CIFilter(name: "CICrop")!
cropFilter.setValue(blurFilter.outputImage, forKey: kCIInputImageKey)
cropFilter.setValue(CIVector(cgRect: beginImage!.extent), forKey: "inputRectangle")
let output = cropFilter.outputImage
var cgimg: CGImage?
var extent: CGRect?
let global = DispatchQueue.global(qos: .userInteractive)
global.async {
extent = output!.extent
cgimg = context.createCGImage(output!, from: extent!)!
let processedImage = UIImage(cgImage: cgimg!)
DispatchQueue.main.async {
completed(processedImage)
}
}
}
}
Как пользоваться. Запустите его, если кадр уже сделан. Например, в viewDidAppear:
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
myView.applyBlur(level: 5)
}