reducir - sensibilidad pantalla iphone 6
Agita el efecto visual en iPhone(NO agita el dispositivo) (11)
Aquí hay un tutorial que detalla cómo hacerlo en Cocoa. Debería ser el mismo para el iPhone (o al menos bastante similar).
http://www.cimgf.com/2008/02/27/core-animation-tutorial-window-shake-effect/
Si falla el inicio de sesión, prefiero evitar mostrar una alerta, es demasiado fugaz. Mostrar la alerta y luego mostrar el texto en algún lugar de la pantalla de inicio de sesión parece una duplicación.
Así que me gustaría que esto agite gráficamente mi vista de inicio de sesión cuando el usuario ingresa el ID de usuario y la contraseña incorrectos como lo hace la pantalla de inicio de sesión de Mac.
¿Alguien sabe si hay alguna forma de lograrlo o si tiene alguna sugerencia sobre otro efecto que pueda usar?
Categoría de batido muy fácil para UIVoew
Creo que esta es una solución más eficiente:
Rápido:
let anim = CAKeyframeAnimation( keyPath:"transform" )
anim.values = [
NSValue( CATransform3D:CATransform3DMakeTranslation(-5, 0, 0 ) ),
NSValue( CATransform3D:CATransform3DMakeTranslation( 5, 0, 0 ) )
]
anim.autoreverses = true
anim.repeatCount = 2
anim.duration = 7/100
viewToShake.layer.addAnimation( anim, forKey:nil )
Obj-C:
CAKeyframeAnimation * anim = [ CAKeyframeAnimation animationWithKeyPath:@"transform" ] ;
anim.values = @[
[ NSValue valueWithCATransform3D:CATransform3DMakeTranslation(-5.0f, 0.0f, 0.0f) ],
[ NSValue valueWithCATransform3D:CATransform3DMakeTranslation( 5.0f, 0.0f, 0.0f) ]
] ;
anim.autoreverses = YES ;
anim.repeatCount = 2.0f ;
anim.duration = 0.07f ;
[ viewToShake.layer addAnimation:anim forKey:nil ] ;
Solo se crea un objeto de animación y se realiza todo en el nivel CoreAnimation.
En iOS 7.0 o posterior, la animación de fotogramas clave UIKit está disponible.
[UIView animateKeyframesWithDuration:0.5 delay:0.0 options:0 animations:^{
[UIView setAnimationCurve:UIViewAnimationCurveLinear];
NSInteger repeatCount = 8;
NSTimeInterval duration = 1.0 / (NSTimeInterval)repeatCount;
for (NSInteger i = 0; i < repeatCount; i++) {
[UIView addKeyframeWithRelativeStartTime:i * duration relativeDuration:duration animations:^{
CGFloat dx = 5.0;
if (i == repeatCount - 1) {
viewToShake.transform = CGAffineTransformIdentity;
} else if (i % 2) {
viewToShake.transform = CGAffineTransformTranslate(CGAffineTransformIdentity, -dx, 0.0);
} else {
viewToShake.transform = CGAffineTransformTranslate(CGAffineTransformIdentity, +dx, 0.0);
}
}];
}
} completion:completion];
Este fragmento de categoría UIView funcionó para mí. Está utilizando 3 CABasingAnimations aplicadas a la capa de la vista.
#import <UIKit/UIKit.h>
#import <QuartzCore/QuartzCore.h>
#define Y_OFFSET 2.0f
#define X_OFFSET 2.0f
#define ANGLE_OFFSET (M_PI_4*0.1f)
@interface UIView (shakeAnimation)
-(BOOL)isShakeAnimationRunning;
-(void)startShakeAnimation;
-(void)stopShakeAnimation;
@end
@implementation UIView (shakeAnimation)
-(BOOL)isShakeAnimationRunning{
return [self.layer animationForKey:@"shake_rotation"] != nil;
}
-(void)startShakeAnimation{
CFTimeInterval offset=(double)arc4random()/(double)RAND_MAX;
self.transform=CGAffineTransformRotate(self.transform, -ANGLE_OFFSET*0.5);
self.transform=CGAffineTransformTranslate(self.transform, -X_OFFSET*0.5f, -Y_OFFSET*0.5f);
CABasicAnimation *tAnim=[CABasicAnimation animationWithKeyPath:@"position.x"];
tAnim.repeatCount=HUGE_VALF;
tAnim.byValue=[NSNumber numberWithFloat:X_OFFSET];
tAnim.duration=0.07f;
tAnim.autoreverses=YES;
tAnim.timeOffset=offset;
[self.layer addAnimation:tAnim forKey:@"shake_translation_x"];
CABasicAnimation *tyAnim=[CABasicAnimation animationWithKeyPath:@"position.y"];
tyAnim.repeatCount=HUGE_VALF;
tyAnim.byValue=[NSNumber numberWithFloat:Y_OFFSET];
tyAnim.duration=0.06f;
tyAnim.autoreverses=YES;
tyAnim.timeOffset=offset;
[self.layer addAnimation:tyAnim forKey:@"shake_translation_y"];
CABasicAnimation *rAnim=[CABasicAnimation animationWithKeyPath:@"transform.rotation"];
rAnim.repeatCount=HUGE_VALF;
rAnim.byValue=[NSNumber numberWithFloat:ANGLE_OFFSET];
rAnim.duration=0.15f;
rAnim.autoreverses=YES;
rAnim.timeOffset=offset;
[self.layer addAnimation:rAnim forKey:@"shake_rotation"];
}
-(void)stopShakeAnimation{
[self.layer removeAnimationForKey:@"shake_translation_x"];
[self.layer removeAnimationForKey:@"shake_translation_y"];
[self.layer removeAnimationForKey:@"shake_rotation"];
[UIView animateWithDuration:0.2f animations:^{
self.transform=CGAffineTransformRotate(self.transform, ANGLE_OFFSET*0.5);
self.transform=CGAffineTransformTranslate(self.transform, X_OFFSET*0.5, Y_OFFSET*0.5f);
}];
}
@end
Espero que ayude a alguien :)
Había visto un poco de animación de bamboleo y la cambié para sacudir una vista de píxeles en posición vertical y hacia abajo:
- (void)earthquake:(UIView*)itemView
{
CGFloat t = 2.0;
CGAffineTransform leftQuake = CGAffineTransformTranslate(CGAffineTransformIdentity, t, -t);
CGAffineTransform rightQuake = CGAffineTransformTranslate(CGAffineTransformIdentity, -t, t);
itemView.transform = leftQuake; // starting point
[UIView beginAnimations:@"earthquake" context:itemView];
[UIView setAnimationRepeatAutoreverses:YES]; // important
[UIView setAnimationRepeatCount:5];
[UIView setAnimationDuration:0.07];
[UIView setAnimationDelegate:self];
[UIView setAnimationDidStopSelector:@selector(earthquakeEnded:finished:context:)];
itemView.transform = rightQuake; // end here & auto-reverse
[UIView commitAnimations];
}
- (void)earthquakeEnded:(NSString *)animationID finished:(NSNumber *)finished context:(void *)context
{
if ([finished boolValue])
{
UIView* item = (UIView *)context;
item.transform = CGAffineTransformIdentity;
}
}
Sé que la pregunta ya está respondida, pero como ya implementé algo como esto anteriormente, siento que no está de más agregarlo:
CAKeyframeAnimation *shakeAnimation = [CAKeyframeAnimation animationWithKeyPath:@"transform.rotation.z"];
NSArray *transformValues = [NSArray arrayWithObjects:
[NSNumber numberWithFloat:((M_PI)/64)],
[NSNumber numberWithFloat:(-((M_PI)/64))],
[NSNumber numberWithFloat:((M_PI)/64)],
[NSNumber numberWithFloat:(-((M_PI)/64))],
[NSNumber numberWithFloat:((M_PI)/64)],
[NSNumber numberWithFloat:(-((M_PI)/64))],
[NSNumber numberWithFloat:0],
nil];
[shakeAnimation setValues:transformValues];
NSArray *times = [NSArray arrayWithObjects:
[NSNumber numberWithFloat:0.14f],
[NSNumber numberWithFloat:0.28f],
[NSNumber numberWithFloat:0.42f],
[NSNumber numberWithFloat:0.57f],
[NSNumber numberWithFloat:0.71f],
[NSNumber numberWithFloat:0.85f],
[NSNumber numberWithFloat:1.0f],
nil];
[shakeAnimation setKeyTimes:times];
shakeAnimation.fillMode = kCAFillModeForwards;
shakeAnimation.removedOnCompletion = NO;
shakeAnimation.duration = 0.6f;
[self.viewToShake.layer addAnimation:shakeAnimation forKey:@"anim"];
Además, dado que desea que el temblor indique que el usuario no inició sesión, también puede considerar agregar esta animación que tiñe la pantalla en rojo mientras la pantalla se sacude:
//Put this in the header (.h)
@property (nonatomic, strong) UIView *redView;
//Put this in the implementation (.m)
@synthesize redView;
//Put this in viewDidLoad
self.redView = [[UIView alloc] initWithFrame:self.view.frame];
self.redView.layer.opacity = 0.0f;
self.redView.layer.backgroundColor = [[UIColor redColor] CGColor];
//Put this wherever you check if the login failed
CAKeyframeAnimation *redTint = [CAKeyframeAnimation animationWithKeyPath:@"opacity"];
NSArray *transformValues = [NSArray arrayWithObjects:
[NSNumber numberWithFloat:0.2f],
[NSNumber numberWithFloat:0.0f],
nil];
[redTint setValues:transformValues];
NSArray *times = [NSArray arrayWithObjects:
[NSNumber numberWithFloat:0.5f],
[NSNumber numberWithFloat:1.0f],
nil];
[redTint setKeyTimes:times];
redTint.fillMode = kCAFillModeForwards;
redTint.removedOnCompletion = NO;
redTint.duration = 0.6f;
[self.redView.layer addAnimation:shakeAnimation forKey:@"anim"];
¡Espero que esto ayude!
Simplemente cambiando la coordenada X de la propiedad central de su vista puede hacer el truco. Si no has hecho ninguna animación básica, es bastante sencillo.
Primero, inicie una animación a la derecha, luego espere a que termine y luego vuelva a la izquierda, y así sucesivamente. Bajar el tiempo para que "se sienta bien" podría tomar un tiempo.
- (void)animationFinishCallback:(NSString *)animationID finished:(BOOL)finished context:(void *)context
{
if ([animationID isEqualToString:@"MoveRight"]) {
[UIView beginAnimations:@"MoveLeft" context:NULL];
[UIView setAnimationDuration:1.0];
[UIView setAnimationDelay: UIViewAnimationCurveEaseIn];
[UIView setAnimationDelegate:self];
[UIView setAnimationDidStopSelector:@selector(animationFinishCallback:finished:context:)];
myView.center = CGRectMake(newX, newY);
[UIView commitAnimations];
}
}
Una solución que utilicé para las restricciones que puse en mi guión gráfico. Sin utilizar animateWithDuration.
@IBOutlet var balloonHorizontalConstraint: NSLayoutConstraint!
NSTimer.scheduledTimerWithTimeInterval(0.04, target: self, selector: "animateBalloon", userInfo: nil, repeats: true)
func animateBalloon() {
switch balloonHorizontalConstraint.constant {
case -46:
balloonHorizontalConstraint.constant = -50
default:
balloonHorizontalConstraint.constant = -46
}
}
En mi caso, la animación siguió, pero al momento de abrir el controlador de mi vista después de unos segundos, esto también detiene mi temporizador.
Usando Auto Layout, adapté la respuesta de Chris Miles pero animé NSLayoutConstraints como este:
NSLayoutConstraint *left = ...
NSLayoutConstraint *right = ...
[UIView animateWithDuration:0.08 delay:0.0 options:UIViewAnimationOptionAutoreverse|UIViewAnimationOptionRepeat animations:^{
[UIView setAnimationRepeatCount:3];
left.constant = 15.0;
right.constant = 25.0;
[self.view layoutIfNeeded];
} completion:^(BOOL finished) {
if (finished) {
[UIView animateWithDuration:0.08 animations:^{
left.constant = 20.0;
right.constant = 20.0;
[self.view layoutIfNeeded];
} completion:NULL];
}
}];
Usando animaciones UIKit basadas en bloques de iOS 4+ (y en general basadas en la respuesta de jayccrown):
- (void)shakeView:(UIView *)viewToShake
{
CGFloat t = 2.0;
CGAffineTransform translateRight = CGAffineTransformTranslate(CGAffineTransformIdentity, t, 0.0);
CGAffineTransform translateLeft = CGAffineTransformTranslate(CGAffineTransformIdentity, -t, 0.0);
viewToShake.transform = translateLeft;
[UIView animateWithDuration:0.07 delay:0.0 options:UIViewAnimationOptionAutoreverse|UIViewAnimationOptionRepeat animations:^{
[UIView setAnimationRepeatCount:2.0];
viewToShake.transform = translateRight;
} completion:^(BOOL finished) {
if (finished) {
[UIView animateWithDuration:0.05 delay:0.0 options:UIViewAnimationOptionBeginFromCurrentState animations:^{
viewToShake.transform = CGAffineTransformIdentity;
} completion:NULL];
}
}];
}