【问题标题】:iOS icon jiggle algorithmiOS 图标抖动算法
【发布时间】:2011-09-30 01:37:03
【问题描述】:

我正在编写一个 iPad 应用程序,它以类似于 Pages 呈现用户文档的方式呈现用户文档(作为实际文档的大图标)。我还想模仿用户点击编辑按钮时的抖动行为。这与您在 iPhone 和 iPad 上点击并按住主屏幕上的图标时所产生的抖动模式相同。

我在互联网上搜索并找到了一些算法,但它们只会导致视图来回摇摆,这根本不像 Apple 摇晃。似乎有一些随机性,因为每个图标都有点不同。

是否有人拥有或知道一些代码可以重新创建相同的抖动模式(或非常接近的模式)?谢谢!!!

【问题讨论】:

    标签: iphone ios ipad uiview core-animation


    【解决方案1】:

    如果有人在 Swift 中需要相同的代码

    class Animation {
    
        static func wiggle(_ btn: UIButton) {
            btn.startWiggling()
        }
    } 
    
    extension UIView {
    
    func startWiggling() {
    
        let count = 5
        let kAnimationRotateDeg = 1.0
    
        let leftDegrees = (kAnimationRotateDeg * ((count%2 > 0) ? +5 : -5)).convertToDegrees()
        let leftWobble = CGAffineTransform(rotationAngle: leftDegrees)
    
        let rightDegrees = (kAnimationRotateDeg * ((count%2 > 0) ? -10 : +10)).convertToDegrees()
        let rightWobble = CGAffineTransform(rotationAngle: rightDegrees)
    
        let moveTransform = rightWobble.translatedBy(x: -2.0, y: 2.0)
        let concatTransform = rightWobble.concatenating(moveTransform)
    
        self.transform = leftWobble
    
        UIView.animate(withDuration: 0.1,
                       delay: 0.1,
                       options: [.allowUserInteraction, .repeat, .autoreverse],
                       animations: {
                        UIView.setAnimationRepeatCount(3)
                        self.transform = concatTransform
        }, completion: { success in
            self.layer.removeAllAnimations()
            self.transform = .identity
        })
    }
    }
    

    打电话来

        Animation.wiggle(viewToBeAnimated)
    

    最好为您调用的函数编写一个包装器,这样即使您必须更改函数参数或者可能是函数的名称,您也不必在代码中的任何地方重写它。

    【讨论】:

      【解决方案2】:

      这是@mientus'代码的Swift 4.2版本(它本身是Paul Popiel's version的更新),作为CALayer的扩展:

      extension CALayer {
      
          private enum WigglingAnimationKey: String {
              case position = "wiggling_position_animation"
              case transform = "wiggling_transform_animation"
          }
      
          func startWiggling() {
              let duration = 0.25
              let displacement = 1.0
              let negativeDisplacement = displacement * -1
              let rotationAngle = Measurement(value: 2, unit: UnitAngle.degrees)
      
              // Position animation
              let positionAnimation = CAKeyframeAnimation(keyPath: #keyPath(CALayer.position))
              positionAnimation.beginTime = 0.8
              positionAnimation.duration = duration
              positionAnimation.values = [
                  NSValue(cgPoint: CGPoint(x: negativeDisplacement, y: negativeDisplacement)),
                  NSValue(cgPoint: CGPoint.zero),
                  NSValue(cgPoint: CGPoint(x: 0, y: negativeDisplacement)),
                  NSValue(cgPoint: CGPoint(x: negativeDisplacement, y: negativeDisplacement))
              ]
              positionAnimation.calculationMode = .linear
              positionAnimation.isRemovedOnCompletion = false
              positionAnimation.repeatCount = .greatestFiniteMagnitude
              positionAnimation.beginTime = CFTimeInterval(Float(Int.random(in: 0...25)) / 100)
              positionAnimation.isAdditive = true
      
              // Rotation animation
              let transformAnimation = CAKeyframeAnimation(keyPath: #keyPath(CALayer.transform))
              transformAnimation.beginTime = 2.6
              transformAnimation.duration = duration
              transformAnimation.valueFunction = CAValueFunction(name: .rotateZ)
              transformAnimation.values = [
                  CGFloat(rotationAngle.converted(to: .radians).value * -1),
                  CGFloat(rotationAngle.converted(to: .radians).value),
                  CGFloat(rotationAngle.converted(to: .radians).value * -1)
              ]
              transformAnimation.calculationMode = .linear
              transformAnimation.isRemovedOnCompletion = false
              transformAnimation.repeatCount = .greatestFiniteMagnitude
              transformAnimation.isAdditive = true
              transformAnimation.beginTime = CFTimeInterval(Float(Int.random(in: 0...25)) / 100)
      
              self.add(positionAnimation, forKey: WigglingAnimationKey.position.rawValue)
              self.add(transformAnimation, forKey: WigglingAnimationKey.transform.rawValue)
          }
      
          func stopWiggling() {
              self.removeAnimation(forKey: WigglingAnimationKey.position.rawValue)
              self.removeAnimation(forKey: WigglingAnimationKey.transform.rawValue)
          }
      }
      

      用法(其中anyLayerCALayer):

      // Start animating.
      anyLayer.startWiggling()
      // Stop animating.
      anyLayer.stopWiggling()
      

      【讨论】:

        【解决方案3】:

        Paul Popiel 对此给出了很好的回答,我永远感激他。我在他的代码中发现了一个小问题,那就是如果多次调用该例程,它就无法正常工作——图层动画有时会丢失或停用。

        为什么要多次调用它?我通过 UICollectionView 实现它,并且随着单元格出列或移动,我需要重新建立摆动。使用 Paul 的原始代码,尽管我尝试在 dequeue 和 willDisplay 回调中重新建立摆动,但如果它们滚动到屏幕外,我的单元格通常会停止摆动。但是,通过将两个动画命名为键,即使在一个单元格上调用两次,它也始终可以可靠地工作。

        这几乎是 Paul 的所有带有上述小修复的代码,此外,我已将其创建为 UIView 的扩展,并添加了与 Swift 4 兼容的 stopWiggle。

        private func degreesToRadians(_ x: CGFloat) -> CGFloat {
            return .pi * x / 180.0
        }
        
        extension UIView {
            func startWiggle() {
                let duration: Double = 0.25
                let displacement: CGFloat = 1.0
                let degreesRotation: CGFloat = 2.0
                let negativeDisplacement = -1.0 * displacement
                let position = CAKeyframeAnimation.init(keyPath: "position")
                position.beginTime = 0.8
                position.duration = duration
                position.values = [
                    NSValue(cgPoint: CGPoint(x: negativeDisplacement, y: negativeDisplacement)),
                    NSValue(cgPoint: CGPoint(x: 0, y: 0)),
                    NSValue(cgPoint: CGPoint(x: negativeDisplacement, y: 0)),
                    NSValue(cgPoint: CGPoint(x: 0, y: negativeDisplacement)),
                    NSValue(cgPoint: CGPoint(x: negativeDisplacement, y: negativeDisplacement))
                ]
                position.calculationMode = "linear"
                position.isRemovedOnCompletion = false
                position.repeatCount = Float.greatestFiniteMagnitude
                position.beginTime = CFTimeInterval(Float(arc4random()).truncatingRemainder(dividingBy: Float(25)) / Float(100))
                position.isAdditive = true
        
                let transform = CAKeyframeAnimation.init(keyPath: "transform")
                transform.beginTime = 2.6
                transform.duration = duration
                transform.valueFunction = CAValueFunction(name: kCAValueFunctionRotateZ)
                transform.values = [
                    degreesToRadians(-1.0 * degreesRotation),
                    degreesToRadians(degreesRotation),
                    degreesToRadians(-1.0 * degreesRotation)
                ]
                transform.calculationMode = "linear"
                transform.isRemovedOnCompletion = false
                transform.repeatCount = Float.greatestFiniteMagnitude
                transform.isAdditive = true
                transform.beginTime = CFTimeInterval(Float(arc4random()).truncatingRemainder(dividingBy: Float(25)) / Float(100))
        
                self.layer.add(position, forKey: "bounce")
                self.layer.add(transform, forKey: "wiggle")
            }
        
            func stopWiggle() {
                self.layer.removeAllAnimations()
                self.transform = .identity
            }
        }
        

        如果它可以节省其他人在 UICollectionView 中实现此功能的时间,您将需要一些其他地方来确保在移动和滚动期间保持摆动。首先,一个开始摆动所有被调用的单元格的例程:

        func wiggleAllVisibleCells() {
            if let visible = collectionView?.indexPathsForVisibleItems {
                for ip in visible {
                    if let cell = collectionView!.cellForItem(at: ip) {
                        cell.startWiggle()
                    }
                }
            }
        }
        

        随着新单元格的显示(通过移动或滚动),我重新建立摆动:

        override func collectionView(_ collectionView: UICollectionView, willDisplay cell: UICollectionViewCell, forItemAt indexPath: IndexPath) {
            // Make sure cells are all still wiggling
            if isReordering {
                cell.startWiggle()
            }
        }
        

        【讨论】:

          【解决方案4】:

          @mientus Swift 4 中的 Apple Jiggle 原始代码,带有可选参数来调整持续时间(即速度)、位移(即位置变化)和度数(即旋转量)。

          private func degreesToRadians(_ x: CGFloat) -> CGFloat {
              return .pi * x / 180.0
          }
          
          func startWiggle(
              duration: Double = 0.25,
              displacement: CGFloat = 1.0,
              degreesRotation: CGFloat = 2.0
              ) {
              let negativeDisplacement = -1.0 * displacement
              let position = CAKeyframeAnimation.init(keyPath: "position")
              position.beginTime = 0.8
              position.duration = duration
              position.values = [
                  NSValue(cgPoint: CGPoint(x: negativeDisplacement, y: negativeDisplacement)),
                  NSValue(cgPoint: CGPoint(x: 0, y: 0)),
                  NSValue(cgPoint: CGPoint(x: negativeDisplacement, y: 0)),
                  NSValue(cgPoint: CGPoint(x: 0, y: negativeDisplacement)),
                  NSValue(cgPoint: CGPoint(x: negativeDisplacement, y: negativeDisplacement))
              ]
              position.calculationMode = "linear"
              position.isRemovedOnCompletion = false
              position.repeatCount = Float.greatestFiniteMagnitude
              position.beginTime = CFTimeInterval(Float(arc4random()).truncatingRemainder(dividingBy: Float(25)) / Float(100))
              position.isAdditive = true
          
              let transform = CAKeyframeAnimation.init(keyPath: "transform")
              transform.beginTime = 2.6
              transform.duration = duration
              transform.valueFunction = CAValueFunction(name: kCAValueFunctionRotateZ)
              transform.values = [
                  degreesToRadians(-1.0 * degreesRotation),
                  degreesToRadians(degreesRotation),
                  degreesToRadians(-1.0 * degreesRotation)
              ]
              transform.calculationMode = "linear"
              transform.isRemovedOnCompletion = false
              transform.repeatCount = Float.greatestFiniteMagnitude
              transform.isAdditive = true
              transform.beginTime = CFTimeInterval(Float(arc4random()).truncatingRemainder(dividingBy: Float(25)) / Float(100))
          
              self.layer.add(position, forKey: nil)
              self.layer.add(transform, forKey: nil)
          }
          

          【讨论】:

            【解决方案5】:

            我对 Apple Stringboard 进行了逆向工程,并稍微修改了它们的动画,下面的代码真的很棒。

            + (CAAnimationGroup *)jiggleAnimation {
            CAKeyframeAnimation *position = [CAKeyframeAnimation animation];
            position.keyPath = @"position";
            position.values = @[
                                [NSValue valueWithCGPoint:CGPointZero],
                                [NSValue valueWithCGPoint:CGPointMake(-1, 0)],
                                [NSValue valueWithCGPoint:CGPointMake(1, 0)],
                                [NSValue valueWithCGPoint:CGPointMake(-1, 1)],
                                [NSValue valueWithCGPoint:CGPointMake(1, -1)],
                                [NSValue valueWithCGPoint:CGPointZero]
                                ];
            position.timingFunctions = @[
                                         [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut],
                                         [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut]
                                         ];
            position.additive = YES;
            
            CAKeyframeAnimation *rotation = [CAKeyframeAnimation animation];
            rotation.keyPath = @"transform.rotation";
            rotation.values = @[
                                @0,
                                @0.03,
                                @0,
                                [NSNumber numberWithFloat:-0.02]
                                ];
            rotation.timingFunctions = @[
                                         [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut],
                                         [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut]
                                         ];
            
            CAAnimationGroup *group = [[CAAnimationGroup alloc] init];
            group.animations = @[ position, rotation ];
            group.duration = 0.3;
            group.repeatCount = HUGE_VALF;
            group.beginTime = arc4random() % 30 / 100.f;
            return group;
            }
            

            原苹果摇晃动画:

            CAKeyframeAnimation *position = [CAKeyframeAnimation animation];
            position.beginTime = 0.8;
            position.duration = 0.25;
            position.values = @[[NSValue valueWithCGPoint:CGPointMake(-1, -1)],
                                [NSValue valueWithCGPoint:CGPointMake(0, 0)],
                                [NSValue valueWithCGPoint:CGPointMake(-1, 0)],
                                [NSValue valueWithCGPoint:CGPointMake(0, -1)],
                                [NSValue valueWithCGPoint:CGPointMake(-1, -1)]];
            position.calculationMode = @"linear";
            position.removedOnCompletion = NO;
            position.repeatCount = CGFLOAT_MAX;
            position.beginTime = arc4random() % 25 / 100.f;
            position.additive = YES;
            position.keyPath = @"position";
            
            CAKeyframeAnimation *transform = [CAKeyframeAnimation animation];
            transform.beginTime = 2.6;
            transform.duration = 0.25;
            transform.valueFunction = [CAValueFunction functionWithName:kCAValueFunctionRotateZ];
            transform.values = @[@(-0.03525565),@(0.03525565),@(-0.03525565)];
            transform.calculationMode = @"linear";
            transform.removedOnCompletion = NO;
            transform.repeatCount = CGFLOAT_MAX;
            transform.additive = YES;
            transform.beginTime = arc4random() % 25 / 100.f;
            transform.keyPath = @"transform";
            
            [self.dupa.layer addAnimation:position forKey:nil];
            [self.dupa.layer addAnimation:transform forKey:nil];
            

            【讨论】:

            • 天哪,我爱你,这太完美了
            【解决方案6】:


            @Vic320 的回答很好,但我个人不喜欢这个翻译。 我编辑了他的代码以提供一个我个人觉得更像跳板摆动效果的解决方案。大多数情况下,它是通过添加一点随机性并专注于旋转来实现的,而不需要平移:

            #define degreesToRadians(x) (M_PI * (x) / 180.0)
            #define kAnimationRotateDeg 1.0
            
            - (void)startJiggling {
                NSInteger randomInt = arc4random_uniform(500);
                float r = (randomInt/500.0)+0.5;
            
                CGAffineTransform leftWobble = CGAffineTransformMakeRotation(degreesToRadians( (kAnimationRotateDeg * -1.0) - r ));
                CGAffineTransform rightWobble = CGAffineTransformMakeRotation(degreesToRadians( kAnimationRotateDeg + r ));
            
                 self.transform = leftWobble;  // starting point
            
                 [[self layer] setAnchorPoint:CGPointMake(0.5, 0.5)];
            
                 [UIView animateWithDuration:0.1
                                       delay:0
                                     options:UIViewAnimationOptionAllowUserInteraction | UIViewAnimationOptionRepeat | UIViewAnimationOptionAutoreverse
                                   animations:^{ 
                                             [UIView setAnimationRepeatCount:NSNotFound];
                                             self.transform = rightWobble; }
                                  completion:nil];
            }
            - (void)stopJiggling {
                [self.layer removeAllAnimations];
                self.transform = CGAffineTransformIdentity;
            }
            


            尽管信用到期,@Vic320 的回答提供了此代码的基础,因此为此 +1。

            【讨论】:

            • 如果您的锚点设置在其他位置,而不是 0.5,0.5,则旋转将使按钮围绕锚点“环绕”。这本身可能是一个很酷的效果:)
            • 是的,亚历克斯!可能不适合 OP,但那将是一个很酷的效果。
            • 多加点:[UIView setAnimationRepeatCount:NSNotFound];不需要,因为 UIViewAnimationOptionRepeat 已设置。要停止动画,请执行以下操作: [self.layer removeAllAnimations];
            • 除了@sdsykes 所说的要删除所有动画之外,您可能还需要重置转换,以便您的视图不会旋转。 self.transform = CGAffineTransformIdentity;
            • @spotdog13 我在回答中提到“@Vic320 的回答提供了此代码的基础”。我的代码旨在替换他的 -[startJiggling:] 方法。他提供了一个 -[stopJiggling] 方法,可以按照你们的描述删除动画并重置变换,所以我觉得没有必要在这里重复。
            【解决方案7】:

            为了完整起见,以下是我使用显式动画为我的 CALayer 子类设置动画的方式(受其他答案的启发)。

            -(void)stopJiggle 
            {
                [self removeAnimationForKey:@"jiggle"];
            }
            
            -(void)startJiggle 
            {
                const float amplitude = 1.0f; // degrees
                float r = ( rand() / (float)RAND_MAX ) - 0.5f;
                float angleInDegrees = amplitude * (1.0f + r * 0.1f);
                float animationRotate = angleInDegrees / 180. * M_PI; // Convert to radians
            
                NSTimeInterval duration = 0.1;
                CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"transform.rotation"];
                animation.duration = duration;
                animation.additive = YES;
                animation.autoreverses = YES;
                animation.repeatCount = FLT_MAX;
                animation.fromValue = @(-animationRotate);
                animation.toValue = @(animationRotate);
                animation.timeOffset = ( rand() / (float)RAND_MAX ) * duration;
                [self addAnimation:animation forKey:@"jiggle"];
            }
            

            【讨论】:

              【解决方案8】:

              所以我确定我会因为编写乱七八糟的代码而被骂(可能有更简单的方法可以做到这一点,因为我是半初学者,所以我不知道),但这是一个更随机的版本改变旋转和平移量的 Vic320 算法。它还随机决定它首先摆动的方向,如果您同时有多个摆动的东西,它会提供更多更随机的外观。如果效率对您来说是个大问题,请不要使用。这正是我想出的我知道的方法。

              如果有人想知道您需要 #import <QuartzCore/QuartzCore.h> 并将其添加到您的链接库中。

              #define degreesToRadians(x) (M_PI * (x) / 180.0)
              
              - (void)startJiggling:(NSInteger)count {
                  double kAnimationRotateDeg = (double)(arc4random()%5 + 5) / 10;
                  double kAnimationTranslateX = (arc4random()%4);
                  double kAnimationTranslateY = (arc4random()%4);
              
                  CGAffineTransform leftWobble = CGAffineTransformMakeRotation(degreesToRadians( kAnimationRotateDeg * (count%2 ? +1 : -1 ) ));
                  CGAffineTransform rightWobble = CGAffineTransformMakeRotation(degreesToRadians( kAnimationRotateDeg * (count%2 ? -1 : +1 ) ));
                  int leftOrRight = (arc4random()%2);
                  if (leftOrRight == 0){
                      CGAffineTransform moveTransform = CGAffineTransformTranslate(rightWobble, -kAnimationTranslateX, -kAnimationTranslateY);
                      CGAffineTransform conCatTransform = CGAffineTransformConcat(rightWobble, moveTransform);
                      self.transform = leftWobble;  // starting point
              
                      [UIView animateWithDuration:0.1
                                            delay:(count * 0.08)
                                          options:UIViewAnimationOptionAllowUserInteraction | UIViewAnimationOptionRepeat | UIViewAnimationOptionAutoreverse
                                       animations:^{ self.transform = conCatTransform; }
                                       completion:nil];
                  } else if (leftOrRight == 1) {
                      CGAffineTransform moveTransform = CGAffineTransformTranslate(leftWobble, -kAnimationTranslateX, -kAnimationTranslateY);
                      CGAffineTransform conCatTransform = CGAffineTransformConcat(leftWobble, moveTransform);
                      self.transform = rightWobble;  // starting point
              
                      [UIView animateWithDuration:0.1
                                            delay:(count * 0.08)
                                          options:UIViewAnimationOptionAllowUserInteraction | UIViewAnimationOptionRepeat | UIViewAnimationOptionAutoreverse
                                       animations:^{ self.transform = conCatTransform; }
                                       completion:nil];
                  }
              }
              
              - (void)stopJiggling {
                  [self.layer removeAllAnimations];
                  self.transform = CGAffineTransformIdentity;  // Set it straight 
              }
              

              【讨论】:

              • 我喜欢你选择随机开始摇晃的方向。我也要去更新我的代码了!!
              【解决方案9】:

              为了将来出现的其他人的利益,我觉得@Vic320 提供的微动有点过于机械化,与 Keynote 相比,它有点太强烈而且不够有机(随机?)。因此,本着分享的精神,这是我在 UIView 的子类中构建的代码......我的视图控制器保留了这些对象的数组,当用户点击编辑按钮时,视图控制器向每个对象发送 startJiggling 消息,然后当用户按下完成按钮时,通过 stopJiggling 消息。

              - (void)startJiggling
              {
                  // jiggling code based off the folks on stackoverflow.com:
                  // http://stackoverflow.com/questions/6604356/ios-icon-jiggle-algorithm
              
              #define degreesToRadians(x) (M_PI * (x) / 180.0)
              #define kAnimationRotateDeg 0.1
                  jiggling = YES;
                  [self wobbleLeft];
              }
              
              - (void)wobbleLeft
              {
                  if (jiggling) {
                      NSInteger randomInt = arc4random()%500;
                      float r = (randomInt/500.0)+0.5;
              
                      CGAffineTransform leftWobble = CGAffineTransformMakeRotation(degreesToRadians( (kAnimationRotateDeg * -1.0) - r ));
                      CGAffineTransform rightWobble = CGAffineTransformMakeRotation(degreesToRadians( kAnimationRotateDeg + r ));
              
                      self.transform = leftWobble;  // starting point
              
                      [UIView animateWithDuration:0.1
                                    delay:0
                                  options:UIViewAnimationOptionAllowUserInteraction
                               animations:^{ self.transform = rightWobble; }
                               completion:^(BOOL finished) { [self wobbleRight]; }
                        ];
                  }
              }
              
              - (void)wobbleRight
              {
                  if (jiggling) {
              
                      NSInteger randomInt = arc4random()%500;
                      float r = (randomInt/500.0)+0.5;
              
                      CGAffineTransform leftWobble = CGAffineTransformMakeRotation(degreesToRadians( (kAnimationRotateDeg * -1.0) - r ));
                      CGAffineTransform rightWobble = CGAffineTransformMakeRotation(degreesToRadians( kAnimationRotateDeg + r ));
              
                      self.transform = rightWobble;  // starting point
              
                      [UIView animateWithDuration:0.1
                                    delay:0
                                  options:UIViewAnimationOptionAllowUserInteraction
                               animations:^{ self.transform = leftWobble; }
                               completion:^(BOOL finished) { [self wobbleLeft]; }
                       ];
                  }
              
              }
              - (void)stopJiggling
              {
                  jiggling = NO;
                  [self.layer removeAllAnimations];
                  [self setTransform:CGAffineTransformIdentity];
                  [self.layer setAnchorPoint:CGPointMake(0.5, 0.5)];
              }
              

              【讨论】:

                【解决方案10】:

                好的,所以 openspringboard 代码并没有完全适合我,但我确实允许我创建一些我认为更好的代码,但仍然不是完美但更好。如果有人有更好的建议,我很想听听他们...(将其添加到您想要抖动的视图的子类中)

                #define degreesToRadians(x) (M_PI * (x) / 180.0)
                #define kAnimationRotateDeg 1.0
                #define kAnimationTranslateX 2.0
                #define kAnimationTranslateY 2.0
                
                - (void)startJiggling:(NSInteger)count {
                
                    CGAffineTransform leftWobble = CGAffineTransformMakeRotation(degreesToRadians( kAnimationRotateDeg * (count%2 ? +1 : -1 ) ));
                    CGAffineTransform rightWobble = CGAffineTransformMakeRotation(degreesToRadians( kAnimationRotateDeg * (count%2 ? -1 : +1 ) ));
                    CGAffineTransform moveTransform = CGAffineTransformTranslate(rightWobble, -kAnimationTranslateX, -kAnimationTranslateY);
                    CGAffineTransform conCatTransform = CGAffineTransformConcat(rightWobble, moveTransform);
                
                    self.transform = leftWobble;  // starting point
                
                    [UIView animateWithDuration:0.1
                                          delay:(count * 0.08)
                                        options:UIViewAnimationOptionAllowUserInteraction | UIViewAnimationOptionRepeat | UIViewAnimationOptionAutoreverse
                                     animations:^{ self.transform = conCatTransform; }
                                     completion:nil];
                }
                
                - (void)stopJiggling {
                    [self.layer removeAllAnimations];
                    self.transform = CGAffineTransformIdentity;  // Set it straight 
                }
                

                【讨论】:

                  【解决方案11】:

                  查看openspringboard project

                  特别是,setIconAnimation:(BOOL)isAnimating 在 OpenSpringBoard.m 中。这应该会给你一些关于如何做到这一点的想法。

                  【讨论】:

                    猜你喜欢
                    • 1970-01-01
                    • 2021-11-10
                    • 1970-01-01
                    • 2014-11-07
                    • 2021-10-20
                    • 1970-01-01
                    • 1970-01-01
                    • 2012-04-26
                    • 1970-01-01
                    相关资源
                    最近更新 更多