iOS 11上的MKAnnotationView setImage()具有动画
自iOS 11起,当我在自定义MKAnnotationView
中使用setImage
时,图像将显示为带有动画.
Since iOS 11, when I use setImage
in my custom MKAnnotationView
, the image is displayed with an animation.
问题是当我选择并取消选择MKAnnotationView
且图像具有不同的大小时.这样会产生怪异的动画.
The problem is when I select and deselect the MKAnnotationView
and the image has a different size. It results in a weird animation.
在iOS 11之前没有问题,我们可以停止这种行为吗?
No problem until iOS 11, can we stop this behaviour?
看到这是我在过去的一年中发现 anywhere 的唯一问题(功能?).一半,首先让我感谢您是我唯一的理智来源.这样,我终于可以回过头来揭开这……的神秘面纱了.我尚未提起雷达,只是因为目前尚不清楚这种行为是否是故意的.无论正确的行为如何,动画都有一些奇怪的副作用,并导致我报告单独的问题.
Seeing that this is the only mention of this issue (feature?) that I've found anywhere over the past year and a half, let me first thank you for being my only source of sanity. With that, I've finally been able to circle back and demystify this...sort of. I've yet to file a radar, only because it is unclear whether this behavior is intended. Whatever the correct behavior, the animation has some odd side-effects, and led me to report a separate issue.
要精简起见,image
字段不是UIKit
将无法停止它们.相反,我们必须完全停止当前线程事务的动画操作,以使嵌套图层动画永远不能执行:
To boil it down, the image
field is not an animatable field, but updating it outside of a user-defined transaction triggers a system-performed path animation from the previous image to the new image. Since the animations are performed at the layer-level, UIKit
will not be able to stop them. Instead, we have to halt the current thread transaction's animation actions entirely so that the nested layer animations are never allowed to perform:
CATransaction.begin()
CATransaction.setDisableActions(true)
annotationView.image = newImage
CATransaction.commit()
修改现有动画
除了完全切断动画之外,还可以通过将自己的属性注入当前线程事务来消除路径动画的混乱.不过,这里要注意的是,为了正确地设置路径&的动画效果,要使图像看起来不动(例如,从小别针动画到大别针动画),我们必须同步centerOffset
的其他动画.此字段确实not
直接修改了图层,但是它看起来确实是UIKit可动画化的字段.这意味着您需要将UIKit动画与CoreAnimation事务相结合:
Modifying Existing Animation
Rather than cutting off the animation completely, you can also de-jank the path animation by injecting your own properties to the current thread transaction. The catch here, though, is that in order to correctly animate the path & make the appearance that the image isn't moving (ex. animating from a small pin to a large pin), we have to synchronize an additional animation of the centerOffset
. This field does not
directly modify the layer, but it does appear to be a UIKit-animatable field. This means that you need to combine a UIKit animation with a CoreAnimation transaction:
CATransaction.begin()
CATransaction.setAnimationDuration(animationDuration)
CATransaction.setAnimationTimingFunction(CAMediaTimingFunction(name: .easeIn))
UIView.animate(withDuration: animationDuration, delay: 0, options: .curveEaseIn, animations: {
self.image = newImage
self.centerOffset = newCenterOffset
}, completion: nil)
CATransaction.commit()
持续时间&两个UIKit动画&的定时功能必须相同CoreAnimation交易.
The duration & timing function must be the same for both the UIKit animation & the CoreAnimation transaction.