【问题标题】:How to get rounded corner & dynamic height of popped custom modalPresentationStyle VC如何获得弹出的自定义modalPresentationStyle VC的圆角和动态高度
【发布时间】:2021-06-14 05:16:37
【问题描述】:

呈现VC时,默认样式不全屏,圆角如下图所示。

但我想控制modalPresentation的高度,假设默认为1/4屏幕高度,并根据tableView的弹出VC行动态更改。所以我在下面的代码基础上实现了一个custommodalPresentationStyle。

但是,我在之后发现了这些问题:

  1. 弹出的VC不是圆角而是矩形角。
  2. 我无法再拖动来移动弹出的 VC,它处于固定位置。
  3. 如果我可以根据它的 tableView 行数增加弹出的 VC 的高度会更好。不是必须的。
    @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)
    }
}

【问题讨论】:

    标签: ios swift uimodalpresentationstyle


    【解决方案1】:

    尝试将cornerRadius分配给您的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)
    }
    

    对于 vc 呈现位置的完全控制,您可以使用子 vc 和自动布局,对于当前子 vc(如模态演示样式),您可以在子 vc 顶部约束上使用 UIView.animate。

    这是子 vc 和自动布局的示例:

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

    结果如下:

    要为子 vc 演示动画制作动画,您可以使用 UIView.animate 函数进行顶级子 vc 约束,或者使用平移手势拖动它,或者任何您认为必要且有效的使用...

    显示它全屏简单设置子 vc 顶部锚到兴趣视图顶部:

    menuUp = firstChildVc.view.topAnchor.constraint(equalTo: view.topAnchor)
    

    【讨论】:

    • @ChuckZHB 我用子 vc 和自动布局的示例更新我的答案
    • 好的,角落的东西已经工作了,但是现在的 VC 是固定的,我不能像默认的模态演示 VC 那样拖动来移动它。你能看看这个吗?
    • @ChuckZHB 在我的示例中,我将顶部的子 vc 固定在视图的中心,因为要长时间编写所有代码以对其进行动画处理或拖动,请查看平移手势识别器和 UIview。动画...这只是向您展示另一种解决方案的示例:)
    • @ChuckZHB 我用一个子控制器、自动布局和点击按钮时的动画示例来更新我的答案,对于拖动,请参见 Pan Gesture...
    • 感谢您的回复。好吧,我实际上并不是在寻找关于模态演示的动画。默认动画present(vc, animated: true) 对我来说没问题。我希望在我的帖子中以上述 gif 显示后拖动和移动模型呈现 VC。因为默认情况下,当我以模态方式呈现 VC 时,呈现的可以支持拖动移动。希望我说清楚。是的,我会看看 Pan Gesture。
    猜你喜欢
    • 2020-08-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-08-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-04-17
    相关资源
    最近更新 更多