0

When present a VC, the default style is not cover full screen and with a rounded corner like below gif illustrated.

gif

But I want to control the height of modalPresentation, let's say a 1/4 screen height by default and dynamic changed according to tableView's rows of popped VC. So I implement a custom modalPresentationStyle on the base VC wit below code.

However, I found these issues after:

  1. The popped VC is not rounded corner but with rectangle corner.
  2. I cannot drag to move the popped VC anymore, it is in fixed position.
  3. It would be more better if I could to increment the popped VC's height per its tableView rows count. Not a must item.
    @objc func collectButtonTapped(_ sender: Any?) {
        
        let vc = PlayListViewController()
        vc.modalPresentationStyle = .custom
        vc.transitioningDelegate = self
        
        present(vc, animated: true)
        
    }
    
    func presentationController(forPresented presented: UIViewController, presenting: UIViewController?, source: UIViewController) -> UIPresentationController? {
        return HalfSizePresentationController(presentedViewController: presented, presenting: presentingViewController)
    }

class HalfSizePresentationController: UIPresentationController {
    override var frameOfPresentedViewInContainerView: CGRect {
        guard let bounds = containerView?.bounds else { return .zero }
        return CGRect(x: 0, y: bounds.height * 0.75, width: bounds.width, height: bounds.height * 0.75)
    }
}
Zhou Haibo
  • 1,681
  • 1
  • 12
  • 32

1 Answers1

0

Try to assign cornerRadius to your vc:

@objc func collectButtonTapped(_ sender: Any?) {
    
    let vc = PlayListViewController()
    vc.modalPresentationStyle = .custom
    vc.transitioningDelegate = self
    // assign corner radius
    vc.view.layer.cornerRadius = 20
    vc.view.clipsToBounds = true
    vc.view.layer.maskedCorners = [.layerMaxXMinYCorner, .layerMinXMinYCorner] // this is for corner radius only for top
    present(vc, animated: true)
}

for total control of vc presented position, you can use child vc and auto layout, for present child vc (like a modal presentation style) you can use UIView.animate on child vc top constraint.

this is an example of child vc and auto layout:

import UIKit

class YourController: UIViewController {

private lazy var firstChildVc = AiutiFirst()

let myButton: UIButton = {
    let b = UIButton(type: .system)
    b.layer.cornerRadius = 10
    b.clipsToBounds = true
    b.backgroundColor = .black
    b.setTitleColor(.white, for: .normal)
    b.setTitle("Present", for: .normal)
    b.addTarget(self, action: #selector(handlePresent), for: .touchUpInside)
    b.translatesAutoresizingMaskIntoConstraints = false
    
    return b
}()

override func viewDidLoad() {
    super.viewDidLoad()
    view.backgroundColor = .blue
    addChildVC()
}

var up = false

@objc fileprivate func handlePresent() {
    
    print("present")
    
    if up == false {
        UIView.animate(withDuration: 0.3, delay: 0, options: .curveEaseOut) {
            self.menuDown?.isActive = false
            self.menuUp?.isActive = true
            self.myButton.setTitle("Dismiss", for: .normal)
            self.view.layoutIfNeeded()
        } completion: { _ in
            print("Animation completed")
            self.up = true
        }
    } else {
        UIView.animate(withDuration: 0.3, delay: 0, options: .curveEaseOut) {
            self.menuUp?.isActive = false
            self.menuDown?.isActive = true
            self.myButton.setTitle("Present", for: .normal)
            self.view.layoutIfNeeded()
        } completion: { _ in
            print("Animation completed")
            self.up = false
        }
    }
}

var menuUp: NSLayoutConstraint?
var menuDown: NSLayoutConstraint?

fileprivate func addChildVC() {
    addChild(firstChildVc)

    firstChildVc.view.translatesAutoresizingMaskIntoConstraints = false

    firstChildVc.view.layer.cornerRadius = 20
    firstChildVc.view.clipsToBounds = true
    firstChildVc.view.layer.maskedCorners = [.layerMaxXMinYCorner, .layerMinXMinYCorner] // this is for corner radius only for top
    
    view.addSubview(firstChildVc.view)

    menuUp = firstChildVc.view.topAnchor.constraint(equalTo: view.centerYAnchor)
    menuDown = firstChildVc.view.topAnchor.constraint(equalTo: view.bottomAnchor)
    menuDown?.isActive = true
    firstChildVc.view.leadingAnchor.constraint(equalTo: view.leadingAnchor).isActive = true
    firstChildVc.view.trailingAnchor.constraint(equalTo: view.trailingAnchor).isActive = true
    firstChildVc.view.bottomAnchor.constraint(equalTo: view.bottomAnchor).isActive = true

    firstChildVc.didMove(toParent: self)
    
    view.addSubview(myButton)
    myButton.bottomAnchor.constraint(equalTo: view.centerYAnchor, constant: -40).isActive = true
    myButton.widthAnchor.constraint(equalToConstant: 200).isActive = true
    myButton.heightAnchor.constraint(equalToConstant: 50).isActive = true
    myButton.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true
 }
}

And this is the result:

enter image description here

To animate child vc presentation you can use UIView.animate function for top child vc constraint, or Pan gesture do drag it, or whatever you deem necessary and valid to use...

to show it full screen simple set child vc top anchor to top of intere view:

menuUp = firstChildVc.view.topAnchor.constraint(equalTo: view.topAnchor)
Fabio
  • 5,432
  • 4
  • 22
  • 24
  • @ChuckZHB I update my answer with an example of child vc and auto layout – Fabio Jun 14 '21 at 06:09
  • Ok, the corner stuff is worked, but the present VC is fixed, I can't drag to move it like a default modal presentation VC do. Could u look in to this? – Zhou Haibo Jun 14 '21 at 06:51
  • @ChuckZHB in my example I fix the top child vc on center of a view, because is to long to write all of code to animate or drag it, take a look to pan gesture recognizer and UIview.animate... It's only an example to show you another way for solution :) – Fabio Jun 14 '21 at 07:27
  • @ChuckZHB I update my answer with an example of child controller, auto layout and animation when button is tapped, for drag see Pan Gesture... – Fabio Jun 14 '21 at 08:02
  • Thanks for the reply. Well, I'm not looking to animation on modal presentation actually. The default animation `present(vc, animated: true)` is ok for me. I'm looking to drag and move the model present VC after its presented as above gif show in my post. Because by defaul, when I present a VC modally, that presented one could support drag to move. Hope I make it clear. And yeah, I will look to Pan Gesture. – Zhou Haibo Jun 14 '21 at 08:41