从错误的位置查看动画

时间:2019-02-16 19:01:37

标签: swift uiview uiviewanimation

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

我的将封面视图向上滑动到屏幕上并进入视图的代码运行正常。但是,将封面视图向下滑动到屏幕之外的代码不起作用!盖子滑落的起始位置似乎不正确。封面会按预期的方式向下滑动,但开始时的位置过高,导致动画在应开始的位置结束。

我已经在屏幕上记录了操作中的错误(显然放慢了动画的速度,因此您可以看到错误的含义)。向下滑动的盖板应从其向上滑动的原始位置向下滑动。 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,那么它可以工作。原来我的原始代码也可以用,但是只有在我有一个预编程的按钮可以触发显示/隐藏功能的情况下,才能再次使用。

但是,我需要使用按钮来触发该功能,在该位置以编程方式重新配置按钮的功能。我是通过.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的运行方式的问题。

您知道为什么会这样吗?无论何时有两个addTarget,或者只有一个目标,但startTeamB()中包含hideScoresCover()时,continueButton目标都会不正确地触发。

我为为什么会如此而感到困惑。 startTeamB()根本不是一个复杂的函数,因此不应干扰hideScoresCover()。因此,这只能使我得出结论,当它既是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.")
}

2 个答案:

答案 0 :(得分: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.")
    }
}
}

编辑

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

例如,如果要从显示/隐藏切换到 teamB,请 删除 显示/隐藏并添加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)

答案 1 :(得分: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`