带有交互式呈现视图的UipresentationController

发布于 2025-01-22 04:14:27 字数 1181 浏览 1 评论 0原文

我查看了这个问题,但没有帮助:与呈现视图进行交互uiperSentationController


我正在尝试实现一个表演控制器,类似于iOS 15的UisheetPresentationController,除了我还需要在iOS 14上运行它。而且我也想做到这一点,以便它具有一个小的定位,类似于在地图应用程序中的操作方式。

因此,我有一个自定义的UipresentationController类,但我还没有太多,但是到目前为止,

- (CGRect)frameOfPresentedViewInContainerView {
    [super frameOfPresentedViewInContainerView];
    CGRect presentedViewFrame = CGRectZero;
    CGRect containerBounds = self.containerView.bounds;
    presentedViewFrame.size = CGSizeMake(containerBounds.size.width, floor(containerBounds.size.height * 0.5));
    presentedViewFrame.origin = CGPointMake(0, containerBounds.size.height - presentedViewFrame.size.height);
    return presentedViewFrame;
}

- (BOOL)shouldPresentInFullscreen {
    return NO;
}

- (BOOL)shouldRemovePresentersView {
    return NO;
}

这确实有效。它确实在显示视图控制器高度的一半处显示了视图控制器。问题在于,呈现视图不再是交互式,因为显然有一个视图会添加出来。

因此,我的问题是如何使呈现视图具有互动性,可以在哪里滚动并与按钮和其他控件进行交互?我希望能够使用演示控制器来介绍视图控制器。

I looked at this question, but it does not help: Interacting with presenting view and UIPresentationController


I am trying to implement a sheet presentation controller, similar to the UISheetPresentationController for iOS 15, except I need it to run on iOS 14 as well. And I am also wanting to make it so that it has a small detent, similar to how it is done in the Maps app.

So I have a custom UIPresentationController class and I don't have much in it yet, but is what I have so far:

- (CGRect)frameOfPresentedViewInContainerView {
    [super frameOfPresentedViewInContainerView];
    CGRect presentedViewFrame = CGRectZero;
    CGRect containerBounds = self.containerView.bounds;
    presentedViewFrame.size = CGSizeMake(containerBounds.size.width, floor(containerBounds.size.height * 0.5));
    presentedViewFrame.origin = CGPointMake(0, containerBounds.size.height - presentedViewFrame.size.height);
    return presentedViewFrame;
}

- (BOOL)shouldPresentInFullscreen {
    return NO;
}

- (BOOL)shouldRemovePresentersView {
    return NO;
}

And this does work. It does display the view controller at half of the height of the presenting view controller. The problem is that the presenting view is no longer interactive because there is a view that gets added by the presentation controller class apparently.

So my question is how do I get the presenting view to be interactive, where I can scroll it and interact with buttons and the other controls? I want to be able to use a presentation controller to present the view controller.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

放我走吧 2025-01-29 04:14:27

以下内容允许您提供一个较短的模态视图控制器,同时仍允许与呈现视图控制器进行交互。这不会尝试使用较新的uisheetPresentationController来实现您获得的收益。这仅解决了能够与两个视图控制器进行交互的问题,而第二个控制器则为较短。

这种方法利用自定义uiperSentationController。这避免了需要处理自定义容器视图并为显示视图的显示动画。

从以下自定义uiperSentationController类开始:

import UIKit

class ShortPresentationController: UIPresentationController {
    override var shouldPresentInFullscreen: Bool {
        // We don't want full screen
        return false
    }

    override var frameOfPresentedViewInContainerView: CGRect {
        let size = containerView?.frame.size ?? presentingViewController.view.frame.size

        // Since the containerView's frame has been resized already, we just need to return a frame of the same
        // size with a 0,0 origin.
        return CGRect(origin: .zero, size: size)
    }

    override func presentationTransitionWillBegin() {
        super.presentationTransitionWillBegin()

        guard let containerView = containerView else { return }

        // By default the containerView's frame covers the screen which prevents interacting with the presenting view controller.
        // Update the containerView's frame to match the area needed by the presented view controller. This allows
        // interection with the presenting view controller even while the presented view controller is in view.
        //
        // This code assumes we want the presented view controller to use the full width of the presenting view controller
        // while honoring the preferredContentSize height. It also assumes we want the bottom of the presented view
        // controller to appear at the bottom of the presenting view controller. Adjust as needed.
        let containerSize = containerView.bounds.size
        let preferredSize = presentedViewController.preferredContentSize
        containerView.frame = CGRect(x: 0, y: containerSize.height - preferredSize.height,
                                     width: containerSize.width, height: preferredSize.height)
    }
}

在“呈现视图控制器”中,您需要创建并呈现简短的视图控制器。这是提供模态视图控制器的相当典型的代码,其将样式设置为custom并分配了transitioningdelegate的重要区别。

FirstViewController.swift:

let vc = SecondViewController()
let nc = UINavigationController(rootViewController: vc)
nc.modalPresentationStyle = .custom
nc.transitioningDelegate = self
present(nc, animated: true)

您需要在FirstViewController中实现一种过渡代表的方法来返回自定义演示文稿控制器:

extension FirstViewController: UIViewControllerTransitioningDelegate {
    func presentationController(forPresented presented: UIViewController, presenting: UIViewController?, source: UIViewController) -> UIPresentationController? {
        return ShortPresentationController(presentedViewController: presented, presenting: presenting)
    }
}

最后,确保您设置第二视图控制器的preferredContentsize属性。一个典型的位置是viewDidload secondViewController:

preferredContentSize = CGSize(width: 320, height: 300)

不包括导航控制器栏(如果有)。如果您希望显示视图控制器设置最终大小,包括栏,则可以在preferredcontentsize on nc> nc上设置它。这取决于您想指示首选尺寸的人。

The following allows you to present a shorter modal view controller while still allowing interaction with the presenting view controller. This doesn't attempt to implement what you get with the newer UISheetPresentationController. This only solves the issue of being able to interact with both view controllers while the shorter second controller is in view.

This approach makes use of a custom UIPresentationController. This avoids the need to deal with custom container views and animating the display of the presented view.

Start with the following custom UIPresentationController class:

import UIKit

class ShortPresentationController: UIPresentationController {
    override var shouldPresentInFullscreen: Bool {
        // We don't want full screen
        return false
    }

    override var frameOfPresentedViewInContainerView: CGRect {
        let size = containerView?.frame.size ?? presentingViewController.view.frame.size

        // Since the containerView's frame has been resized already, we just need to return a frame of the same
        // size with a 0,0 origin.
        return CGRect(origin: .zero, size: size)
    }

    override func presentationTransitionWillBegin() {
        super.presentationTransitionWillBegin()

        guard let containerView = containerView else { return }

        // By default the containerView's frame covers the screen which prevents interacting with the presenting view controller.
        // Update the containerView's frame to match the area needed by the presented view controller. This allows
        // interection with the presenting view controller even while the presented view controller is in view.
        //
        // This code assumes we want the presented view controller to use the full width of the presenting view controller
        // while honoring the preferredContentSize height. It also assumes we want the bottom of the presented view
        // controller to appear at the bottom of the presenting view controller. Adjust as needed.
        let containerSize = containerView.bounds.size
        let preferredSize = presentedViewController.preferredContentSize
        containerView.frame = CGRect(x: 0, y: containerSize.height - preferredSize.height,
                                     width: containerSize.width, height: preferredSize.height)
    }
}

In the presenting view controller you need to create and present the short view controller. This is fairly typical code for presenting a modal view controller with the important differences of setting the style to custom and assigning the transitioningDelegate.

FirstViewController.swift:

let vc = SecondViewController()
let nc = UINavigationController(rootViewController: vc)
nc.modalPresentationStyle = .custom
nc.transitioningDelegate = self
present(nc, animated: true)

You need to implement one method of the transition delegate in FirstViewController to return the custom presentation controller:

extension FirstViewController: UIViewControllerTransitioningDelegate {
    func presentationController(forPresented presented: UIViewController, presenting: UIViewController?, source: UIViewController) -> UIPresentationController? {
        return ShortPresentationController(presentedViewController: presented, presenting: presenting)
    }
}

And lastly, make sure you set the preferredContentSize property of the second view controller. One typical place is in the viewDidLoad of SecondViewController:

preferredContentSize = CGSize(width: 320, height: 300)

That does not include the navigation controller bars (if any). If you want the presenting view controller to set the final size, including the bars, you could set the preferredContentSize on nc just before presenting it. It depends on who you want to dictate the preferred size.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文