ios - Как сделать мигающий(или мигающий) курсор на iphone?




objective-c uikit (4)

Ответ Мэтта Лонга в 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)
}

Я пытаюсь создать пользовательский «мигающий курсор» в 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];
}

По делегату:

- (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.


Скорее всего, вы блокируете основной цикл событий и, таким образом, блокируете анимацию, когда пытаетесь анимировать только по окончании.

Вместо этого установите таймер, который срабатывает через полсекунды и запускает следующую анимацию. Этот таймер может быть сброшен по окончании предыдущей анимации, тем самым уменьшая нагрузку и делая вашу частоту мерцания более регулярной (но вам придется выяснить, что является наиболее подходящим).

Смотрите документацию по классу 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"];




uikit