Анимировать изменение цвета фона на Android
Как вы анимировать изменение цвета фона представления на Android?
например:
У меня есть вид с красным цветом фона. Цвет фона представления изменяется на синий. Как сделать плавный переход между цветами?
Если это не может быть сделано с видом, альтернатива будет приветствоваться.
12 ответов
Я в конечном итоге выяснить (очень хорошее) решение этой проблемы!
можно использовать 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 в .
на этом этапе вы можете инициировать переход в вашем коде по команде делать:
TransitionDrawable transition = (TransitionDrawable) viewObj.getBackground();
transition.startTransition(transitionTime);
или запустите переход в обратном порядке, вызвав:
transition.reverseTransition(transitionTime);
посмотреть Роман для другого решения с использованием API анимации свойств, который не был доступен в то время, когда этот ответ был первоначально опубликован.
вы можете использовать new Свойство Анимации 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 использование девять старых андроидов библиотека от Джейка Уортон.
на getColor
метод был устаревшим в Android M, поэтому у вас есть два варианта:
-
если вы используете библиотеку поддержки, вам нужно заменить
getColor
звонки с:ContextCompat.getColor(this, R.color.red);
-
если вы не используете библиотека поддержки, вам нужно заменить
getColor
звонки с:getColor(R.color.red);
в зависимости от того, как ваш вид получает свой цвет фона и как вы получаете свой целевой цвет есть несколько различных способов сделать это.
первые два использует Анимация Свойств Android основы.
использовать Объект Аниматор если:
- ваш вид имеет свой цвет фона, определенный как
argb
значение в xml-файле. - ваш вид ранее имел свой цвет, установленный
view.setBackgroundColor()
- ваш вид имеет свой цвет фона, определенный в drawable, что НЕ определяет любые дополнительные свойства, такие как ход или угловые радиусы.
- ваш вид имеет свой цвет фона, определенный в drawable, и вы хотите удалить любые дополнительные свойства, такие как штрихи или угловые радиусы, имейте в виду, что удаление дополнительных свойств не будет анимировано.
аниматор объектов работает, вызывая view.setBackgroundColor
который заменяет определенный drawable если это не экземпляр ColorDrawable
, что редко бывает. Это означает, что любые дополнительные свойства фона из drawable как штрих или углы будут удалены.
использовать Аниматор Значение если:
- ваш вид имеет свой цвет фона, определенный в drawable, который также устанавливает свойства, такие как штрихи или угловые радиусы, и вы хотите изменить его на новый цвет, который решается во время работы.
использовать a переход drawable если:
- ваше представление должно переключаться между двумя drawable, которые были определены до развертывания.
у меня были некоторые проблемы с производительностью с переходными чертежами, которые запускаются во время открытия DrawerLayout, который я не смог решить, поэтому, если вы столкнетесь с неожиданным заиканием, Вы можете столкнуться с той же ошибкой, что и я.
вам придется изменить пример аниматора значений, если вы хотите использовать выигрышного StateLists или 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 objectAnimator анимировать фон макета
посмотреть определение:
<View
android:background="@drawable/example"
android:layout_width="50dp"
android:layout_height="50dp"/>
Drawable определение:
<?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"/>
Drawable определение:
<?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.
вы можете сделать аниматор объект. Например, у меня есть targetView, и я хочу изменить цвет фона:
int colorFrom = Color.RED;
int colorTo = Color.GREEN;
int duration = 1000;
ObjectAnimator.ofObject(targetView, "backgroundColor", new ArgbEvaluator(), colorFrom, colorTo)
.setDuration(duration)
.start();
Если вы хотите цветную анимацию, как это,
этот код поможет вам:
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();
еще один простой способ достичь этого-выполнить переход через AlphaAnimation.
- сделайте свой вид ViewGroup
- добавьте дочернее представление к нему по индексу 0 с размерами макета match_parent
- дайте вашему ребенку тот же фон, что и контейнер
- изменить фон контейнера на целевой цвет
- выцветание ребенка с помощью AlphaAnimation.
- удалите ребенка, когда анимация будет завершена (с помощью AnimationListener)
Это метод, который я использую в базовой активности для изменения фона. Я использую 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 setCrossFadeEnabled(true) вызвать нежелательный эффект белого, поэтому мне пришлось переключиться на сплошной цвет для
лучший способ использовать 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();
вот хорошая функция, которая позволяет это:
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();
}
ответ дается многими способами. Вы также можете использовать ofArgb(startColor,endColor)
of 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();
я обнаружил, что реализация используется ArgbEvaluator
в исходном коде Android лучше всего работает при переходе цветов. При использовании HSV, в зависимости от двух цветов, переход прыгал через слишком много оттенков для меня. Но этот метод не работает.
если вы пытаетесь просто анимировать, используйте ArgbEvaluator
С ValueAnimator
как было предложено здесь:
ValueAnimator colorAnimation = ValueAnimator.ofObject(new ArgbEvaluator(), colorFrom, colorTo);
colorAnimation.addUpdateListener(new AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animator) {
view.setBackgroundColor((int) animator.getAnimatedValue());
}
});
colorAnimation.start();
однако, если вы похожи на меня и хотите связать свой переход с каким-либо жестом пользователя или другим значение, переданное с входа,ValueAnimator
не очень помогает (если вы не нацелены на API 22 и выше, в этом случае вы можете использовать ValueAnimator.setCurrentFraction()
метод). При таргетинге ниже API 22 оберните код, найденный в ArgbEvaluator
исходный код в вашем собственном методе, как показано ниже:
public static int interpolateColor(float fraction, int startValue, int endValue) {
int startA = (startValue >> 24) & 0xff;
int startR = (startValue >> 16) & 0xff;
int startG = (startValue >> 8) & 0xff;
int startB = startValue & 0xff;
int endA = (endValue >> 24) & 0xff;
int endR = (endValue >> 16) & 0xff;
int endG = (endValue >> 8) & 0xff;
int endB = endValue & 0xff;
return ((startA + (int) (fraction * (endA - startA))) << 24) |
((startR + (int) (fraction * (endR - startR))) << 16) |
((startG + (int) (fraction * (endG - startG))) << 8) |
((startB + (int) (fraction * (endB - startB))));
}
и использовать его, как вы хотите.
добавить папку аниматор на res. (имя должно быть аниматор). Добавьте файл ресурсов аниматора. Например res / аниматор / fade.в XML
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
<objectAnimator
android:propertyName="backgroundColor"
android:duration="1000"
android:valueFrom="#000000"
android:valueTo="#FFFFFF"
android:startOffset="0"
android:repeatCount="-1"
android:repeatMode="reverse" />
</set>
внутри Java-файла активности, назовите это
View v = getWindow().getDecorView().findViewById(android.R.id.content);
AnimatorSet set = (AnimatorSet) AnimatorInflater.loadAnimator(this, R.animator.fade);
set.setTarget(v);
set.start();