从错误的位置查看动画

问题描述 投票:0回答:2

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

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

我有一个错误的屏幕录制(显然减慢了动画速度,所以你可以看到错误的意思)。向下滑动的盖子应该从其向上滑动的原始位置向下滑动。 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.")
        })
}

EDIT

嘿@Nickolans感谢你对这个问题的帮助。所以...我对此查询有一个奇怪的更新。我实现了你的代码,如果我有一个预先编程的按钮来激活showScoreCover和hideScoresCover,它就可以工作。事实证明,即使我的原始代码有效,但是,只有当我有一个预先编程的按钮来激活显示/隐藏功能时。

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

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

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

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

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

我很难过为什么会这样。 startTeamB()根本不是一个复杂的函数,因此不应该干扰hideScoresCover()。所以这导致我得出的结论是,当startButton除了将startTeamB作为目标之外还有一个单独的目标,或者当startTeamB本身包含hideScoresCover()时,它必须是continueButton触发hideScoresCover()的方式。当唯一的.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.")
}
swift uiview uiviewanimation
2个回答
0
投票

我将它带入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,请删除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)

0
投票

我只想说一件事,也许这里不需要+=

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`
© www.soinside.com 2019 - 2024. All rights reserved.