Подтвердить что ты не робот

Как реализовать UIVisualEffectView в UITableView с адаптивными сегментами

Я хотел бы реализовать UIVisualEffectView, чтобы применить эффект размытия к представлению, чтобы показать представление, которое находится за ним.

Этот вид, который должен иметь размытый фон, представляет собой UITableViewController, встроенный в UINavigationController, и он будет либо представлен в popover на iPad, либо будет представлен полноэкранным образом на iPhone, благодаря iOS 8 адаптивных сегментов (присутствует как Popover). Когда этот диспетчер представлений находится в popover, я хочу, чтобы фон размыл то, что находится под popover, и когда он отображается в полноэкранном режиме, я хочу, чтобы фон размыл предыдущий контроллер представления.

Я попытался реализовать это и не добился успеха. Я даже не могу заставить эффект размытия работать для popover. Я думал, что этот код должен сделать трюк:

//In viewDidLoad on the UITableViewController subclass:
let effectView = UIVisualEffectView(effect: UIBlurEffect(style: .Light))
effectView.frame = tableView.frame
tableView.addSubview(effectView)

Я также попытался добавить subview к tableView.backgroundView, я попробовал установить backgroundView на мой effectView, я пытался использовать ограничения Autolayout вместо установки фрейма, но ничего не сработало. Можете ли вы помочь мне выполнить желаемое поведение?

Пример того, что я пытаюсь получить:
iPad popover:
enter image description here

iPhone модальная презентация:
enter image description here

4b9b3361

Ответ 1

Наконец-то я нашел решение. Мне пришлось создать два отдельных сегмента: один для презентации Popover, который называется только на iPad, а другой - модальный сегмент с стилем презентации, установленным на Full Full Screen (что важно) для iPhone.

В представленном контроллере табличного представления в viewDidLoad этот код применит желаемый эффект размытия (и бонус, только если они не отключили эффекты прозрачности):

if (!UIAccessibilityIsReduceTransparencyEnabled()) {
    tableView.backgroundColor = UIColor.clear
    let blurEffect = UIBlurEffect(style: .light)
    let blurEffectView = UIVisualEffectView(effect: blurEffect)
    tableView.backgroundView = blurEffectView

    //if inside a popover
    if let popover = navigationController?.popoverPresentationController {
        popover.backgroundColor = UIColor.clear
    }

    //if you want translucent vibrant table view separator lines
    tableView.separatorEffect = UIVibrancyEffect(blurEffect: blurEffect)
}

Это приводит к тому, что фон таблицы отображается так же, как на скриншотах. Трюк для iPhone заключался в том, чтобы обеспечить его отображение на экране, в то время как трюк для iPad заключался в том, чтобы удалить backgroundColor в popoverPresentationController.

Ответ 2

Быстрый пример добавления размытия с использованием адаптивности:

extension ViewController: UIPopoverPresentationControllerDelegate {

 override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {

    // Grab the destination view controller and set the presentation delegate
    let viewController = segue.destinationViewController as UIViewController
    viewController.popoverPresentationController?.delegate = self
    viewController.presentationController?.delegate = self
  }

  // Note: Only called for FormSheet and Popover
  func adaptivePresentationStyleForPresentationController(controller: UIPresentationController) -> UIModalPresentationStyle {
    switch controller.presentedViewController {
    case let vc as PopoverViewController:
      return .None // Keep the popover in Compact screens
    default:
      return .OverFullScreen
    }
  }

  func presentationController(controller: UIPresentationController, viewControllerForAdaptivePresentationStyle style: UIModalPresentationStyle) -> UIViewController? {
    // This is a custom method on UIViewController
    controller.presentedViewController.createBlur()

    // Wrap in a Navigation Controller, the controller should add a title and bar buttons
    if !(presentedViewController is UINavigationController) {
      return UINavigationController(rootViewController: presentedViewController)
    }
  }
}

extension UIViewController {
  func createBlur(effectStyle: UIBlurEffectStyle = .Light) {
    if !UIAccessibilityIsReduceTransparencyEnabled() {
      view.backgroundColor = UIColor.clearColor()

      let blurView = UIVisualEffectView(effect: UIBlurEffect(style: effectStyle))
      blurView.autoresizingMask = UIViewAutoresizing.FlexibleHeight | UIViewAutoresizing.FlexibleWidth
      blurView.frame = view.bounds

      view.insertSubview(blurView, atIndex: 0)
    }
  }
}

extension UITableViewController {
  override func createBlur(effectStyle: UIBlurEffectStyle = defaultBlurEffectStyle) {
    if !UIAccessibilityIsReduceTransparencyEnabled() {
      tableView.backgroundColor = UIColor.clearColor()

      let blurEffect = UIBlurEffect(style: effectStyle)      
      tableView.backgroundView = UIVisualEffectView(effect: blurEffect)
      tableView.separatorEffect = UIVibrancyEffect(forBlurEffect: blurEffect)
    }
  }
}

Ответ 3

Немного поздно к столу с этим, но лучшим решением для меня (в ios8 +) было взятие UIVisualEffectView в Раскадке и сделать его корневым представлением моего ViewController. Затем добавьте мое представление в таблицу

enter image description here

Чтобы найти визуальный эффект, перейдите в раздел "Выбор компонентов" (не уверен, что это вызвало) в нижней правой части и выполните поиск VisualEffectView

enter image description here

Это похоже на гораздо более простой способ сделать это, и соответствует рекомендациям Apple, чтобы как можно больше сделать на раскадровке

Ответ 4

Небольшое изменение для IOS 10 Swift 3

if #available(iOS 10.0, *) {
        let blurEffect = UIBlurEffect(style: .prominent)
        let blurEffectView = UIVisualEffectView(effect: blurEffect)
        groupTable.backgroundView = blurEffectView

    } else {
        let blurEffect = UIBlurEffect(style: .dark)
        let blurEffectView = UIVisualEffectView(effect: blurEffect)
        groupTable.backgroundView = blurEffectView

    }