用户从代码输入错误密码时摇动窗口

时间:2012-04-07 17:06:28

标签: objective-c xcode macos cocoa

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

4 个答案:

答案 0 :(得分:13)

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

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];

答案 1 :(得分:4)

这是@ SajjadZare在Swift中的回答:

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)

Swift 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)!)

答案 2 :(得分:2)

我为街区而疯狂。这是一个应该有效的块版本......

- (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];
                                              }];
                         }];
    }
}

答案 3 :(得分:0)

这就是我这样做的方式:

-(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];
        });
    }
}