iPhone обеспечивает плавную анимацию с помощью индикатора выполнения - PullRequest
4 голосов
/ 08 июня 2011

Я пытаюсь реализовать простое приложение для викторины на iphone в духе обучения, частью этого приложения является таймер.

Я хочу, чтобы мой таймер отсчитывал от 10 до 0. У меня был простой NSTimer, который повторял и вызывал метод каждую секунду, и в этом методе я обновляю метку, которая отображает оставшееся время, что хорошо работает.

Теперь вместо отображения таймера с использованием метки я хотел использовать графический индикатор выполнения, поэтому я создал десять изображений, одно полное по длине (представляющее 10), следующие 9/10 размера и т. Д., И в Мой метод повторяющегося таймера вместо обновления метки я обновляю UIImage с соответствующим изображением, так что со временем индикатор выполнения становится все меньше и меньше.

Моя проблема в том, что из-за того, как я реализовал индикатор выполнения, он не выглядит очень гладким, когда обновляется каждую секунду. Есть ли другой способ, которым я должен подходить к разработке такого рода функциональности? Я слышал, что вы можете использовать растягиваемое изображение, чтобы получить более плавный эффект, но я не смог увидеть хороших примеров этого.

Любые советы и примеры кода приветствуются, просто пытаюсь узнать здесь.

Ответы [ 3 ]

5 голосов
/ 11 июня 2011

После изучения нескольких вариантов я решил использовать UIProgressView (предложенный sudo в комментариях) в сочетании с NSTimer, который обновляет прогресс десять раз в секунду в течение десяти секунд, я использовал это решение, потому что:

  1. Это стандартный элемент, предоставленный яблоком.
  2. Эта опция не требует дополнительных затрат на создание и загрузку 100 изображений (как предложил Криптон в комментариях).
  3. С помощью NSTimer я могу добавить проверку в функцию updateProgressBar, чтобы добавить некоторую обратную связь с пользователем, когда таймер достигает низкого уровня, например, вибрация в течение последних трех секунд и т. Д. (Используя анимацию, я бы не сталиспользуйте эту опцию).

Используя приведенный ниже код, предположим, что у меня есть переменная UIProgressView с именем «progressView», NSTimer с именем «timer» и переменная с плавающей точкой с именем «time», тогда:

-(void)updateProgressBar
{
    if(time <= 0.0f)
    {
        //Invalidate timer when time reaches 0
        [timer invalidate];
    }
    else
    {
        time -= 0.01;
        progressView.progress = time;
    }
}

-(void)animateProgressView2
{
    progressView.progress = 1;
    time = 1;
    timer = [NSTimer scheduledTimerWithTimeInterval: 0.1f
                                             target: self
                                           selector: @selector(updateProgressBar)
                                           userInfo: nil
                                            repeats: YES];
}

Другой способ, которым я исследовал (после просмотра комментариев Диско), но решил не использовать анимацию.В этом случае я создал два png-изображения с именами «redbar.png» и «greenbar.png», идея которых заключается в том, что они будут размещены друг над другом (зеленая полоса находится сверху / на переднем плане) и на протяжениианимация, когда зеленая полоса сжимается, показывая красную полосу на заднем плане.

UIImage *green= [UIImage imageNamed:@"greenbar.png"];
UIImage *red= [UIImage imageNamed:@"redbar.png"];

redBar.image = red; // allocate the red image to the UIImageView
redBar.frame = CGRectMake(20,250,220,30);// set the size of the red image

greenBar.image = green; // allocate the green image to the UIImageView
greenBar.frame = CGRectMake(20,250,220,30);//set the size of the green image

[UIView beginAnimations:nil context:nil];
[UIView setAnimationDelegate:self];
[UIView setAnimationDuration:10]; //the time you want the animation to last for
[UIView setAnimationDidStopSelector:@selector(animationFinished)];//the method to be called once the animation is finished
    //at the end of the animation we want the greenBar frame to disappear
    greenBar.frame = CGRectMake(20,250,0,30);
[UIView commitAnimations];

Идеальным решением было бы объединить UIProgressView и блок UIAnimation, но в настоящее время это не вариант (см. этот вопрос оживить изменения UIProgressView ).

Надеюсь, это поможет кому-то в будущем.

EDIT ::

Похоже, идеальное решение, о котором я упоминал выше, теперь доступно в iOS5, взято с эталонного сайта Apple:

setProgress: animated: регулирует текущий прогресс, отображаемый приемником, при желании анимируя изменения.

  • (void) setProgress: (float) анимированный прогресс: (BOOL) animated
1 голос
/ 08 июня 2011

Может быть не то, что вы ищете, но может помочь вам. Почему бы не иметь UIImageView с вашим изображением в полном размере, а затем применить к нему UIView анимацию в течение заданного времени? Таким образом, сжатие будет плавным.

UIImageView *imageView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"YourImage.png"]];
imageView.frame = CGRectMake(0,0,320,30);//starts big
[self.view addSubview:imageView];
[UIView beginAnimations:@"Progress Bar Animation" Context:nil];
[UIView setAnimationDuration:10]; //whatever time you want
imageView.frame = CGRectMake(0,0,10,30);//ends small
[UIView commitAnimations];

Это может быть то, что вы ищете, я не уверен. Просто кажется немного проще, чем использовать десять разных изображений.

0 голосов
/ 03 февраля 2016

Я сделал, увеличив прогресс в настройке с (0,01 - 1,00) до (0,001 - 1000) и уменьшив разницу во времени между значениями прогресса в настройке.

Вот мой приведенный ниже код с тремя разными скоростями анимации.

 -(void)setProgressViewProgress
{
    //Check for completion
    if(progress > 1.0)
    {
        [self progressCompleted];
        return;
    }
    //Diffrent speed for range
    CGFloat speed;
    //From 0.000 to 0.500 speed is 500*0.007 = 3.5 seconds    0.007(sec) => x(sec) = Total time in range(sec) / 500.0 ==> 3.5/500.0 = 0.07
    if(progress<0.50)
    {
        speed = 0.007;
    }
    //From 0.500 to 0.750 speed is 250*0.005 = 1.25 seconds 0.005(sec) => x(sec) = Total time in range(sec) / 500.0 ==> 1.25/250.0 = 0.05
    else if(progress<0.75)
    {
        speed = 0.005;
    }
    //From 0.750 to 1.0 speed is 250*0.002 = 0.5 seconds 0.002(sec) => x(sec) = Total time in range(sec) / 500.0 ==> 0.5/250.0 = 0.02
    else
    {
        speed = 0.002;
    }
    //Increase the progress view by 1/1000  for smooth animation
    progress+=0.001;
    [progressView setProgress:progress];
    [self performSelector:@selector(setProgressViewProgress) withObject:nil afterDelay:speed];
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...