使用自定义高度在 iOS 13 中显示模态

jrj*_*ian 10 iphone user-interface objective-c ios13

在 iOS 13 中,模态视图控制器在呈现时有一个新行为。我发现内置的 App Photo 呈现了一个较小的模型视图控制器。

如何呈现具有这样自定义大小的视图控制器?并且可以向上滑动到更大的高度?

较小的高度

更大的高度

来自系统照片应用程序的图片截图。

Arv*_*tel 11

是的,可以在 iOS 13 中以自定义高度呈现模式。您只需将以下代码添加到您的演示模式中

 override func updateViewConstraints() {
        self.view.frame.size.height = UIScreen.main.bounds.height - 150
        self.view.frame.origin.y =  150
        self.view.roundCorners(corners: [.topLeft, .topRight], radius: 10.0)
        super.updateViewConstraints()
 }

 extension UIView {
   func roundCorners(corners: UIRectCorner, radius: CGFloat) {
        let path = UIBezierPath(roundedRect: bounds, byRoundingCorners: corners, cornerRadii: CGSize(width: radius, height: radius))
        let mask = CAShapeLayer()
        mask.path = path.cgPath
        layer.mask = mask
    }
 }
Run Code Online (Sandbox Code Playgroud)


Nik*_*der 7

用 Swift 回答

我一直在寻找一种方法来复制这种类型的 ViewController 行为,尽管使用的是基本的 UI,并且已经找到了一个相当简单的解决方案。基本上,您创建一个CardViewContoller具有透明背景的 ViewController ( ),然后向其中添加一个带有 的卡片式视图UIPanGestureReconizer,这将使您能够拖动它并使用 ViewController 关闭它。

要呈现您只需调用present,设置modalPresentationStyleto.overCurrentContextmodalTransitionStyleto .coverVertical

let cardVC = CardViewController()
cardVC.modalPresentationStyle = .overCurrentContext
cardVC.modalTransitionStyle = .coverVertical
present(cardVC, animated: true, completion: nil)
Run Code Online (Sandbox Code Playgroud)

CardViewController可以以编程方式或使用 Interface Builder 创建的 in ,您可以将 a 添加UIPanGestureRecognizer到您的卡片视图 ( contentView):

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

Run Code Online (Sandbox Code Playgroud)

然后只需添加一个@objc响应 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
        }
    }
Run Code Online (Sandbox Code Playgroud)

swipeThreshold是一个CGFloat具有您选择的值的变量(200 对我来说非常有用),如果UIPanGestureRecognizery 平移超过,将触发 ViewController 以及所有元素的解除。同样,您可以添加一个简单的按钮,该按钮将在.touchUpInside调用时关闭 ViewControllerdismiss()

如果你愿意,你可以看看这个 repo,其中我有一个展示这种行为的示例项目。这样您就可以构建自己的完全可定制的卡片。