从错误的位置查看动画

View animating from the incorrect position

我正在尝试在我的代码中为封面视图设置动画。本质上,封面从屏幕外向上滑动(关闭)到屏幕上,在用户按下按钮后,封面向下滑动(打开)一直到屏幕外。

我将封面视图向上滑动到屏幕并进入视图的代码运行良好。但是,将封面视图向下滑动到屏幕之外的代码不起作用!盖子向下滑动的起始位置似乎是不正确的。封面按预期向下滑动,但起点太高,以至于动画在它应该开始的地方结束。

我有错误操作的屏幕录像(显然放慢了动画速度,所以你可以明白我所说的错误是什么意思)。向下滑动的盖子应该是从它向上滑动到的原始位置向下滑动。 Link to recording.

谁能发现我的代码哪里出错了?

func showScoresCover() {
    verticalDistance = ScoresCoverView.frame.size.height
    self.ScoresCoverView.frame.origin.y += verticalDistance
    UIView.animate(
        withDuration: 0.5,
        delay: 0.25,
        options: .curveEaseOut,
        animations:
        { self.ScoresCoverView.frame.origin.y -= self.verticalDistance},
        completion:
        { finished in
          print("Score cover closed.")
        })
}

func hideScoresCover() {
    verticalDistance = ScoresCoverView.frame.size.height
    UIView.animate(
        withDuration: 0.5,
        delay: 0.25,
        options: .curveEaseIn,
        animations:
        { self.ScoresCoverView.frame.origin.y += self.verticalDistance},
        completion:
        { finished in
          print("Score cover opened.")
        })
}

编辑

嘿@Nickolans 感谢您在此问题上的帮助。所以...关于这个查询,我有一个奇怪的更新要告诉你。我实现了您的代码,如果我有一个触发 showScoreCover 和 hideScoresCover 的预编程按钮,它就可以工作。事实证明,即使我的原始代码也能工作,但同样,只有当我有一个预编程的按钮可以触发 show/hide 功能时。

但是,我需要使用一个按钮来触发该功能,我在其中以编程方式重新配置按钮的功能。我是如何通过 .addTarget 和一些选择器实现这一点的,这些选择器会根据用户在游戏中的位置而有所不同。

无论如何,这就是我的代码:

self.continueButton.addTarget(self, action: #selector(self.hideScoresCover), for: UIControlEvents.touchUpInside)
self.continueButton.addTarget(self, action: #selector(self.startTeamB), for: UIControlEvents.touchUpInside)

最初我只使用了一个.addTarget 并将hideScoresCover() 包含在startTeamB 函数中。这导致了最初的问题,即封面没有正确隐藏(屏幕上的起点太高)。所以我把它分成上面两个 .addTargets,这也会导致同样的问题。但是,如果我注释掉上面与 startTeamB 选择器相关的整个 .addTarget 行并保留与 hideScoresCover 相关的选择器,那么封面就会显示并完全隐藏,就像我想要的那样,动画是完美的。这意味着 hideScoresCover() 中的底层代码工作正常,但问题是在按下继续按钮时 hideScoresCover 如何 运行 以某种方式出现。

你知道为什么会这样吗?不知何故,只要有两个 addTargets,或者当只有一个目标但 hideScoresCover() 包含在 startTeamB() 中时,continueButton 目标就会错误触发。

我很困惑为什么会这样。 startTeamB() 根本不是一个复杂的函数,因此不应干扰 hideScoresCover()。因此,这让我只能得出结论,它必须是 continueButton 触发 hideScoresCover() 的方式,当它是一个单独的目标而不是 startTeamB 作为目标时,或者当 hideScoresCover() 包含在 startTeamB 本身中时。当唯一的 .addTarget 是一个调用 hidesScoresCover?

的选择器时,它确实正常工作是不寻常的
@objc func startTeamB() {
    self.UpdateTeam() //Just changes the team name
    self.TeamBTimer() //Starts a timer to countdown teamB's remaining time
    self.TeamAIndicator.isHidden = true //Just hides teamA image
    self.TeamBIndicator.isHidden = false //Just shows teamB image
    print("Hintify: ","-----Start Team B.")
}

我把它带进了Xcode,自己设置了。我认为问题可能在于您如何更改 Y 值,而不是更改原点更改视图层的 y 位置。

下面的代码有效,所以你可以接受它!确保在您第一次开始时将框架更改为您需要的任何内容。

class ViewController: UIViewController {

//Bool to keep track if view is open
var isOpen = false

var verticalDistance: CGFloat = 0
var ScoresCoverView = UIView()
var button = UIButton()

override func viewDidLoad() {

    //Setup Score view
    ScoresCoverView.frame = CGRect(x: 0, y: 0, width: view.frame.width, height: view.frame.width)
    ScoresCoverView.backgroundColor = .blue
    view.addSubview(ScoresCoverView)

    //Set vertical distance
    verticalDistance = ScoresCoverView.frame.height

    //TEST button to test view animations
    button.frame = CGRect(x: 200, y: 500, width: 100, height: 100)
    button.backgroundColor = .purple
    button.addTarget(self, action: #selector(hasBeenFired), for: .touchUpInside)
    self.view.addSubview(button)
}

//When button pressed
@objc func hasBeenFired() {
    if isOpen {
        self.hideScoresCover()
        self.isOpen = false
    } else {
        self.showScoresCover()
        self.isOpen = true
    }
}

//Show
func showScoresCover() {

    self.ScoresCoverView.isHidden = false

    UIView.animate(withDuration: 0.5, delay: 0.25, options: .curveEaseOut, animations: {
        self.ScoresCoverView.layer.position.y -= self.verticalDistance
    }) { (finished) in
        print("Score cover closed.")
    }
}

//Hide
func hideScoresCover() {

    UIView.animate(withDuration: 0.5, delay: 0.25, options: .curveEaseIn, animations: {
        self.ScoresCoverView.layer.position.y += self.verticalDistance
    }) { (finished) in
        self.ScoresCoverView.isHidden = true
        print("Score cover Opened.")
    }
}
}

编辑

如果您想更改按钮的功能,请确保在添加新目标之前删除之前的目标。

例如,如果你想从show/hide 切换到 teamB remove show/hide 并添加 teamB-- 反之亦然。

当您第一次开始时,添加您的初始目标:

self.continueButton.addTarget(self, action: #selector(self.hideScoresCover), for: UIControlEvents.touchUpInside)

切换到 startTeamB:

self.continueButton.removeTarget(self, action: #selector(self.hideScoresCover), for: UIControlEvents.touchUpInside)
self.continueButton.addTarget(self, action: #selector(self.startTeamB), for: UIControlEvents.touchUpInside)

切换到 hideScoreCover:

self.continueButton.removeTarget(self, action: #selector(self.startTeamB), for: UIControlEvents.touchUpInside)
self.continueButton.addTarget(self, action: #selector(self.hideScoresCover), for: UIControlEvents.touchUpInside)

我只想说一件事,也许+=在这里没有必要

func showScoresCover() {
verticalDistance = ScoresCoverView.frame.size.height
self.ScoresCoverView.frame.origin.y += verticalDistance
UIView.animate(
    withDuration: 0.5,
    delay: 0.25,
    options: .curveEaseOut,
    animations:
    { self.ScoresCoverView.frame.origin.y -= self.verticalDistance},
    completion:
    { finished in
      print("Score cover closed.")
    })
}

应该是

   `self.ScoresCoverView.frame.origin.y = verticalDistance`