Как сделать мигающий (или мигающий) курсор на iphone?
Я пытаюсь создать пользовательский "мигающий курсор" в UIKit, я попробовал, как показано ниже, имея 2 функции, которые в основном продолжают вызывать друг друга, пока курсор не будет скрыт. Но это приводит к хорошей бесконечной рекурсии... по какой-то причине функции вызывают друг друга сразу, а не каждую полсекунду, как ожидалось.
Я попытался вернуть, если параметр 'Finished' не YES (раскомментировав строку 'if (! Ok)'), но это вообще не приводит к анимации...
Есть идея получше? Я что-то упустил, есть ли гораздо более простой способ сделать "мигающий курсор"?
- (void)onBlinkIn:(NSString *)animationID finished:(BOOL)ok context:(void *)ctx {
if (cursorView.hidden) return;
//if (!ok) return;
[UIView beginAnimations:nil context:UIGraphicsGetCurrentContext()];
[UIView setAnimationCurve:UIViewAnimationCurveEaseInOut];
[UIView setAnimationDuration:0.5f];
[UIView setAnimationDelegate:self];
[UIView setAnimationDidStopSelector:@selector(onBlinkOut:finished:context:)];
cursorView.textColor = [UIColor grayColor];
[UIView commitAnimations];
}
- (void)onBlinkOut:(NSString *)animationID finished:(BOOL)ok context:(void *)ctx {
if (cursorView.hidden) return;
[UIView beginAnimations:nil context:UIGraphicsGetCurrentContext()];
[UIView setAnimationCurve:UIViewAnimationCurveEaseInOut];
[UIView setAnimationDuration:0.5f];
[UIView setAnimationDelegate:self];
[UIView setAnimationDidStopSelector:@selector(onBlinkIn:finished:context:)];
cursorView.textColor = [UIColor clearColor];
[UIView commitAnimations];
}
5 ответов
По делегату:
- (void)blinkAnimation:(NSString *)animationId finished:(BOOL)finished target:(UIView *)target
{
if (shouldContinueBlinking) {
[UIView beginAnimations:animationId context:target];
[UIView setAnimationDuration:0.5f];
[UIView setAnimationDelegate:self];
[UIView setAnimationDidStopSelector:@selector(blinkAnimation:finished:target:)];
if ([target alpha] == 1.0f)
[target setAlpha:0.0f];
else
[target setAlpha:1.0f];
[UIView commitAnimations];
}
}
И чтобы запустить анимацию:
shouldContinueBlinking = YES;
[self blinkAnimation:@"blinkAnimation" finished:YES target:cursorView];
Также убедитесь, что у вашего класса есть переменная экземпляра shouldContinueBlinking.
Сделайте это способом Core Animation:
CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"opacity"];
[animation setFromValue:[NSNumber numberWithFloat:1.0]];
[animation setToValue:[NSNumber numberWithFloat:0.0]];
[animation setDuration:0.5f];
[animation setTimingFunction:[CAMediaTimingFunction
functionWithName:kCAMediaTimingFunctionLinear]];
[animation setAutoreverses:YES];
[animation setRepeatCount:20000];
[[view layer] addAnimation:animation forKey:@"opacity"];
Где вид - это UIView, который вы хотите мигать. Базовая анимация делает это очень удобным, потому что она автоматически перевернет анимацию для вас. Имейте в виду, что ваша полная продолжительность в два раза больше, чем вы задали в поле длительности, потому что указанное вами значение относится к прямому направлению. Если вы хотите, чтобы вся анимация запускалась (вперед, а затем назад) за указанную продолжительность, разделите ее пополам.
Ответ Мэтта Лонга в Swift 4:
func addOpacityAnimation(view: UIView) {
let key = "opacity"
let animation = CABasicAnimation(keyPath: key)
animation.fromValue = 1.0
animation.toValue = 0.0
animation.duration = 0.5
animation.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionLinear)
animation.autoreverses = true
animation.repeatCount = Float.greatestFiniteMagnitude
view.layer.add(animation, forKey: key)
}
Скорее всего, вы блокируете основной цикл событий и, таким образом, блокируете анимацию, когда пытаетесь анимировать только на финише.
Вместо этого установите таймер, который срабатывает через полсекунды и запускает следующую анимацию. Этот таймер может быть сброшен в конце предыдущей анимации, тем самым уменьшая нагрузку и делая вашу частоту мерцания более регулярной (но вам придется выяснить, что является наиболее подходящим).
Смотрите документацию по классу NSTimer.
Обратите внимание, что любая постоянная анимация, подобная этой, приведет к разрядке аккумулятора. Не огромная, во всяком случае, но... все же...
CAKeyframeAnimation *animation = [CAKeyframeAnimation animation];
animation.keyPath = @"opacity";
animation.values = @[ @(0.0),@(0.0),@(1.0), @(1.0)];
animation.keyTimes = @[ @(0.001),@(0.49),@(0.50), @(1.0)];
animation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionLinear];
animation.duration = 1.2;
animation.autoreverses = NO;
animation.repeatCount= HUGE;
[layer addAnimation:animation forKey:@"blink"];