UIView 子视图不平滑动画

Posted

技术标签:

【中文标题】UIView 子视图不平滑动画【英文标题】:UIView Subviews Do Not Smoothly Animate 【发布时间】:2014-09-18 19:49:44 【问题描述】:

我正在尝试为标签栏设置动画,使其从屏幕底部下方移动到顶部,同时调整视图的高度以缩小标签栏的高度。本质上,我有一个“隐藏”的标签栏,当它取消隐藏时应该会在视图中显示动画,并且 displayView 应该根据标签栏现在占用的空间进行调整。

但是,动画对于显示视图来说是跳跃的。似乎显示视图的动画效果很好,但子视图会自动调整它们的高度而没有任何动画。任何解决此问题的方向都将不胜感激。

我会接受 Objective-c 或 swift 的帮助,因为翻译相当容易。

 //Displays tab bar with slide up animation. If animated is false, all other params are unused
        func displayTabBar(animated:Bool, duration:NSTimeInterval = 0.5, delay:NSTimeInterval = 0, options:UIViewAnimationOptions = UIViewAnimationOptions.CurveLinear, completion:((Bool) -> Void)? = nil)
            if(animated)
                UIView.animateWithDuration(duration, delay: delay, options: options, animations: 
                        self.adjustTabBarDisplayed()
                    , completion: completion)
                UIView.animateWithDuration(duration, delay: delay, options: options, animations: 
                        self.adjustDisplayViewTabDisplayed()
                    , completion: nil)
            
            else
                self.adjustTabBarDisplayed()
                self.adjustDisplayViewTabDisplayed()
            

        

        //Adjusts frame of tab bar to display tab bar
        private func adjustTabBarDisplayed()
            self.tabBar.frame = CGRectMake(0,UIScreen.mainScreen().bounds.height - self.tabBar.bounds.height, self.tabBar.bounds.width, self.tabBar.bounds.height)
        

        //Adjusts frame of display view to match displayed tab bar
        private func adjustDisplayViewTabDisplayed()
            self.displayView.frame = CGRectMake(0,0,self.displayView.bounds.width, UIScreen.mainScreen().bounds.height - self.tabBar.bounds.height)
        

【问题讨论】:

【参考方案1】:

当您修改视图的大小时,它不会立即布置其子视图。相反,它设置一个标志,表明它需要布局。稍后,在系统完成调度最终调用displayTabBar 的事件后,它运行显示刷新代码。显示刷新代码会找到设置了 needs-layout 标志的视图,并告诉它们进行布局(通过发送layoutSubviews)。

在这里,您正在动画块内更改显示视图的大小。因此,对显示视图框架的更改将被动画化。但其子视图的帧在动画块外部发生变化;它们在布局阶段稍后会发生变化。您需要让它们在内部动画块中进行更改。

你很幸运,这很容易。只需在动画块内调用self.displayView.layoutIfNeeded()。此外,您只需要一个动画块,因为所有动画参数都是相同的:

func displayTabBar(animated:Bool, duration:NSTimeInterval = 0.5, delay:NSTimeInterval = 0, options:UIViewAnimationOptions = UIViewAnimationOptions.CurveLinear, completion:((Bool) -> Void)? = nil)
    if(animated)
        UIView.animateWithDuration(duration, delay: delay, options: options, animations: 
                self.adjustTabBarDisplayed()
                self.adjustDisplayViewTabDisplayed()

                // ADD THIS LINE
                self.displayView.layoutIfNeeded()
            , completion: completion)
    
    else
        self.adjustTabBarDisplayed()
        self.adjustDisplayViewTabDisplayed()
    

【讨论】:

【参考方案2】:

在动画块中使用下面的代码行

scrollView.layoutIfNeeded()

【讨论】:

以上是关于UIView 子视图不平滑动画的主要内容,如果未能解决你的问题,请参考以下文章

旋转后重新初始化 UIView 视图和子视图

更新 UIView 会产生子视图对齐/Swift 的散列

gganimate 不平滑动画

在 UIView 子类的子视图内绘图

iPhone UIView:是不是可以仅在子视图上启用用户交互?

如何在 iOS 中滑动 UIViewController 中包含的子视图控制器?