Анимация изменения цвета фонового изображения на Android
Как вы можете изменить цвет фона на Android?
Например:
У меня есть вид с красным цветом фона. Цвет фона в представлении меняется на синий. Как я могу сделать плавный переход между цветами?
Если это невозможно сделать с представлениями, будет приветствоваться альтернатива.
Ответы
Ответ 1
Я решил выяснить (довольно хорошее) решение этой проблемы!
Для этого вы можете использовать TransitionDrawable. Например, в файле XML в выпадающей папке вы можете написать что-то вроде:
<?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 анимации свойств, который не был доступен в момент, когда этот ответ был первоначально опубликован.
Ответ 2
Вы можете использовать новую 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 используйте Девять старых андроидов библиотеки от Джейка Уортона.
Метод getColor
устарел в Android M, поэтому у вас есть два варианта:
-
Если вы используете библиотеку поддержки, вам нужно заменить вызовы getColor
на:
ContextCompat.getColor(this, R.color.red);
-
если вы не используете библиотеку поддержки, вам необходимо заменить вызовы getColor
на:
getColor(R.color.red);
Ответ 3
В зависимости от того, как ваш вид получает свой цвет фона и как вы получаете целевой цвет, есть несколько способов сделать это.
Первые два используют инфраструктуру Android Animation.
Используйте Object Animator, если:
- В вашем представлении цвет фона определяется как значение
argb
в XML файле.
- У вашего представления ранее был установлен цвет
view.setBackgroundColor()
- У вашего представления есть свой фоновый цвет, определенный в чертеже, который НЕ ДЕЛАЕТ определяет любые дополнительные свойства, такие как радиус удара или угол.
- В вашем представлении есть свой фоновый цвет, определенный в чертеже, и вы хотите удалить любые дополнительные свойства, такие как ударные или угловые радиусы, помните, что удаление дополнительных свойств не будет анимировано.
Аниматор объектов работает, вызывая view.setBackgroundColor
, который заменяет определенный drawable, если это не экземпляр ColorDrawable
, который он редко бывает. Это означает, что любые дополнительные фоновые свойства из рисунка, такого как ход или углы, будут удалены.
Используйте Value Animator, если:
- В вашем представлении есть свой фоновый цвет, определенный в drawable, который также устанавливает свойства, такие как радиус штриха или угла И вы хотите изменить его на новый цвет, который определяется во время работы.
Используйте переходный вариант, если:
- Ваше представление должно переключаться между двумя доступными, которые были определены до развертывания.
У меня были некоторые проблемы с производительностью с помощью переходов, которые выполняются, когда я открываю 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 objectAnimator animate backgroundColor of Layout
Value Animator:
Просмотр определения:
<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.
Ответ 4
Вы можете создать объектный аниматор. Например, у меня есть targetView, и я хочу изменить цвет фона:
int colorFrom = Color.RED;
int colorTo = Color.GREEN;
int duration = 1000;
ObjectAnimator.ofObject(targetView, "backgroundColor", new ArgbEvaluator(), colorFrom, colorTo)
.setDuration(duration)
.start();
Ответ 5
Если вам нужна цветная анимация, как эта,
![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();
Ответ 6
Другим простым способом добиться этого является выполнение затухания с использованием AlphaAnimation.
- Сделайте вид ViewGroup
- Добавьте дочерний вид к нему с индексом 0, с параметрами макета match_parent
- Дайте вашему ребенку тот же фон, что и контейнер
- Изменить на фон контейнера на целевой цвет
- Затушить ребенка с помощью AlphaAnimation.
- Удалить анимацию после завершения анимации (используя AnimationListener)
Ответ 7
Лучший способ - использовать 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.setBackgroundColor(ColorUtils.blendARGB(Color.parseColor("#FFFFFF")
, Color.parseColor("#000000")
, fractionAnim));
}
});
valueAnimator.start();
Ответ 8
Это метод, который я использую в базовой операции для изменения фона. Я использую 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);
}
}
}
update: В случае, если кто-то работает с той же проблемой, я обнаружил, что по какой-то причине Android < 4.3 с использованием setCrossFadeEnabled(true)
вызывает нежелательный эффект белого, поэтому мне пришлось переключиться на сплошной цвет для < 4.3, использу метод @Roman Minenok ValueAnimator, отмеченный выше.
Ответ 9
Ответ дается во многих отношениях. Вы также можете использовать 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();
Ответ 10
Вот хорошая функция, которая позволяет это:
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();
}
Ответ 11
добавьте папку аниматора в папку res. (имя должно быть аниматором). Добавьте файл ресурсов аниматора. Например, res/animator/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 файла Activity, позвоните по этому
View v = getWindow().getDecorView().findViewById(android.R.id.content);
AnimatorSet set = (AnimatorSet) AnimatorInflater.loadAnimator(this, R.animator.fade);
set.setTarget(v);
set.start();
Ответ 12
Я обнаружил, что реализация, используемая 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))));
}
И используйте его, как хотите.
Ответ 13
Документация по анимации на основе XML ужасна. Я искал около часа, чтобы анимировать цвет фона кнопки при нажатии... Печально то, что анимация находится всего в одном атрибуте: вы можете использовать exitFadeDuration
в selector
:
<selector xmlns:android="http://schemas.android.com/apk/res/android"
android:exitFadeDuration="200">
<item android:state_pressed="true">
<shape android:tint="#3F51B5" />
</item>
<item>
<shape android:tint="#F44336" />
</item>
</selector>
Тогда просто используйте его как background
для вашего обзора. Код Java/Kotlin не требуется.