UIKit Dynamics 和 CALayers 与 UIView 分离

UIKit Dynamics and CALayers decoupled from UIView

是否可以在使用 UIKit Dynamics 时不使用 UIView,而是将物理属性、锚点、力等全部绑定到一个 UIView 中的 CALayer?

根据 Ash Farrow 的这个页面:

UIDynamicItem is a protocol that defines a centre, a bounds, and a transform (only two-dimensional transforms are used). UIView conforms to this protocol, and is the most common use of UIDynamicBehaviour. You can also use UICollectionViewLayoutAttributes with UIDynamicBehaviours, but we’re not going to cover that today.

这似乎表明任何东西都可以符合 UIDynamicItem 协议,但我找不到任何关于其他人制作 CALayers 的信息。

能不能比这个方法更直接:

https://www.invasivecode.com/weblog/uikit-dynamics-layer-constraint/

如链接文章所述,CALayer 这些方法的类型存在冲突,因此不能直接符合 UIDynamicItem。您需要的是某种适配器层,将 CALayer 方法转换为 UIDynamicItem 所需的类型和含义。

幸运的是,UIKit 正好提供了这样一个适配器层。它被称为UIView。只需将每一层放在一个视图中并嵌套视图即可。

我一直认为观点非常重量级,特别是来自 OS X 世界。所以我一直认为 "if you want this to be fast, you'd better do it with a layer." 但事实证明,视图实际上非常薄,并且在大多数情况下与层相比没有太多开销,特别是对于你在 iOS 中谈论的数字.请参阅 TearOff 演示,了解使用许多视图毫无问题地执行 UIKItDynamics 的示例。

如果你真的需要图层,那么是的,你绝对可以做到。只需自己创建适配器。它只需要持有一个CALayer并符合UIKitDynamics。它不需要做任何其他事情。这样的事情应该有效:

public class DynamicLayerItem : NSObject, UIDynamicItem {
    let layer: CALayer
    init(layer: CALayer) { self.layer = layer}

    public var center: CGPoint { get {
        return layer.position
        }
        set {
            layer.position = center
        }
    }

    public var bounds: CGRect { return layer.bounds }
    public var transform: CGAffineTransform {
        get {
            return layer.affineTransform()
        }
        set {
            layer.transform = CATransform3DMakeAffineTransform(newValue)
        }
    }
}

您只需为该对象设置动画,这会导致图层以等效方式设置动画。