为某些元素设置动画时遇到问题 UIView 将排除其他元素

Posted

技术标签:

【中文标题】为某些元素设置动画时遇到问题 UIView 将排除其他元素【英文标题】:Having an issue animating certain elements UIView will excluding others 【发布时间】:2014-07-23 23:45:38 【问题描述】:

在我的代码中,当键盘弹出时,我已正确地将 UITextfield 移动到视图中。但是,我一直在努力创建另一个仅作用于 UIImageView 的动画,因为当前的解决方案会永久偏移 UIImageView 中的徽标。

var logoImage:UIImageView!
var logoImageX:CGFloat = 85
var logoImageY:CGFloat = 35

// Logo Code

let logo:UIImage = UIImage(named:"color-logo.png")
let logoHeight:CGFloat = 150
let logoWidth:CGFloat = logoHeight

logoImage = UIImageView(image:Logo)
logoImage.frame = CGRectMake(logoImageX,logoImageY,logoWidth, logoHeight)
self.view.insertSubview(logoImage, atIndex: 1)

// Keyboard Auto Scroll

func textFieldDidBeginEditing(textField: UITextField!) 
    self.animateTextField(textField, up: true)
    self.animateWithDuration(true)


func textFieldDidEndEditing(textField: UITextField!) 
    self.animateTextField(textField, up: false)
    self.animateWithDuration(false)


func animateTextField(textField:UITextField,up: Bool)

    let movementDistance:Int = -100
    let movementDuration:NSTimeInterval = 0.25
    var movement = CGFloat(Int((up ? movementDistance : -movementDistance)))

    UIView.beginAnimations("animateTextField", context:nil)
    UIView.setAnimationBeginsFromCurrentState(true)
    UIView.setAnimationDuration(movementDuration)
    self.view.frame = CGRectOffset(self.view.frame, 0, movement)
    UIView.commitAnimations()


这是 UIImageView 的函数:

//Logo (UIImageView) Scroll
func animateWithDuration(up:Bool)
    let logoMovementDuration = 0.25
    let logoMovementDistance:Int = 20
    var logoMovement = CGFloat(Int((up ? logoMovementDistance : -logoMovementDistance + (logoImageY))))
    UIView.beginAnimations("animateWithDuration", context:nil)
    UIView.setAnimationDuration(logoMovementDuration)
    logoImage.frame = CGRectMake(logoImageX,logoMovement,logoImage.frame.size.width,logoImage.frame.size.height)
    UIView.commitAnimations()

【问题讨论】:

你为什么不使用基于块的动画?自 ios 4 以来,Apple 一直建议不要使用 beginAnimations/commitAnimations 方法。 我从 iOS 7 开始才开始开发,我还没有注意到 beginAnimations/commitAnimations 方法的推动。你认为基于块的动画是解决我当前难题的关键吗? 你是对的,通过文档我发现 Apple 确实推荐 iOS 4.0 及更低版本的 beginAnimation/commitAnimation 以及所有 iOS 版本的动画块。我找到了答案并进行了更新。 【参考方案1】:

我通过创建多个 UIView 找到了解决方案,或者在我的案例 3 中。

代码如下所示,具体取决于您想要实现的目标,分为不同的组,以便将动画应用于每个组(这些在 viewDidLoad() 之外声明以使它们可公开访问):

var otherView = UIView(frame: UIScreen.mainScreen().bounds)
var logoImageView = UIView(frame:CGRect(x: 0, y: 0, width: xx, height: xx)) 
var resultView = UIView(frame:CGRect(x: 0, y: 0, width: xx, height: xx))

之后,我将子视图添加到 UIView 实例中,最后添加到超级视图中(在 viewDidLoad() 中声明):

self.logoImageView.insertSubview(logoImage, atIndex:1)
self.view.insertSubview(logoImageView, atIndex: 1)

然后最终应用了相同的 func,现在使用 rdelmar 建议的基于块的动画,并从 iOS 4.0 开始由 Apple 推荐(在 viewDidLoad() 之外和之后):

// 键盘自动滚动

func textFieldDidBeginEditing(textField: UITextField!) 
    self.animateTextField(textField, up: true)


func textFieldDidEndEditing(textField: UITextField!) 
    self.animateTextField(textField, up: false)


func animateTextField(textField:UITextField,up: Bool)

    let resultMovementDistance:Int = -xx
    let movementDistance:Int = -xx
    let movementDuration:NSTimeInterval = 0.xx
    var resultMovement = CGFloat(Int((up ? resultMovementDistance : -resultMovementDistance)))
    var otherMovement = CGFloat(Int((up ? movementDistance : -movementDistance)))
    var logoMovement = otherMovement/5
    UIView.animateWithDuration(
        movementDuration,
        delay: 0,
        options: UIViewAnimationOptions.CurveEaseIn, animations:
        self.otherView.frame = CGRectOffset(self.otherView.frame,0,otherMovement),
        completion:nil)
    UIView.animateWithDuration(
        movementDuration,
        delay: 0,
        options: UIViewAnimationOptions.CurveEaseIn, animations:
            self.logoImageView.frame = CGRectOffset(self.logoImageView.frame,0,logoMovement),
        completion:nil)
    UIView.animateWithDuration(
        movementDuration,
        delay: 0,
        options: UIViewAnimationOptions.CurveEaseIn, animations:
            self.resultView.frame = CGRectOffset(self.resultView.frame,0,resultMovement),
        completion:nil)

注意:我确实很难将动画嵌套在块中,但我很高兴它成功了。我希望这有帮助。

【讨论】:

以上是关于为某些元素设置动画时遇到问题 UIView 将排除其他元素的主要内容,如果未能解决你的问题,请参考以下文章

在 2 个 UIViewController 的过渡之间为 UIView 元素设置动画

为 navController 设置动画时保留 UIView

使用 CoreAnimation 一次为多个 UIView 设置动画

UIView 不重绘,但元素错位

快速使用自动布局时为 UIView 高度设置动画

MonoTouch - UIView.Animate 完成回调未在按钮 touchUpInside 委托内调用