web-dev-qa-db-fra.com

Comment présenter un ViewController sur un demi-écran

J'ai une UIViewController qui n'a qu'une UIView qui couvre 1/3 du viewController à partir du bas. Comme ça

 enter image description here

Je veux présenter ce viewController sur un autre ViewController. Il devrait apparaître du bas animé et il devrait être rejeté du bas animé.

Mais je ne veux pas que cela couvre tout l'écran. Le viewController sur lequel il est présenté doit être visible à l'arrière.

Cela semble être une question fondamentale, mais je suis incapable de le faire. Quelqu'un peut-il s'il vous plaît me diriger vers la direction?

Modifier:

C'est ce que j'ai essayé jusqu'à présent. J'ai créé ces cours

// MARK: -

class MyFadeInFadeOutTransitioning: NSObject, UIViewControllerTransitioningDelegate {
var backgroundColorAlpha: CGFloat = 0.5
var shoulDismiss = false

func animationController(forPresented presented: UIViewController, presenting: UIViewController, source: UIViewController) -> UIViewControllerAnimatedTransitioning? {

    let fadeInPresentAnimationController = MyFadeInPresentAnimationController()
        fadeInPresentAnimationController.backgroundColorAlpha = backgroundColorAlpha

    return fadeInPresentAnimationController
}

func animationController(forDismissed dismissed: UIViewController) -> UIViewControllerAnimatedTransitioning? {

    let fadeOutDismissAnimationController = MyFadeOutDismissAnimationController()

    return fadeOutDismissAnimationController
}

}

// MARK: -

class MYFadeInPresentAnimationController: NSObject, UIViewControllerAnimatedTransitioning {

let kPresentationDuration = 0.5
var backgroundColorAlpha: CGFloat?

func transitionDuration(using transitionContext: UIViewControllerContextTransitioning?) -> TimeInterval {
    return kPresentationDuration
}

func animateTransition(using transitionContext: UIViewControllerContextTransitioning) {
    let toViewController = transitionContext.viewController(forKey: UITransitionContextViewControllerKey.to)!

    toViewController.view.backgroundColor = UIColor.clear

    let toViewFrame = transitionContext.finalFrame(for: toViewController)
    let containerView = transitionContext.containerView

    if let pickerContainerView = toViewController.view.viewWithTag(kContainerViewTag) {
        let transform = CGAffineTransform(translationX: 0.0, y: pickerContainerView.frame.size.height)
        pickerContainerView.transform = transform
    }

    toViewController.view.frame = toViewFrame
    containerView.addSubview(toViewController.view)

    UIView.animate(withDuration: 0.3, delay: 0.0, options: .curveLinear , animations: {
        toViewController.view.backgroundColor = UIColor(white: 0.0, alpha: self.backgroundColorAlpha!)

        if let pickerContainerView = toViewController.view.viewWithTag(kContainerViewTag) {
            pickerContainerView.transform = CGAffineTransform.identity
        }

    }) { (finished) in
        transitionContext.completeTransition(true)
    }
}

}

// MARK: -

class MYFadeOutDismissAnimationController: NSObject, UIViewControllerAnimatedTransitioning {
let kDismissalDuration = 0.15

func transitionDuration(using transitionContext: UIViewControllerContextTransitioning?) -> TimeInterval {
    return kDismissalDuration
}

func animateTransition(using transitionContext: UIViewControllerContextTransitioning) {
    let fromViewController = transitionContext.viewController(forKey: UITransitionContextViewControllerKey.from)!
    let toViewController = transitionContext.viewController(forKey: UITransitionContextViewControllerKey.to)!
    let containerView = transitionContext.containerView

    containerView.addSubview(toViewController.view)
    containerView.sendSubview(toBack: toViewController.view)

    UIView.animate(withDuration: kDismissalDuration, delay: 0.0, options: .curveLinear, animations: {
        //            fromViewController.view.backgroundColor = UIColor.clearColor()
        //            if let pickerContainerView = toViewController.view.viewWithTag(kContainerViewTag) {
        //                let transform = CGAffineTransformMakeTranslation(0.0, pickerContainerView.frame.size.height)
        //                pickerContainerView.transform = transform
        //            }
        fromViewController.view.alpha = 0.0

    }) { (finished) in
        let canceled: Bool = transitionContext.transitionWasCancelled
        transitionContext.completeTransition(true)

        if !canceled {
            UIApplication.shared.keyWindow?.addSubview(toViewController.view)
        }
    }
}

}

Et dans le viewController qui est présenté, je fais comme suit

var customTransitioningDelegate: MYFadeInFadeOutTransitioning? = MYFadeInFadeOutTransitioning()

    init() {
    super.init(nibName: "SomeNibName", bundle: Bundle.main)
    transitioningDelegate = customTransitioningDelegate
    modalPresentationStyle = .custom

    customTransitioningDelegate?.backgroundColorAlpha = 0.0
} 

Il présente le viewController et je peux également voir le viewController en arrière-plan. Mais je veux qu'il soit présenté du bas avec une animation. Et rejetez au fond avec animation. Comment puis je faire ça ?

9
Umair Afzal

Je recommanderais d'implémenter cette fonctionnalité en utilisant les vues de conteneur. Jetez un oeil ici pour référence.

Cela signifie que vous pouvez afficher un UIViewController (et ses sous-classes) intégré dans un UIView dans un autre ViewController. Ensuite, vous pouvez animer le fondu ou ce que vous voulez. 

6
regetskcob

Il y a le code mis à jour pour réaliser cette fonctionnalité. Sur l'action où vous souhaitez présenter ViewController

  @IBAction func btnShow(_ sender: Any) {
        let storyboard = UIStoryboard(name: "Main", bundle: nil)
        let pvc = storyboard.instantiateViewController(withIdentifier: "SubViewController") as! SubViewController
        pvc.modalPresentationStyle = UIModalPresentationStyle.overCurrentContext

        self.present(pvc, animated: true, completion: nil)
    } 

Allez dans StoryBoard sélectionnez subViewController ajoutez un UIViews dedans pour effet de flou définissez sa contrainte sur (haut: 0, bas: 0, premier: 0, suivi: 0). pour tous les côtés et changez sa couleur en black et définissez la valeur alpha comme vous le souhaitez. Et après cela, ajoutez un autre UIViews pour les options, définissez ses contraintes sur (top: -, Bottom: 0, Leading: 0, Trailing: 0), définissez la contrainte height sur hauteur égale avec superview (self.View) et changez son multiplicateur en 0.33 ou 0.34. J'espère que cela vous aidera .. Screen Short.  enter image description here

2

Vous pouvez utiliser un UIPresentationController pour y parvenir. Implémentez la méthode UIViewControllerTransitioningDelegate sur la présentation de ViewController et renvoyez votre PresentationController à partir de la méthode déléguée

func presentationController(forPresented presented: UIViewController, 
                          presenting: UIViewController?, 
                              source: UIViewController) -> UIPresentationController? 

Vous pouvez consulter cette réponse qui a une exigence similaire. Vous pouvez également utiliser l'animation UIView ou le contrôleur de vue intégré comme suggéré dans les autres réponses.

Modifier:

exemple de projet trouvé dans Github 

https://github.com/martinnormark/HalfModalPresentationController

2
Suhit Patil