web-dev-qa-db-fra.com

Comment implémenter UIVisualEffectView dans UITableView avec des séquences adaptatives

Je voudrais implémenter UIVisualEffectView pour appliquer un effet de flou à une vue afin de montrer la vue qui la sous-tend. 

Cette vue qui devrait avoir un arrière-plan flou est une UITableViewController intégrée à une UINavigationController. Elle sera présentée dans une fenêtre popover sur iPad ou sera présentée en mode plein écran sur iPhone, grâce à iOS 8 adaptations ). Lorsque ce contrôleur de vue est affiché dans un popover, je souhaite que l'arrière-plan brouille ce qui se trouve sous celui-ci. Lorsqu'il est affiché en plein écran, je souhaite que l'arrière-plan brouille le contrôleur de vue précédent. 

J'ai essayé de mettre cela en œuvre et je n'ai pas réussi. Je n'arrive même pas à obtenir l'effet de flou pour le popover. J'ai pensé que ce code devrait faire l'affaire:

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

J'ai également essayé d'ajouter la sous-vue au tableView.backgroundView, j'ai essayé de définir la backgroundView sur ma effectView, j'ai essayé d'utiliser des contraintes Autolayout au lieu de définir le cadre, mais rien n'a fonctionné. Pouvez-vous m'aider à accomplir le comportement souhaité?

Un exemple de ce que je cherche à obtenir:
Popover iPad:
enter image description here

présentation modale iPhone:
enter image description here

27
Jordan H

J'ai enfin trouvé une solution. J'ai dû créer deux séquences distinctes - une pour une présentation Popover appelée uniquement sur iPad et l'autre, une séquence modale avec Style de présentation défini sur Plein écran (c'est important) pour iPhone.

Dans le contrôleur de vue de table présenté, dans viewDidLoad, ce code appliquera l'effet de flou souhaité (et le bonus, uniquement s'ils n'ont pas désactivé les effets de transparence):

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

Cela provoque l’arrière-plan du tableau comme dans les captures d’écran. Pour iPhone, l’astuce consistait à s’assurer qu’elle était présentée à l’écran, tandis que pour iPad, il fallait supprimer backgroundColor dans popoverPresentationController.

46
Jordan H

Un exemple rapide pour ajouter le flou en utilisant Adaptivity:

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

Un peu tard pour la table avec celui-ci, mais la meilleure solution pour moi (sous ios8 +) était de prendre un UIVisualEffectView dans le Storyboard et d'en faire la vue racine de mon ViewController. Ajoutez ensuite ma tableview à celle

enter image description here

Pour trouver la vue des effets visuels, allez dans le sélecteur de composants (vous ne savez pas comment on l'appelle) en bas à droite et recherchez VisualEffectView.

enter image description here

Cela semble être un moyen beaucoup plus facile de s'y prendre et s'inscrit dans la recommandation d'Apple de faire autant que possible sur le Storyboard.

5
bolnad

Un petit changement pour 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

    }
0
Jeremy Andrews