UIPresentationController preferredContentSize 更新动画

Posted

技术标签:

【中文标题】UIPresentationController preferredContentSize 更新动画【英文标题】:UIPresentationController preferredContentSize update animated 【发布时间】:2015-11-27 16:00:20 【问题描述】:

所以我有一个非常基本的 UIPresentationController,它基本上以屏幕为中心显示 contentView,它的大小由视图控制器 PreferredContentSize 决定。 (它非常类似于以 FormSheet 形式呈现的常规模式视图控制器)。

我想要实现的是能够动态更新此视图控制器视图的大小,只需更改它的preferredContentSize。

当我设置preferredContentSize 时,我的UIPresentationController 子类会在以下位置接收有关它的信息:

-(void)preferredContentSizeDidChangeForChildContentContainer:(id<UIContentContainer>)container

但是我怎样才能从这里用动画调整视图框架的大小?如果我只是打电话:

-(void)preferredContentSizeDidChangeForChildContentContainer:(id<UIContentContainer>)container

    [UIView animateWithDuration:1.0 animations:^
        self.presentedView.frame = [self frameOfPresentedViewInContainerView];
     completion:nil]; 

立即被调用 containerViewWillLayoutSubviews 并且框架在没有动画的情况下被改变。

-(void)containerViewWillLayoutSubviews

    self.presentedView.frame = [self frameOfPresentedViewInContainerView];

请帮我找到一种方法,用动画调整它的大小。这一定是可能的,因为它会通过动画调整大小,例如在发生旋转时。

【问题讨论】:

您是否在不使用containerViewWillLayoutSubviews 中的一些奇怪的isAnimating 标志的情况下解决此问题? 【参考方案1】:

您必须使用自动布局。从您的容器高度限制中创建一个出口:

@property (nonatomic, strong, readwrite) IBOutlet NSLayoutConstraint *drawerViewHeightConstraint;

然后添加以下代码:

- (void)preferredContentSizeDidChangeForChildContentContainer:(id<UIContentContainer>)container

    [super preferredContentSizeDidChangeForChildContentContainer:container];
    self.drawerViewHeightConstraint.constant = container.preferredContentSize.height;

    [UIView animateWithDuration:0.25
                     animations:^
                       [self.view layoutIfNeeded];
                     ];

【讨论】:

虽然这可能行得通,但没有必要像您暗示的那样使用自动布局。【参考方案2】:

您只需在容器视图上调用setNeedsLayoutlayoutIfNeeded,而不是从preferredContentSizeDidChangeForChildContentContainer 中设置框架。 这会导致调用containerViewWillLayoutSubviews,这将使用您的动画配置更新帧。

目标-C:

- (void)preferredContentSizeDidChangeForChildContentContainer:(id<UIContentContainer>)container

    [UIView animateWithDuration:1.0 animations:^
        [self.containerView setNeedsLayout];
        [self.containerView layoutIfNeeded];
     completion:nil]; 

斯威夫特:

override func preferredContentSizeDidChange(forChildContentContainer container: UIContentContainer) 
    super.preferredContentSizeDidChange(forChildContentContainer: container)
    
    guard let containerView = containerView else 
        return
    
    
    UIView.animate(withDuration: 1.0, animations: 
        containerView.setNeedsLayout()
        containerView.layoutIfNeeded()
    )

替代方法

或者,您不能在 preferredContentSizeDidChange... 中使用动画块,而是将 preferredContentSize 的分配放在动画块中。

这样您可以更好地控制各个过渡的动画速度。

目标-C:

- (void)preferredContentSizeDidChangeForChildContentContainer:(id<UIContentContainer>)container

    [self.containerView setNeedsLayout];
    [self.containerView layoutIfNeeded];


// In view controller:

[UIView animateWithDuration:0.25 animations:^
    self.preferredContentSize = CGSizeMake(self.view.bounds.width, 500.f);
];

斯威夫特:

override func preferredContentSizeDidChange(forChildContentContainer container: UIContentContainer) 
    super.preferredContentSizeDidChange(forChildContentContainer: container)
    
    guard let containerView = containerView else 
        return
    
    
    containerView.setNeedsLayout()
    containerView.layoutIfNeeded()


// In view controller

UIView.animate(withDuration: 0.25) 
    self.preferredContentSize = CGSize(width: self.view.width, height: 500)

【讨论】:

“在视图控制器中”这表示哪个范围? 你展示的视图控制器。例如,例如;当有人在其中滚动时更新呈现的视图控制器的高度。 什么是containerView?收到错误Cannot find 'containerView' in scope

以上是关于UIPresentationController preferredContentSize 更新动画的主要内容,如果未能解决你的问题,请参考以下文章

UIPresentationController 在巨大延迟后呈现

UIPresentationController 传递触摸事件

拖动以关闭 UIPresentationController

iOS 上的自定义 UIPresentationController

在两个不同的 UIPresentationController 之间进行适配

基于视图大小的自适应 UIPresentationController