Анимировать изменение цвета фона просмотра на Android - PullRequest
302 голосов
/ 10 апреля 2010

Как вы анимируете изменение цвета фона представления на Android?

Например:

У меня есть вид с красным фоном. Цвет фона представления меняется на синий. Как я могу сделать плавный переход между цветами?

Если это невозможно сделать с представлениями, альтернатива будет приветствоваться.

Ответы [ 12 ]

461 голосов
/ 23 января 2013

Вы можете использовать новый Property Animation Api для цветной анимации:

int colorFrom = getResources().getColor(R.color.red);
int colorTo = getResources().getColor(R.color.blue);
ValueAnimator colorAnimation = ValueAnimator.ofObject(new ArgbEvaluator(), colorFrom, colorTo);
colorAnimation.setDuration(250); // milliseconds
colorAnimation.addUpdateListener(new AnimatorUpdateListener() {

    @Override
    public void onAnimationUpdate(ValueAnimator animator) {
        textView.setBackgroundColor((int) animator.getAnimatedValue());
    }

});
colorAnimation.start();

Для обратной совместимости с Android 2.x используйте Библиотека девяти старых Android от Джейка Уортона.

Метод getColor устарел в Android M, поэтому у вас есть два варианта:

  • Если вы используете библиотеку поддержки, вам нужно заменить вызовы getColor на:

    ContextCompat.getColor(this, R.color.red);
    
  • если вы не используете библиотеку поддержки, вам нужно заменить вызовы getColor на:

    getColor(R.color.red);
    
345 голосов
/ 09 июля 2010

В итоге я нашел (довольно хорошее) решение этой проблемы!

Вы можете использовать TransitionDrawable для этого. Например, в файле XML в папке drawable вы можете написать что-то вроде:

<?xml version="1.0" encoding="UTF-8"?>
<transition xmlns:android="http://schemas.android.com/apk/res/android">
    <!-- The drawables used here can be solid colors, gradients, shapes, images, etc. -->
    <item android:drawable="@drawable/original_state" />
    <item android:drawable="@drawable/new_state" />
</transition>

Затем в вашем XML для фактического представления вы бы указали на этот TransitionDrawable в атрибуте android:background.

На этом этапе вы можете инициировать переход в своем коде по команде, выполнив:

TransitionDrawable transition = (TransitionDrawable) viewObj.getBackground();
transition.startTransition(transitionTime);

Или запустите переход в обратном порядке, вызвав:

transition.reverseTransition(transitionTime);

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

127 голосов
/ 10 сентября 2013

В зависимости от того, как ваш вид получает цвет фона и как вы получаете целевой цвет, есть несколько разных способов сделать это.

Первые два используют Android Property Animation framework.

Использовать Аниматор объектов , если:

  • Цвет вашего представления определен как значение argb в файле XML.
  • Цвет вашего просмотра ранее был установлен на view.setBackgroundColor()
  • Ваш вид имеет цвет фона, заданный в чертеже, который НЕ определяет любые дополнительные свойства, такие как радиус обводки или угла.
  • Цвет вашего вида определен в виде отрисовки, и вы хотите удалить любые дополнительные свойства, такие как радиус обводки или угла, имейте в виду, что удаление дополнительных свойств не будет анимированным.

Аниматор объектов работает, вызывая view.setBackgroundColor, который заменяет определенный объект рисования, если только он не является экземпляром ColorDrawable, которым он редко является. Это означает, что любые дополнительные свойства фона из таких объектов, как обводка или углы, будут удалены.

Использовать Значение аниматора , если:

  • Ваш вид имеет цвет фона, заданный в чертеже, который также устанавливает свойства, такие как обводка или угловые радиусы, и вы хотите изменить его на новый цвет, который определяется во время работы.

Использовать Переходный чертеж , если:

  • Ваше представление должно переключаться между двумя объектами рисования, которые были определены до развертывания.

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

Вам придется изменить пример Value Animator, если вы хотите использовать StateLists drawable или LayerLists drawable , в противном случае произойдет сбой в строке final GradientDrawable background = (GradientDrawable) view.getBackground();.

Аниматор объектов :

Просмотр определения:

<View
    android:background="#FFFF0000"
    android:layout_width="50dp"
    android:layout_height="50dp"/>

Создайте и используйте ObjectAnimator, как это.

final ObjectAnimator backgroundColorAnimator = ObjectAnimator.ofObject(view,
                                                                       "backgroundColor",
                                                                       new ArgbEvaluator(),
                                                                       0xFFFFFFFF,
                                                                       0xff78c5f9);
backgroundColorAnimator.setDuration(300);
backgroundColorAnimator.start();

Вы также можете загрузить определение анимации из xml с помощью AnimatorInflater, как это делает XMight в Android-объектAnimator animate backgroundColor of Layout

Значение аниматора :

Просмотр определения:

<View
    android:background="@drawable/example"
    android:layout_width="50dp"
    android:layout_height="50dp"/>

Рисуемое определение:

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
    <solid android:color="#FFFFFF"/>
    <stroke
        android:color="#edf0f6"
        android:width="1dp"/>
    <corners android:radius="3dp"/>

</shape>

Создайте и используйте ValueAnimator следующим образом:

final ValueAnimator valueAnimator = ValueAnimator.ofObject(new ArgbEvaluator(),
                                                           0xFFFFFFFF,
                                                           0xff78c5f9);

final GradientDrawable background = (GradientDrawable) view.getBackground();
currentAnimation.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {

    @Override
    public void onAnimationUpdate(final ValueAnimator animator) {
        background.setColor((Integer) animator.getAnimatedValue());
    }

});
currentAnimation.setDuration(300);
currentAnimation.start();

Переходный чертеж :

Просмотр определения:

<View
    android:background="@drawable/example"
    android:layout_width="50dp"
    android:layout_height="50dp"/>

Рисуемое определение:

<?xml version="1.0" encoding="utf-8"?>
<transition xmlns:android="http://schemas.android.com/apk/res/android">
    <item>
        <shape>
            <solid android:color="#FFFFFF"/>
            <stroke
                android:color="#edf0f6"
                android:width="1dp"/>
            <corners android:radius="3dp"/>
        </shape>
    </item>

    <item>
        <shape>
            <solid android:color="#78c5f9"/>
            <stroke
                android:color="#68aff4"
                android:width="1dp"/>
            <corners android:radius="3dp"/>
        </shape>
    </item>
</transition>

Используйте TransitionDrawable следующим образом:

final TransitionDrawable background = (TransitionDrawable) view.getBackground();
background.startTransition(300);

Вы можете отменить анимацию, вызвав .reverse() в экземпляре анимации.

Существуют и другие способы создания анимации, но эти три, вероятно, являются наиболее распространенными. Я обычно использую ValueAnimator.

52 голосов
/ 06 сентября 2014

Вы можете сделать объект аниматором. Например, у меня есть targetView, и я хочу изменить цвет фона:

int colorFrom = Color.RED;
int colorTo = Color.GREEN;
int duration = 1000;
ObjectAnimator.ofObject(targetView, "backgroundColor", new ArgbEvaluator(), colorFrom, colorTo)
    .setDuration(duration)
    .start();
19 голосов
/ 23 декабря 2015

Если вы хотите цветную анимацию, как это,

Enter image description here

этот код поможет вам:

ValueAnimator anim = ValueAnimator.ofFloat(0, 1);   
anim.setDuration(2000);

float[] hsv;
int runColor;
int hue = 0;
hsv = new float[3]; // Transition color
hsv[1] = 1;
hsv[2] = 1;
anim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {

    @Override
    public void onAnimationUpdate(ValueAnimator animation) {

        hsv[0] = 360 * animation.getAnimatedFraction();

        runColor = Color.HSVToColor(hsv);
        yourView.setBackgroundColor(runColor);
    }
});

anim.setRepeatCount(Animation.INFINITE);

anim.start();
11 голосов
/ 26 апреля 2012

Еще один простой способ добиться этого - выполнить затухание с помощью AlphaAnimation.

  1. Сделайте ваш просмотр ViewGroup
  2. Добавить дочернее представление к нему с индексом 0, с размерами компоновки match_parent
  3. Дайте вашему ребенку тот же фон, что и у контейнера
  4. Изменить цвет фона контейнера на целевой цвет
  5. Исчезновение ребенка с помощью AlphaAnimation.
  6. Удалите дочерний элемент после завершения анимации (используя AnimationListener)
9 голосов
/ 24 октября 2017

лучший способ - использовать ValueAnimator и ColorUtils.blendARGB

 ValueAnimator valueAnimator = ValueAnimator.ofFloat(0.0f, 1.0f);
 valueAnimator.setDuration(325);
 valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
        @Override
        public void onAnimationUpdate(ValueAnimator valueAnimator) {

              float fractionAnim = (float) valueAnimator.getAnimatedValue();

              view.setColorBackground(ColorUtils.blendARGB(Color.parseColor("#FFFFFF")
                                    , Color.parseColor("#000000")
                                    , fractionAnim));
        }
});
valueAnimator.start();
9 голосов
/ 09 июля 2014

Это метод, который я использую в Базовом занятии для изменения фона. Я использую GradientDrawables, сгенерированные в коде, но могут быть адаптированы для соответствия.

    protected void setPageBackground(View root, int type){
        if (root!=null) {
            Drawable currentBG = root.getBackground();
            //add your own logic here to determine the newBG 
            Drawable newBG = Utils.createGradientDrawable(type); 
            if (currentBG==null) {
                if(Build.VERSION.SDK_INT<Build.VERSION_CODES.JELLY_BEAN){
                    root.setBackgroundDrawable(newBG);
                }else{
                    root.setBackground(newBG);
                }
            }else{
                TransitionDrawable transitionDrawable = new TransitionDrawable(new Drawable[]{currentBG, newBG});
                transitionDrawable.setCrossFadeEnabled(true);
                if(Build.VERSION.SDK_INT<Build.VERSION_CODES.JELLY_BEAN){
                     root.setBackgroundDrawable(transitionDrawable);
                }else{
                    root.setBackground(transitionDrawable);
                }
                transitionDrawable.startTransition(400);
            }
        }
    }

обновление: В случае, если кто-то столкнется с той же проблемой, которую я обнаружил, по какой-то причине на Android <4.3 использование <code>setCrossFadeEnabled(true) вызывает нежелательный белый эффект, поэтому мне пришлось переключиться на сплошной цвет для < 4.3 с использованием метода @Roman Minenok ValueAnimator, описанного выше.

5 голосов
/ 03 февраля 2018

Ответ дается во многих отношениях. Вы также можете использовать ofArgb(startColor,endColor) из ValueAnimator.

для API> 21:

int cyanColorBg = ContextCompat.getColor(this,R.color.cyan_bg);
int purpleColorBg = ContextCompat.getColor(this,R.color.purple_bg);

ValueAnimator valueAnimator = ValueAnimator.ofArgb(cyanColorBg,purpleColorBg);
        valueAnimator.setDuration(500);
        valueAnimator.setInterpolator(new LinearInterpolator());
        valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
              @Override
              public void onAnimationUpdate(ValueAnimator valueAnimator) {
                   relativeLayout.setBackgroundColor((Integer)valueAnimator.getAnimatedValue());
              }
        });
        valueAnimator.start();
4 голосов
/ 30 апреля 2014

Вот хорошая функция, которая позволяет это:

public static void animateBetweenColors(final View viewToAnimateItBackground, final int colorFrom, final int colorTo,
        final int durationInMs) {
    final ValueAnimator colorAnimation = ValueAnimator.ofObject(new ArgbEvaluator(), colorFrom, colorTo);
    colorAnimation.addUpdateListener(new AnimatorUpdateListener() {
        ColorDrawable colorDrawable = new ColorDrawable(colorFrom);

        @Override
        public void onAnimationUpdate(final ValueAnimator animator) {
            colorDrawable.setColor((Integer) animator.getAnimatedValue());
            viewToAnimateItBackground.setBackgroundDrawable(colorDrawable);
        }
    });
    if (durationInMs >= 0)
        colorAnimation.setDuration(durationInMs);
    colorAnimation.start();
}
...