web-dev-qa-db-fra.com

Présentation du modal dans iOS 13 avec une hauteur personnalisée

Dans iOS 13, il y a un nouveau comportement pour le contrôleur de vue modale lors de sa présentation, et j'ai trouvé que l'application intégrée Photo présente un contrôleur de vue de modèle plus petit.

Comment puis-je présenter un viewController avec une taille personnalisée comme celle-ci can et peut glisser jusqu'à une plus grande hauteur?

smaller height

larger height

Captures d'écran de l'application photo système.

6
jrjian

Répondre en Swift

Je cherchais un moyen de reproduire ce type de comportement de ViewController, bien qu'avec une interface utilisateur de base, et j'ai trouvé une solution assez simple. Fondamentalement, vous créez un ViewController (CardViewContoller) avec un arrière-plan transparent, puis vous y ajoutez une vue semblable à une carte avec un UIPanGestureReconizer, qui vous permettra de le faire glisser et de le supprimer avec le ViewController.

Pour vous présenter, appelez simplement present, en définissant modalPresentationStyle sur .overCurrentContext Et modalTransitionStyle sur .coverVertical:

let cardVC = CardViewController()
cardVC.modalPresentationStyle = .overCurrentContext
cardVC.modalTransitionStyle = .coverVertical
present(cardVC, animated: true, completion: nil)

Dans CardViewController, qui peut être créé par programmation ou à l'aide d'Interface Builder, vous ajoutez un UIPanGestureRecognizer à votre vue de carte (contentView):

let panGestureRecognizer = UIPanGestureRecognizer(target: self, action: #selector(handleDismiss(recognizer:)))
panGestureRecognizer.cancelsTouchesInView = false
contentView.addGestureRecognizer(panGestureRecognizer)

Ensuite, ajoutez simplement une fonction @objc Qui répondra à UIPanGestureRecognizer:

    @objc
    func handleDismiss (recognizer: UIPanGestureRecognizer) {
        switch recognizer.state {
        case .changed:
            viewTranslation = recognizer.translation(in: view)
            UIView.animate(withDuration: 0.5, delay: 0, usingSpringWithDamping: 0.7, initialSpringVelocity: 1, options: .curveEaseOut, animations: {
                guard self.viewTranslation.y > 0 else {return}
                self.view.transform = CGAffineTransform(translationX: 0, y: self.viewTranslation.y)
            })
        case .ended:
            if viewTranslation.y < swipeThreshold {
                UIView.animate(withDuration: 0.5, delay: 0, usingSpringWithDamping: 0.7, initialSpringVelocity: 1, options: .curveEaseOut, animations: {
                    self.view.transform = .identity
                })
            } else {
                dismiss(animated: true, completion: nil)
            }
        default:
            break
        }
    }

swipeThreshold est une variable CGFloat avec une valeur de votre choix (200 fonctionne très bien pour moi), que si la traduction UIPanGestureRecognizer y dépasse, cela déclenchera le rejet du ViewController avec tous les éléments. De même, vous pouvez ajouter un simple bouton qui fermera le ViewController lors de l'appel de .touchUpInsidedismiss()

Si vous le souhaitez, vous pouvez consulter ce dépôt , dans lequel j'ai un exemple de projet qui présente ce comportement. De cette façon, vous pouvez créer vos propres cartes totalement personnalisables.

2
Nikita Alexander

Je ne pense pas que cela soit possible avec l'implémentation UIViewController standard - c'est-à-dire simplement en définissant une hauteur de présentation, même avec le nouveau style de présentation d'iOS 13.

Vous voudrez peut-être étudier une solution tierce (ou vous en inspirer) comme ceci:

https://github.com/MarioIannotta/PullUpController

0
Ash Cameron