Ios 设置CALayer动画时平滑动画';黑道

Ios 设置CALayer动画时平滑动画';黑道,ios,objective-c,animation,uikit,core-animation,Ios,Objective C,Animation,Uikit,Core Animation,在我的应用程序中,我有一个ui视图,它使用CALayer来实现阴影: @implementation MyUIView - (instancetype) initWithFrame:(CGRect)frame { self = [super initWithFrame:frame]; if(!self) return self; self.layer.shadowColor = [UIColor colorWithWhite:0 alp

在我的应用程序中,我有一个
ui视图
,它使用
CALayer
来实现阴影:

@implementation MyUIView

    - (instancetype) initWithFrame:(CGRect)frame {
        self = [super initWithFrame:frame];
        if(!self) return self;

        self.layer.shadowColor = [UIColor colorWithWhite:0 alpha:.2].CGColor;
        self.layer.shadowOffset = CGSizeMake(0, 2);
        self.layer.shadowOpacity = 1;
        self.layer.shadowRadius = 1;

        return self;
    }

@end
如果我想要任何接近合理性能的东西,我必须定义
CALayer
shadowPath

@implementation MyUIView

    - (void) setFrame:(CGRect)frame {
        [super setFrame:frame];

        self.layer.shadowPath = CGPathCreateWithRect(self.bounds, NULL);
    }

@end
每当我设置此视图的动画时,我注意到两件事:

  • 如果我不使用
    阴影路径,阴影会随着旋转和帧大小的改变而很好地动画化。这里需要注意的是,动画速度非常慢,而且普遍缺乏性能

  • 如果我do使用
    阴影路径
    ,每当
    ui视图
    设置动画时,动画都是平滑及时的,但是阴影的过渡本身比没有
    阴影路径
    时更像块(也更不平滑)

  • 示例:

    • 使用
      阴影路径
      :(注意阴影的行为如何像一个变换不好的矩形?)
    • 不带阴影路径(动画的缓慢在设备上更为明显,但你知道了):
    编辑:


    值得注意的是,这些动画是隐式的——我自己并没有调用它们。它们是
    UIViewController
    随设备方向旋转的结果。阴影位于旋转过程中改变大小的
    UIView上。

    我试图重现您提供的两个GIF中显示的行为,但没有成功(也许您可以使用动画代码编辑您的问题,例如
    UIView animateWithDuration:animations:

    然而,在我脑海深处的某个地方,我记得偶尔会遇到类似的问题,结果我不得不将视图光栅化以使其平滑

    因此,我不能保证它能为您解决问题,但请尝试一下:

    self.layer.shouldRasterize = YES;
    self.layer.rasterizationScale = [[UIScreen mainScreen] scale];
    

    调整视图大小时,阴影路径需要设置其他动画

    你可以直接使用我的课程

    /*
    斯威夫特
    版权所有©2018、2020-2021 BB9z
    https://github.com/BB9z/iOS-Project-Template
    麻省理工学院执照
    https://opensource.org/licenses/MIT
    */
    /**
    景色投下阴影。
    */
    @可设计的
    类ShadowView:UIView{
    @IBInspectable var shadowOffset:CGPoint=CGPoint(x:0,y:8){
    didSet{needsUpdateStyle=true}
    }
    @IBInspectable var shadowBlur:CGFloat=10{
    didSet{needsUpdateStyle=true}
    }
    @IBInspectable var shadowSpread:CGFloat=0{
    didSet{needsUpdateStyle=true}
    }
    ///设置为零可以禁用阴影
    @IBInspectable var shadowColor:UIColor?=UIColor.black.withAlphaComponent(0.3){
    didSet{needsUpdateStyle=true}
    }
    @i可检测的var角半径:CGFloat{
    获取{layer.cornerRadius}
    设置{layer.cornerRadius=newValue}
    }
    私有变量needsUpdateStyle=false{
    迪塞特{
    guard needsUpdateStyle,!oldValue else{return}
    DispatchQueue.main.async{[self]位于
    如果需要UpdateStyle{updateLayerStyle()}
    }
    }
    }
    private func updateLayerStyle(){
    needsUpdateStyle=false
    如果let color=shadowColor{
    阴影(视图:自身、偏移:阴影偏移、模糊:阴影模糊、扩散:阴影扩散、颜色:颜色、拐角半径:拐角半径)
    }否则{
    layer.shadowColor=nil
    layer.shadowPath=nil
    layer.shadowOpacity=0
    }
    }
    重写func prepareForInterfaceBuilder(){
    super.prepareforPrinterFaceBuilder()
    updateLayerStyle()
    }
    覆盖func layoutSublayers(图层的名称:CALayer){
    超级布局子层(共层)
    lastLayerSize=layer.bounds.size
    如果shadowColor!=nil,layer.shadowOpacity==0{
    updateLayerStyle()
    }
    }
    私有变量lastLayerSize=CGSize.zero{
    迪塞特{
    如果oldValue==lastLayerSize{return}
    保护阴影颜色!=nil else{return}
    updateShadowPathWithAnimationFixes(bonuds:layer.bounds)
    }
    }
    //在调整视图大小时,我们需要一些额外的步骤来实现平滑的结果
    private func updateShadowPathWithAnimationFixes(bonuds:CGRect){
    设rect=bonuds.insertby(dx:shadowSpread,dy:shadowSpread)
    让newShadowPath=UIBezierPath(roundedRect:rect,cornerRadius:cornerRadius).cgPath
    如果让resizeAnimation=layer.animation(forKey:“bounds.size”){
    let key=#keyPath(CALayer.shadowPath)
    让阴影动画=cabasicanition(关键路径:关键点)
    shadowAnimation.duration=调整大小animation.duration
    shadowAnimation.timingFunction=调整大小Animation.timingFunction
    shadowAnimation.fromValue=layer.shadowPath
    shadowAnimation.toValue=newShadowPath
    添加(阴影动画,forKey:key)
    }
    layer.shadowPath=newShadowPath
    }
    }
    /**
    使用与草图应用程序相同的效果制作阴影。
    */
    func阴影(视图:UIView?,偏移:CGPoint,模糊:CGFloat,排列:CGFloat,颜色:UIColor,角半径:CGFloat=0){//swiftlint:disable:此标识符\u名称
    保护层=视图?其他层{
    返回
    }
    layer.shadowColor=color.cgColor
    layer.shadowOffset=CGSize(宽度:offset.x,高度:offset.y)
    layer.shadowRadius=模糊
    layer.shadowOpacity=1
    layer.cornerRadius=cornerRadius
    设rect=layer.bounds.insetBy(dx:spread,dy:spread)
    layer.shadowPath=UIBezierPath(roundedRect:rect,cornerRadius:cornerRadius).cgPath
    }
    

    通过

    我没有手动设置动画,这只是一个随着设备方向旋转的视图控制器。我来试试你的建议。你好,丹尼斯,除了不使用阴影路径之外,这个问题也解决了。这解决了不使用
    shadowPat的性能问题