UIView.animateWithDuration不动画Swift(再次)

时间:2016-04-05 20:37:23

标签: ios swift animation uiviewanimation uiviewanimationtransition

注意:我已经检查了以下堆栈溢出问题:

27907570322292522611814131604300

我想要做的就是在附加到按钮的IBAction调用时在视图中淡化动画(通过alpha)。然后在视图上的按钮被击中时反转。

我的皱纹可能是我在故事板视图中使用ViewDock上的辅助视图。视图在viewDidLoad时被添加到子视图中,其中框架/边界设置为与超视图相同(用于完全中转)

这是作为叠加视图完成的原因,因为它是一个教程指示器。

结果(就像许多其他列出此问题的人一样)是视图(和包含的控件)只是立即出现并立即消失。没有褪色。

我已尝试使用延迟,带有和不带完成,带有转换的animationWithDuration,甚至以旧的UIView.beginAnimations开始。

什么都没有用。建议热烈欢迎。

代码与我能做到的一样直截了当:
修改:将代码扩展到相关的所有内容 Edit2: TL; DR Everything适用于UIViewAnimateWithDuration,它似乎忽略了块和持续时间,只是作为即时UI更改内联运行代码。 解决此问题获得赏金

@IBOutlet var infoDetailView: UIView! // Connected to the view in the SceneDock

override func viewDidLoad() {
    super.viewDidLoad()

    // Cut other vDL code that isn't relevant

    setupInfoView()
}

func setupInfoView() {
    infoDetailView.alpha = 0.0
    view.addSubview(infoDetailView)
    updateInfoViewRect(infoDetailView.superview!.bounds.size)
}

func updateInfoViewRect(size:CGSize) {
    let viewRect = CGRect(origin: CGPointZero, size: size)

    infoDetailView.frame = viewRect
    infoDetailView.bounds = viewRect

    infoDetailView.layoutIfNeeded()
    infoDetailView.setNeedsDisplay()
}

override func viewWillTransitionToSize(size: CGSize, withTransitionCoordinator coordinator: UIViewControllerTransitionCoordinator) {
    super.viewWillTransitionToSize(size, withTransitionCoordinator: coordinator)
    updateInfoViewRect(size)
}

func hideInfoView() {
    AFLog.enter(thisClass)
    UIView.animateWithDuration(
        2.0,
        animations:
        {
            self.infoDetailView.alpha = 0.0
        },
        completion:
        { (finished) in
            return true
        }
    )
    AFLog.exit(thisClass)
}

func showInfoView() {
    AFLog.enter(thisClass)
    UIView.animateWithDuration(
        2.0,
        animations:
        {
            self.infoDetailView.alpha = 0.75
        },
        completion:
        { (finished) in
            return true
        }
    )
    AFLog.exit(thisClass)
}

// MARK: - IBActions

@IBAction func openInfoView(sender: UIButton) {
    showInfoView()
}

@IBAction func closeInfoView(sender: UIButton) {
    hideInfoView()
}

请注意,我从以下开始:

func showInfoView() {
    UIView.animateWithDuration(2.0, animations: { () -> Void in
        self.infoDetailView.alpha = 0.75
    })
}

func hideInfoView() {
    UIView.animateWithDuration(2.0, animations: { () -> Void in
        self.infoDetailView.alpha = 0.00
    })
}

11 个答案:

答案 0 :(得分:38)

如果infoDetailView处于自动布局约束下,则需要在视图里面调用layoutIfNeeded animateWithDuration:

func showInfoView() {
    self.view.layoutIfNeeded() // call it also here to finish pending layout operations
    UIView.animateWithDuration(2.0, animations: { () -> Void in
        self.infoDetailView.alpha = 0.75
        self.view.layoutIfNeeded()
    })
}

理论上,如果您只是更改.alpha值,则不需要这样,但可能这可能是这种情况下的问题。

答案 1 :(得分:12)

我可以看到几件奇怪的事情,

首先,删除:

infoDetailView.layoutIfNeeded()
infoDetailView.setNeedsDisplay()

通常您不需要手动调用这些方法,除非您确切知道自己在做什么。

此外,当您更改尺寸时:

infoDetailView.frame = viewRect
infoDetailView.bounds = viewRect

您永远不需要同时设置boundsframe。只需设置frame

此外,您应该通过设置确保视图实际上不会忽略该帧:

infoDetailView.translatesAutoresizingMaskIntoConstraints = true

不要重置帧,只需设置自动调整大小掩码:

infoDetailView.autoresizingMask = [.FlexibleWidth, .FlexibleHeight]

导致:

override func viewDidLoad() {
    super.viewDidLoad()

    // Cut other vDL code that isn't relevant

    setupInfoView()
}

func setupInfoView() {
    infoDetailView.alpha = 0.0
    infoDetailView.translatesAutoresizingMaskIntoConstraints = true
    infoDetailView.autoresizingMask = [.FlexibleWidth, .FlexibleHeight]
    infoDetailView.frame = view.bounds
    view.addSubview(infoDetailView)
}

func hideInfoView() {
  ...
}

我认为这实际上应该有所帮助,因为即时动画通常与尺寸问题有关。

如果问题仍然存在,您应该检查动画中的infoDetailView是否与您要添加到控制器的infoDetailView相同。

答案 2 :(得分:4)

如果动画似乎没有执行,那么在进入动画块之前,请考虑检查每个视图的状态。例如,如果alpha已经设置为0.4,那么调整视图alpha的动画几乎会立即完成,没有明显效果。

请考虑使用关键帧动画。这就是目标c中的摇动动画的样子。

+(CAKeyframeAnimation*)shakeAnimation {
    CAKeyframeAnimation *animation = [CAKeyframeAnimation animationWithKeyPath:@"transform"];
    animation.values = @[[NSValue valueWithCATransform3D:CATransform3DMakeTranslation(-10.0, 0.0, 0.0)],
                         [NSValue valueWithCATransform3D:CATransform3DMakeTranslation(10.0, 0.0, 0.0)]];
    animation.autoreverses = YES;
    animation.repeatCount = 2;
    animation.duration = 0.07;
    return animation;
}

这是一篇帖子,向您展示如何使用关键帧https://stackoverflow.com/a/18658081/1951992

调整alpha

答案 3 :(得分:3)

确保infoDetailView' s opaque为假。

https://developer.apple.com/library/ios/documentation/UIKit/Reference/UIView_Class/#//apple_ref/occ/instp/UIView/opaque

  

此属性为绘图系统提供了如何处理视图的提示。如果设置为true,则绘图系统将视图视为完全不透明,这允许绘图系统优化某些绘图操作并提高性能。如果设置为false,则绘图系统会正常地将视图与其他内容合成。此属性的默认值为true。

答案 4 :(得分:1)

使用此代码:

UIView.animateWithDuration(0.3, animations: { () -> Void in
    self.infoDetailView.alpha = 0.0 
})

答案 5 :(得分:1)

我已经复制了您的代码并且运行良好,一切正常。 您可能必须控制约束,IBOutlet和IBActions连接。如果有必要,请尝试将此代码隔离到新项目中。

更新my code 和我的故事板和项目文件夹照片:

my storyboard and project folder photo

每个对象(视图和按钮)都使用默认设置。

enter image description here

我已经评论了所有AFLog专线(可能它只是#34;详细模式"来帮助你),其余的代码都没问题,它做了你所做的事情从中,如果按下打开按钮,视图会淡入,当您点按关闭按钮时,视图会淡出。

PS不相关,但我正在使用xCode 7.3,这是一个新的swift 2.2项目。

答案 6 :(得分:1)

尝试以下代码。只需使用alpha和持续时间来完善它。

隐藏功能

func hideInfoView() {
AFLog.enter(thisClass)
UIView.animateWithDuration(
    2.0,
    animations:
    {
        self.infoDetailView.alpha = 0.8
    },
    completion:
    { (finished) in
        UIView.animateWithDuration(
    2.0,
    animations:
    {
        self.infoDetailView.alpha = 0.4
    },
    completion:
    { (finished) in
        self.infoDetailView.alpha = 0.0
    }
)
    }
)
AFLog.exit(thisClass)
}

显示功能

func showInfoView() {
AFLog.enter(thisClass)
UIView.animateWithDuration(
    2.0,
    animations:
    {
        self.infoDetailView.alpha = 0.3
    },
    completion:
    { (finished) in
        UIView.animateWithDuration(
    2.0,
    animations:
    {
        self.infoDetailView.alpha = 0.7
    },
    completion:
    { (finished) in
        self.infoDetailView.alpha = 1.0
    }
)
    }
)
AFLog.exit(thisClass)
}

答案 7 :(得分:1)

对于其他希望在加载视图时立即开始播放动画的人...

如果您在UIView.animate(...)内调用viewDidLoad,则动画将不起作用。相反,必须从 viewDidAppear 函数中调用它。

override func viewDidAppear(_ animated: Bool) {
    UIView.animate(withDuration: 3) {
        self.otherView.frame.origin.x += 500
    }
}

答案 8 :(得分:0)

您是否尝试将showInfoView()更改为更像toggleInfoView的内容?

func toggleInfoView() {
    let alpha = CGFloat(infoDetailView.alpha == 0 ? 1 : 0)
    infoDetailView.alpha = alpha       //this is where the toggle happens
}

它表示如果您的视图的alpha为0,则将其更改为1.否则,将其设为0.

如果你需要在动画中发生这种情况,请尝试

@IBAction func openInfoView(sender: UIButton) {
    UIView.animate(withDuration: 2.0, animations: {
        self.toggleInfoView()           //fade in/out infoDetailView when animating
    })   
}
  • 您仍然希望将infoDetailView.alpha = 0.0保留在viewDidLoad的所有位置。

答案 9 :(得分:0)

对于UILabel组件,请尝试更改图层的背景颜色。

试试这个(在Swift 4上测试):

Banana

答案 10 :(得分:0)

由于无法执行动画而遇到类似的问题。

perform(aSelector: Selector, with: Any?, afterDelay: TimeInterval)的形式更改了使用perform(#selector(functionThatDoesAnimationOfAlphaValue), with: nil, afterDelay: 0)的函数调用,并且可以正常工作。即使将TimeInterval设置为0。

万一有人来这里寻求解决方案。

相关问题