2013-09-15 4 views
0

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

В качестве справки, взгляните на this app.

EDIT: Я попытался с помощью ObjectAnimator и ArgbEvaluator в цикле с 3 вторым переходным периодом, но на экране продолжает мигать в стробоскопе таким образом, что будет просто дать вам головную боль. Кроме того, цвета меняются просто отлично, а все остальное прекрасно. Может ли кто-нибудь запустить это и посмотреть, что может пойти не так?

public class Main extends Activity { 

public int color1, color2, red1, red2, blue1, blue2, green1, green2; 

@Override 
protected void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 
    requestWindowFeature(Window.FEATURE_NO_TITLE); 
    setContentView(R.layout.main); 


    new Thread() { 
     public void run() { 
      while(true) { 
       try { 
        Thread.sleep(3000); // I've also tried 1000 and 4000, same issue. 
       } catch (InterruptedException e) { 
        e.printStackTrace(); 
       } 
       Main.this.runOnUiThread(new Runnable() { 
        public void run() { 

        //generate color 1 
         red1 = (int)(Math.random() * 128 + 127); 
         green1 = (int)(Math.random() * 128 + 127); 
         blue1 = (int)(Math.random() * 128 + 127); 
         color1 = 0xff << 24 | (red1 << 16) | 
           (green1 << 8) | blue1; 


        //generate color 2 

         red2 = (int)(Math.random() * 128 + 127); 
         green2 = (int)(Math.random() * 128 + 127); 
         blue2 = (int)(Math.random() * 128 + 127); 
         color2 = 0xff << 24 | (red2 << 16) | 
           (green2 << 8) | blue2; 

        //start animation 
         View v = findViewById(R.id.view); 
         ObjectAnimator anim = ObjectAnimator.ofInt(v, "backgroundColor", color1, color2); 


         anim.setEvaluator(new ArgbEvaluator()); 
         anim.setRepeatCount(ValueAnimator.INFINITE); 
         anim.setRepeatMode(ValueAnimator.REVERSE); 
         anim.setDuration(3000); 
         anim.start(); 

        } 
       }); 
      } 
     } 
    }.start(); 
} 

}

EDIT: Я сузил и нашел ".setRepeatMode" вызывают проблемы. У меня все еще нет исправления. Изменяя «Реверс» на что-то еще (бесконечные или другие предоставленные опции), это предотвращает анимацию. Любая идея, что я могу сделать, чтобы исправить это?

ТАКЖЕ, знает ли кто-нибудь лучший способ генерации более ярких цветов? Все, что я искал, устарело.

+0

Что происходит, когда вы запускаете этот код? – Prmths

+0

Эта нить плюс реверсирование анимации не будет слишком хорошо. Посмотрите на это и посмотрите, хотите ли вы https://gist.github.com/luksprog/6673439. – Luksprog

ответ

5

Вы делаете все правильно, за исключением одной вещи: каждые 3 секунды вы произвольно генерируете цветов. Таким образом, это то, что происходит:

первой итерации:

цвет1 генерируется

цвет2 генерируется

фон View установлен в цвет1. А затем фон меняет от color1 до color2.

// Все хорошо

второй итерации:

Там новый цвет1

Там новый цвет2

фон View установлен на новый цвет1. Непосредственное изменение вызывает световой эффект строба. А затем фон меняется с нового color1 на новый цвет2.

Что вы должны сделать, чтобы исправить это:

@Override 
protected void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 
    requestWindowFeature(Window.FEATURE_NO_TITLE); 
    setContentView(R.layout.main); 

    // Generate color1 before starting the thread 
    red1 = (int)(Math.random() * 128 + 127); 
    green1 = (int)(Math.random() * 128 + 127); 
    blue1 = (int)(Math.random() * 128 + 127); 
    color1 = 0xff << 24 | (red1 << 16) | 
          (green1 << 8) | blue1; 


    new Thread() { 
     public void run() { 
      while(true) { 
       try { 
        Thread.sleep(3000); 
       } catch (InterruptedException e) { 
        e.printStackTrace(); 
       } 
       Main.this.runOnUiThread(new Runnable() { 
        public void run() { 

        //generate color 2 

         red2 = (int)(Math.random() * 128 + 127); 
         green2 = (int)(Math.random() * 128 + 127); 
         blue2 = (int)(Math.random() * 128 + 127); 
         color2 = 0xff << 24 | (red2 << 16) | 
           (green2 << 8) | blue2; 

        //start animation 
         View v = findViewById(R.id.view); 
         ObjectAnimator anim = ObjectAnimator.ofInt(v, "backgroundColor", color1, color2); 


         anim.setEvaluator(new ArgbEvaluator()); 
         anim.setRepeatCount(ValueAnimator.INFINITE); 
         anim.setRepeatMode(ValueAnimator.REVERSE); 
         anim.setDuration(3000); 
         anim.start(); 

         // Now set color1 to color2 
         // This way, the background will go from 
         // the previous color to the next color 
         // smoothly 
         color1 = color2; 

        } 
       }); 
      } 
     } 
    }.start(); 
} 

Таким образом, со второй итерации года, исходный цвет должен быть таким же, как цвет, заканчивающийся на предыдущей итерации. Инициализировать/генерировать цвет1 только один раз: перед запуском потока. После anim.start(), добавьте:

color1 = color2; 

Кроме того, заметьте, что вы создаете новый ObjectAnimatorкаждые 3 секунды:

ObjectAnimator anim = ObjectAnimator.ofInt(v, "backgroundColor", color1, color2); 

Итак, следующие утверждения имеют никакого эффекта:

anim.setRepeatCount(ValueAnimator.INFINITE); 
anim.setRepeatMode(ValueAnimator.REVERSE); 

Вот что я рекомендую:

public class Main extends Activity { 

    public int color1, color2, red1, red2, blue1, blue2, green1, green2; 

    View v; 

    ObjectAnimator anim; 

    @Override 
    protected void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     requestWindowFeature(Window.FEATURE_NO_TITLE); 
     setContentView(R.layout.main); 

     // White or whatever color background R.id.view 
     // has at the beginning 
     color1 = 0xffffffff; 

     v = findViewById(R.id.llMain); 

     // We haven't initialized color2 yet. Will set this later 
     anim = ObjectAnimator.ofInt(v, "backgroundColor", color1); 

     anim.setEvaluator(new ArgbEvaluator()); 

     anim.setDuration(3000); 


     new Thread() { 
      public void run() { 
       while(true) { 
        try { 
         Thread.sleep(3000); 
        } catch (InterruptedException e) { 
         e.printStackTrace(); 
        } 
        Main.this.runOnUiThread(new Runnable() { 
         public void run() { 

          //generate color 2 

          red2 = (int)(Math.random() * 128 + 127); 
          green2 = (int)(Math.random() * 128 + 127); 
          blue2 = (int)(Math.random() * 128 + 127); 
          color2 = 0xff << 24 | (red2 << 16) | 
            (green2 << 8) | blue2; 

          // Update the color values 
          anim.setIntValues(color1, color2); 

          anim.start(); 

          // Order the colors 
          color1 = color2; 

         } 
        }); 
       } 
      } 
     }.start(); 
    } 
} 

Таким образом вы создаете объект ObjectAnimator один раз и обновляете значения цвета каждые 3 секунды.

+0

Спасибо за качественный ответ, он работает! Я награду щедростью, когда это позволит мне за 33 минуты. –

+1

Награда Bounty - еще раз спасибо. –

+1

@Collin Добро пожаловать. Это самая быстрая раздача, которую я видел. Спасибо. – Vikram

2

Как об использовании ObjectAnimator w/ArgbEvaluator. Используя ObjectAnimator, вы можете легко анимировать любое свойство, если объект имеет правильный метод настройки в случае верблюда (в виде set()). В вашем случае, View имеет setBackgroundColor, так что вы можете попробовать это:

View v = findViewById(R.id.mask2); 
ObjectAnimator anim = ObjectAnimator.ofInt(v, "backgroundColor", Color.RED, Color.BLUE); 
anim.setDuration(3000); 
anim.setEvaluator(new ArgbEvaluator()); 
anim.setRepeatCount(ValueAnimator.INFINITE); 
anim.setRepeatMode(ValueAnimator.REVERSE); 
anim.start(); 

Для более общего описания & подробно об анимации свойств:

http://developer.android.com/guide/topics/graphics/prop-animation.html#object-animator

К сожалению, этот новый АФИ поддерживается только API11 +, поэтому, если вы касаетесь проблемы совместимости, вы можете попробовать использовать библиотеку NineOldAndroids, написанную JakeWharton.

+0

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

+1

Я сузил его и обнаружил, что «.setRepeatMode» вызывает проблему. У меня все еще нет исправления, изменив «Реверс» на что-то еще, что предотвращает анимацию. Есть предположения? –

0

Еще одна альтернатива, как изменить цвет фона;

ColorDrawable[] color = { new ColorDrawable(Color.RED), new ColorDrawable(Color.WHITE) }; 
    TransitionDrawable trans = new TransitionDrawable(color); 
    view.setBackgroundDrawable(trans); 
    trans.startTransition(3000); 

Этот подход также имеет методы, такие как trans.reverseTransition (duration).

Смежные вопросы