【发布时间】:2021-03-16 21:36:05
【问题描述】:
我正在使用 UIView.transition 来翻转卡片。
在排除故障时无法正常工作,但我偶然发现了一种使其正常工作的方法 - 但我不知道为什么。我希望有人可以查看下面的两个代码块并帮助我理解为什么一个有效而另一个无效。我觉得这很奇怪。
首先,这里是实际工作的代码块。卡片翻转在视觉上完美无瑕。
UIView.animate(withDuration: 0.01) { imageView.alpha = 1.0 imageView.layoutIfNeeded() // Works with and without this layoutIfNeeded() } completion: { (true) in UIView.transition(with: imageView, duration: 1.2, options: animation) { imageView.image = endingImage imageView.layoutIfNeeded() // Works with and without this layoutIfNeeded() } completion: { (true) in if self.dealTicketState.isTicketFaceUp == true { self.faceDownView.alpha = 0.0 } else { self.faceDownView.alpha = 1.0 } UIView.animate(withDuration: 0.01) { self.coveringLabel.backgroundColor = .clear self.coveringLabel.layoutIfNeeded() imageView.removeFromSuperview() self.tickNumLabel.alpha = originalTicketNumAlpha } } }
但我不明白为什么我似乎需要将 UIView.transition() 包装到调用 UIView.animate() 的完成处理程序中才能使翻转动画工作。
*(注意:如果我将“imageView.alpha = 1.0”拉出 animate() 块并在调用 UIView.animate() 之前立即将其放置 - 翻转动画确实 not 发生(使用或没有 layoutIfNeeded() 调用)。它只是切换图像。*
现在,这是我期望工作的代码 - 但是当我使用此代码而不是上面的代码时,没有“翻转”过渡。卡片图像会立即在面朝上和面朝下图像之间切换。此处的“UIView.transition”调用与上述代码中的调用相同。这里唯一的区别是它不包装到 0.01 秒的 UIView.animate 完成块中。
imageView.alpha = 1.0 imageView.layoutIfNeeded() UIView.transition(with: imageView, duration: 1.2, options: animation) { imageView.image = endingImage imageView.layoutIfNeeded() // same behaviour with and without this line } completion: { (true) in if self.dealTicketState.isTicketFaceUp == true { self.faceDownView.alpha = 0.0 } else { self.faceDownView.alpha = 1.0 } UIView.animate(withDuration: 0.01) { self.coveringLabel.backgroundColor = .clear self.coveringLabel.layoutIfNeeded() imageView.removeFromSuperview() self.tickNumLabel.alpha = originalTicketNumAlpha } }
这个过渡结束了我的 flipTicket() 函数。在这两种情况下,此转换之前的代码是相同的。我不打算把它包括在内,因为我认为没有必要理解这个问题——但话又说回来——我知道什么?以下是上述剪辑之前的内容:
func flipTicket() { let originalTicketNumAlpha = self.tickNumLabel.alpha self.tickNumLabel.alpha = 0.0 let tempFaceDownImage:UIImage = self.dealTicketState.faceDownImage let tempFaceUpImage:UIImage = getCurrentFaceUpImage() var endingImage:UIImage = self.dealTicketState.faceDownImage let imageView = UIImageView() imageView.translatesAutoresizingMaskIntoConstraints = false imageView.contentMode = .scaleToFill imageView.clipsToBounds = true imageView.alpha = 0.0 self.coveringLabel.alpha = 1.0 self.coveringLabel.backgroundColor = .black self.coveringLabel.layoutIfNeeded() var animation:UIView.AnimationOptions = .transitionFlipFromLeft if faceDownView.alpha == 1.0 { animation = .transitionFlipFromRight imageView.image = tempFaceDownImage endingImage = tempFaceUpImage } else { animation = .transitionFlipFromLeft imageView.image = tempFaceUpImage } self.addSubview(imageView) NSLayoutConstraint.activate([ imageView.topAnchor.constraint(equalTo: self.topAnchor), imageView.bottomAnchor.constraint(equalTo: self.bottomAnchor), imageView.leadingAnchor.constraint(equalTo: self.leadingAnchor), imageView.trailingAnchor.constraint(equalTo: self.trailingAnchor), ]) imageView.layoutIfNeeded()
背景: 此代码是代表扑克牌的自定义 UI 控件的一部分。它由几个子视图组成。最上面的子视图最初是一个 UIImageView,它保存了卡片背面的图像。这让我可以简单地切换该顶视图的 alpha 以将卡片显示为面朝上或面朝下。然后我向控件添加了一个 topMost 视图 - 一个带有“background = .clear”的 UILabel 并附加了一个 UITapGestureRecognizer 。当控件被点击时,这个用于动画卡片翻转的函数被调用。
为了构建动画,我调用了 getCurrentFaceUp() 函数,该函数临时将卡片 faceDownView 的 alpha 设置为 0(这样我就可以在卡片下方拍摄当前配置的卡片快照)。它返回卡片“正面朝上”视图的 UIImage。我已经有了 faceDown 视图的 UIImage。这是我过渡所需的 2 张图片。
所以...然后我将 topMost UILabel 的背景颜色设置为 .black,创建一个新的临时 UIImageView 并将其放在现有控件的顶部。我将临时 imageView 设置为最初显示控件上当前可见的 2 个图像中的任何一个。然后我运行翻转过渡,更改背景控件的配置以匹配新状态,将标签背景更改回 .clear 并处理临时 UIImageView。
(如果有更好的方法来实现这一点,我很乐意听到它,但这篇文章的主要目的是了解为什么我的代码似乎表现得很奇怪。)
当我在寻找一种动画卡片翻转的方法时,我发现了一个 YouTube 视频,该视频演示了 UIView.transition() 与翻转动画。它不需要使用 UIView.animate() 包装器来使其工作 - 所以我很确定是我做错了什么 - 但我花了几个小时测试变化并寻找其他有这个问题的人我一直没能找到答案。
非常感谢任何可以帮助我了解这里发生了什么的人......
【问题讨论】:
-
我不认为是 layoutIfNeeded()。我在调用和不调用 layoutIfNeeded() 的情况下都对其进行了测试,它的行为方式相同 - 也就是说 - 它在一个示例中有效,在另一个示例中无效(但两组代码都包含 layoutIfNeeded() 调用. 另外 - Apple 文档声明您需要在动画块的末尾包含 layoutIfNeeded() 以便它知道要制作什么动画。
-
好的,那么它似乎是
imageView.alpha的设置?如果您暂时将其注释掉,是否可以解决问题? -
@matt 不,注释掉 ImageView.alpha=1.0 不会使损坏的代码工作 - 但它确实会使工作代码中断。
标签: ios swift uiviewanimationtransition