Android에서 뷰의 배경색 변경을 어떻게 애니메이션합니까?
예를 들면 다음과 같습니다.
빨간색 배경색으로 볼 수 있습니다. 뷰의 배경색이 파란색으로 바뀝니다. 색상 간을 부드럽게 전환하려면 어떻게해야합니까?
뷰를 사용하여이 작업을 수행 할 수없는 경우 다른 방법을 환영합니다.
Android에서 뷰의 배경색 변경을 어떻게 애니메이션합니까?
예를 들면 다음과 같습니다.
빨간색 배경색으로 볼 수 있습니다. 뷰의 배경색이 파란색으로 바뀝니다. 색상 간을 부드럽게 전환하려면 어떻게해야합니까?
뷰를 사용하여이 작업을 수행 할 수없는 경우 다른 방법을 환영합니다.
답변:
나는이 문제에 대한 (꽤 좋은) 해결책을 알아 냈습니다!
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에서 android:background
속성 에서이 TransitionDrawable을 참조 합니다.
이 시점에서 다음을 수행하여 명령에 따라 코드 전환을 시작할 수 있습니다.
TransitionDrawable transition = (TransitionDrawable) viewObj.getBackground();
transition.startTransition(transitionTime);
또는 다음을 호출하여 전환을 반대로 실행하십시오.
transition.reverseTransition(transitionTime);
이 답변이 처음 게시 된 시점에는 사용할 수 없었던 Property Animation API를 사용하는 다른 솔루션에 대한 Roman의 답변 을 참조하십시오 .
컬러 애니메이션에 새로운 속성 애니메이션 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와의 호환성을 위해 Jake Wharton의 Nine Old Androids 라이브러리 를 사용하십시오 .
이 getColor
방법은 Android M에서 더 이상 사용되지 않으므로 다음 두 가지 중에서 선택할 수 있습니다.
지원 라이브러리를 사용하는 경우 getColor
통화를 다음과 같이 바꿔야합니다 .
ContextCompat.getColor(this, R.color.red);
지원 라이브러리를 사용하지 않는 경우 getColor
통화를 다음과 같이 바꿔야합니다 .
getColor(R.color.red);
ValueAnimator.ofArgb(colorFrom, colorTo)
요점을 더 잘 보지만 슬프게도 새로운 것입니다.
뷰의 배경색을 얻는 방법과 대상 색을 얻는 방법에 따라 여러 가지 방법이 있습니다.
처음 두 개는 Android 속성 애니메이션 프레임 워크를 사용합니다 .
다음과 같은 경우 Object Animator를 사용하십시오 .
argb
이 xml 파일 의 값으로 정의되어 있습니다.view.setBackgroundColor()
객체 애니메이터 view.setBackgroundColor
는 정의 된 드로어 블 ColorDrawable
이 거의 인스턴스가 아닌 한 정의 된 드로어 블을 대체하여 호출 하여 작동 합니다 . 즉, 획 또는 모서리와 같은 드로어 블의 추가 배경 속성이 제거됩니다.
다음과 같은 경우 Value Animator를 사용하십시오 .
다음과 같은 경우 전환 드로어 블을 사용하십시오 .
해결할 수 없었던 DrawerLayout을 여는 동안 실행되는 전환 드로어 블과 관련된 성능 문제가 발생했습니다. 따라서 예기치 않은 말더듬이 발생하면 같은 버그가 발생했을 수 있습니다.
StateList 드로어 블 또는 LayerLists 드로어 블 을 사용하려면 Value Animator 예제를 수정해야합니다 . 그렇지 않으면 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();
XMight가 Android 객체 에서하는 것과 같은 AnimatorInflater를 사용하여 XML에서 애니메이션 정의를로드 할 수도 있습니다.
가치 애니메이터 :
정의보기 :
<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를 사용합니다.
객체 애니메이터를 만들 수 있습니다. 예를 들어 targetView가 있고 배경색을 변경하고 싶습니다.
int colorFrom = Color.RED;
int colorTo = Color.GREEN;
int duration = 1000;
ObjectAnimator.ofObject(targetView, "backgroundColor", new ArgbEvaluator(), colorFrom, colorTo)
.setDuration(duration)
.start();
ofArgb(targetView, "backgroundColor", colorFrom, colorTo)
. 구현은 단지 ofInt(...).setEvaluator(new ArgbEvaluator())
입니다.
이와 같은 컬러 애니메이션을 원한다면
이 코드는 당신을 도울 것입니다 :
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();
anim.setRepeatCount(ValueAnimator.INFINITE);
동일하지 않습니다. 현재는 동일하지만 보장 할 사항은 없습니다.
가장 좋은 방법은 사용하는 것입니다 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();
이것이 기본 활동에서 배경을 변경하는 데 사용하는 방법입니다. 코드로 생성 된 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);
}
}
}
업데이트 : 내가 발견 한 동일한 문제가 setCrossFadeEnabled(true)
발생하는 경우 안드로이드 <4.3에서 어떤 이유로 인해 바람직하지 않은 화이트 아웃 효과가 발생하므로 위에서 언급 한 @Roman Minenok ValueAnimator 방법을 사용하여 <4.3의 단색으로 전환해야했습니다.
답변은 여러 가지 방법으로 제공됩니다. 당신은 또한 사용할 수 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();
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 코드가 필요하지 않습니다.
android:enterFadeDuration
또한 필요할 수도 있습니다. 내 경험은 그것 없이는 내 애니메이션이 두 번째로 작동하지 않았다는 것입니다.
이를 가능하게하는 멋진 기능이 있습니다.
public static void animateBetweenColors(final @NonNull View viewToAnimateItsBackground, final int colorFrom,
final int colorTo, final int durationInMs) {
final ColorDrawable colorDrawable = new ColorDrawable(durationInMs > 0 ? colorFrom : colorTo);
ViewCompat.setBackground(viewToAnimateItsBackground, colorDrawable);
if (durationInMs > 0) {
final ValueAnimator colorAnimation = ValueAnimator.ofObject(new ArgbEvaluator(), colorFrom, colorTo);
colorAnimation.addUpdateListener(animator -> {
colorDrawable.setColor((Integer) animator.getAnimatedValue());
ViewCompat.setBackground(viewToAnimateItsBackground, colorDrawable);
});
colorAnimation.setDuration(durationInMs);
colorAnimation.start();
}
}
그리고 코 틀린에서 :
@JvmStatic
fun animateBetweenColors(viewToAnimateItsBackground: View, colorFrom: Int, colorTo: Int, durationInMs: Int) {
val colorDrawable = ColorDrawable(if (durationInMs > 0) colorFrom else colorTo)
ViewCompat.setBackground(viewToAnimateItsBackground, colorDrawable)
if (durationInMs > 0) {
val colorAnimation = ValueAnimator.ofObject(ArgbEvaluator(), colorFrom, colorTo)
colorAnimation.addUpdateListener { animator: ValueAnimator ->
colorDrawable.color = (animator.animatedValue as Int)
ViewCompat.setBackground(viewToAnimateItsBackground, colorDrawable)
}
colorAnimation.duration = durationInMs.toLong()
colorAnimation.start()
}
}
폴더 애니메이터 를 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>
내부 활동 자바 파일, 이것을 호출
View v = getWindow().getDecorView().findViewById(android.R.id.content);
AnimatorSet set = (AnimatorSet) AnimatorInflater.loadAnimator(this, R.animator.fade);
set.setTarget(v);
set.start();
Kotlin에 아래 기능을 사용하십시오.
private fun animateColorValue(view: View) {
val colorAnimation =
ValueAnimator.ofObject(ArgbEvaluator(), Color.GRAY, Color.CYAN)
colorAnimation.duration = 500L
colorAnimation.addUpdateListener { animator -> view.setBackgroundColor(animator.animatedValue as Int) }
colorAnimation.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))));
}
원하는대로 사용하십시오.
ademar111190의 답변 에 따라이 방법을 사용하여 두 가지 색상 사이에서보기의 배경색을 펄스합니다.
private void animateBackground(View view, int colorFrom, int colorTo, int duration) {
ObjectAnimator objectAnimator = ObjectAnimator.ofObject(view, "backgroundColor", new ArgbEvaluator(), colorFrom, colorTo);
objectAnimator.setDuration(duration);
//objectAnimator.setRepeatCount(Animation.INFINITE);
objectAnimator.addListener(new Animator.AnimatorListener() {
@Override
public void onAnimationStart(Animator animation) {
}
@Override
public void onAnimationEnd(Animator animation) {
// Call this method again, but with the two colors switched around.
animateBackground(view, colorTo, colorFrom, duration);
}
@Override
public void onAnimationCancel(Animator animation) {
}
@Override
public void onAnimationRepeat(Animator animation) {
}
});
objectAnimator.start();
}