【问题标题】:shake window when user enter wrong password from code当用户从代码中输入错误密码时摇动窗口
【发布时间】:2012-04-07 17:06:27
【问题描述】:

当我们在 OSX 中需要密码的程序中输入错误密码时,窗口会抖动我如何在我的程序中实现它?

【问题讨论】:

    标签: objective-c xcode macos cocoa


    【解决方案1】:

    当用户输入错误密码时使用下面的代码

    static int numberOfShakes = 8;
        static float durationOfShake = 0.5f;
        static float vigourOfShake = 0.05f;
    
        CGRect frame=[self.view.window frame];
        CAKeyframeAnimation *shakeAnimation = [CAKeyframeAnimation animation];
    
        CGMutablePathRef shakePath = CGPathCreateMutable();
        CGPathMoveToPoint(shakePath, NULL, NSMinX(frame), NSMinY(frame));
        int index;
        for (index = 0; index < numberOfShakes; ++index)
        {
            CGPathAddLineToPoint(shakePath, NULL, NSMinX(frame) - frame.size.width * vigourOfShake, NSMinY(frame));
            CGPathAddLineToPoint(shakePath, NULL, NSMinX(frame) + frame.size.width * vigourOfShake, NSMinY(frame));
        }
        CGPathCloseSubpath(shakePath);
        shakeAnimation.path = shakePath;
        shakeAnimation.duration = durationOfShake;
    
        [self.view.window setAnimations:[NSDictionary dictionaryWithObject: shakeAnimation forKey:@"frameOrigin"]];
        [[self.view.window animator] setFrameOrigin:[self.view.window frame].origin];
    

    【讨论】:

    • 以上使用视图,here摇窗。 变化不大,仅供参考
    【解决方案2】:

    这是@SajjadZare 在 Swift 中的回答:

    斯威夫特 2.0:

            let numberOfShakes:Int = 8
            let durationOfShake:Float = 0.5
            let vigourOfShake:Float = 0.05
    
            let frame:CGRect = (self.view.window?.frame)!
            let shakeAnimation = CAKeyframeAnimation()
    
            let shakePath = CGPathCreateMutable()
            CGPathMoveToPoint(shakePath, nil, NSMinX(frame), NSMinY(frame))
    
            for _ in 1...numberOfShakes {
                CGPathAddLineToPoint(shakePath, nil, NSMinX(frame) - frame.size.width * CGFloat(vigourOfShake), NSMinY(frame))
                CGPathAddLineToPoint(shakePath, nil, NSMinX(frame) + frame.size.width * CGFloat(vigourOfShake), NSMinY(frame))
            }
    
            CGPathCloseSubpath(shakePath)
            shakeAnimation.path = shakePath
            shakeAnimation.duration = CFTimeInterval(durationOfShake)
            self.view.window?.animations = ["frameOrigin":shakeAnimation]
            self.view.window?.animator().setFrameOrigin(self.view.window!.frame.origin)
    

    斯威夫特 3.0:

    let numberOfShakes:Int = 8
        let durationOfShake:Float = 0.5
        let vigourOfShake:Float = 0.05
    
        let frame:CGRect = (self.view.window!.frame)
        let shakeAnimation = CAKeyframeAnimation()
    
        let shakePath = CGMutablePath()
        shakePath.move(to: CGPoint(x: NSMinX(frame), y: NSMinY(frame)))
    
        for _ in 1...numberOfShakes {
            shakePath.addLine(to: CGPoint(x:NSMinX(frame) - frame.size.width * CGFloat(vigourOfShake), y: NSMinY(frame)))
            shakePath.addLine(to: CGPoint(x:NSMinX(frame) + frame.size.width * CGFloat(vigourOfShake), y: NSMinY(frame)))
        }
    
        shakePath.closeSubpath()
        shakeAnimation.path = shakePath
        shakeAnimation.duration = CFTimeInterval(durationOfShake)
        self.view.window?.animations = ["frameOrigin":shakeAnimation]
        self.view.window?.animator().setFrameOrigin((self.view.window?.frame.origin)!)
    

    【讨论】:

    • 这是进入视图控制器还是窗口控制器(如果存在?)
    • 对不起,我不太确定,但我认为它在视图控制器中。我刚刚创建了一个测试应用程序,为按钮添加了一个方法/操作,并将代码粘贴到那里。
    • 这应该与实际摇晃比较吗? imo有点激烈。
    • 我不明白您所说的“与实际比较”是什么意思。如果代码太繁琐,您将不得不弄乱代码。
    【解决方案3】:

    我很喜欢积木。这是一个应该也可以工作的块版本......

    - (void)shakeView:(UIView *)view times:(NSInteger)times completion:(void (^)(BOOL finished))completion {
    
        if (times <= 0) {
            completion(YES);
        } else {
            UIViewAnimationOptions options = UIViewAnimationOptionBeginFromCurrentState;
            [UIView animateWithDuration:0.1 delay: 0.0 options: options 
                             animations:^{
                                 view.frame = CGRectOffset(view.frame, 6.0, 0.0);  // shake to
                             }
                             completion:^(BOOL finished){
                                 [UIView animateWithDuration:0.1 delay: 0.0 options:options 
                                                  animations:^{
                                                      view.frame = CGRectOffset(view.frame, -6.0, 0.0);  // shake fro
                                                  }
                                                  completion:^(BOOL finished) {
                                                      [self shakeView:view times:times-1 completion:completion];
                                                  }];
                             }];
        }
    }
    

    【讨论】:

      【解决方案4】:

      我就是这样做的:

      -(void)shakeLayer:(CALayer*)layer{
          int repeats = 4;
          float time = 0.04;
          float movement = 5;
          for(int x = 0; x < repeats; x++){
              dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(x*(time*4) * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
                  CABasicAnimation *posAnimation = [CABasicAnimation animationWithKeyPath:@"transform.translation.x"];
                  [posAnimation setFromValue:[NSNumber numberWithFloat:0]];
                  [posAnimation setToValue:[NSNumber numberWithFloat:movement]];
                  [posAnimation setBeginTime:0.0];
                  [posAnimation setDuration:time];
      
                  CABasicAnimation *negAnimation = [CABasicAnimation animationWithKeyPath:@"transform.translation.x"];
                  [negAnimation setFromValue:[NSNumber numberWithFloat:movement]];
                  [negAnimation setToValue:[NSNumber numberWithFloat:-movement]];
                  [negAnimation setBeginTime:time];
                  [negAnimation setDuration:time*2];
      
                  CABasicAnimation *posAnimation2 = [CABasicAnimation animationWithKeyPath:@"transform.translation.x"];
                  [posAnimation2 setFromValue:[NSNumber numberWithFloat:-movement]];
                  [posAnimation2 setToValue:[NSNumber numberWithFloat:0]];
                  [posAnimation2 setBeginTime:time*3];
                  [posAnimation2 setDuration:time];
      
                  CAAnimationGroup *group = [CAAnimationGroup animation];
                  [group setDuration:time*4];
                  [group setAnimations:[NSArray arrayWithObjects:posAnimation, negAnimation, posAnimation2, nil]];
      
                  [layer addAnimation:group forKey:nil];
              });
          }
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2013-02-02
        • 2020-10-27
        • 2018-11-30
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多