I am trying to create a small animation which changes smoothly the background color. My problem is that it only shows the last value (100, that means it directly goes to a red background). I don't know why my created while-loop doesn't actualize every value (so that it would show a smoothly color animation)
New code (which almost works, but Idk how to stop the animation)
imageButton_info.setOnClickListener(new View.OnClickListener(){
#Override
public void onClick(View v){
final Handler handler = new Handler();
Runnable ChangeBackgroundRunnable = new Runnable() {
#Override
public void run() {
number++;
float[] hsvColor = {0, 1, 1};
hsvColor[0] = 360f * number / 100;
color.setBackgroundColor(Color.HSVToColor(hsvColor));
handler.postDelayed(this, 80);
if (number >=100)
number = 1;
}
};
number = 0;
handler.removeCallbacks(ChangeBackgroundRunnable);
handler.postDelayed(ChangeBackgroundRunnable, 0);
}
});
Code:
public void onClick(View v){
try {
while (number<=100) {
number=number+1;
float[] hsvColor = {0, 1, 1};
hsvColor[0] = 360f * number / 100;
color.setBackgroundColor(Color.HSVToColor(hsvColor));
Thread.sleep(10);
}
}catch(Exception e){
//New exception
Log.e("Camera Error!",e.getMessage());
}
Thank you for your answer in advance...
When you change something in the UI, it doesn't happen immediately. Instead, it posts a message to the Looper on the UI thread. When control returns to the looper (when you're done with whatever function the framework called), it will process all the messages on the Looper, until it eventually processes the redraw request. Then it will draw. So if you're looping in onClick, you will not get any updates to the screen. If you want something to happen in 10ms, post a delayed message to a Handler and update the UI in that thread.
Side note: NEVER EVER sleep on the UI thread. The reason is that no input or draw commands can be processed if you're not returning control to the Looper. So your app becomes unresponsive. If you do it long enough, it can even cause the framework to kill your app for being unresponsive.
A better way to do this would be to use an Android animation. I stole the code for this from here
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();
Wrapped the answers posted by #gabe-sechan and #jesse-buss
ValueAnimator support from devices SDK above HONEYCOMB. So below that SDK level we'll use #gabe-sechan suggestion. Check the below code.
private void executeBackgroundChange() {
// Handler and runnable to run the animation in devices sdk below honeycomb.
mHandler = new Handler();
mChangeBackgroundRunnable = new Runnable() {
#Override
public void run() {
number++;
float[] hsvColor = {0, 1, 1};
hsvColor[0] = 360f * number / 100;
mContainer.setBackgroundColor(Color.HSVToColor(hsvColor));
mHandler.postDelayed(this, 500);
if (number == 100)
number = 0;
}
};
number = 0;
mHandler.removeCallbacks(mChangeBackgroundRunnable);
mHandler.postDelayed(mChangeBackgroundRunnable, 0);
}
#TargetApi(Build.VERSION_CODES.HONEYCOMB)
private void executeBackgroundChangeUsingValueAnimator() {
colorAnimation = ValueAnimator.ofObject(new ArgbEvaluator(), getResources().getColor(R.color.red), getResources().getColor(R.color.blue));
colorAnimation.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
#Override
public void onAnimationUpdate(final ValueAnimator animator) {
mContainer.setBackgroundColor((Integer) animator.getAnimatedValue());
}
});
colorAnimation.setRepeatCount(ValueAnimator.INFINITE);
colorAnimation.setDuration(10 * 1000);
colorAnimation.start();
}
Add the below method and to stop the animation on click of something call the below method.
private void stopBackgroundChangeAnimation() {
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.HONEYCOMB) {
if (colorAnimation != null && colorAnimation.isRunning())
colorAnimation.end();
} else {
if (mHandler != null && mChangeBackgroundRunnable != null)
mHandler.removeCallbacks(mChangeBackgroundRunnable);
}
}
Check the github project for reference.
Try to use runOnUiThread
public void onCreate(Bundle savedInstanceState) {
res = getResources();
super.onCreate(savedInstanceState);
setContentView(R.layout.xyz);//**Works**/
handler.postDelayed(runnable, 10);
}
private Runnable runnable = new Runnable() {
public void run() {
runOnUiThread(new Runnable() {
public void run()
{
try {
while (number<=100) {
number=number+1;
float[] hsvColor = {0, 1, 1};
hsvColor[0] = 360f * number / 100;
color.setBackgroundColor(Color.HSVToColor(hsvColor));
}
}catch(Exception e){
//New exception
}
}
});
}
}
Related
If the user (in my quizgame) chooses the false answer, the button with the correct answer should blink green.
So far i did it like this:
if(answerTrue)
for (int i = 0; i < 2000; i = i + 250) {
handler.postDelayed(rbl_blinkNormal, i);
i = i + 250;
handler.postDelayed(rbl_blinkGreen, i);
}
And the runnables:
Green:
rbl_blinkGreen= new Runnable() {
#Override
public void run() {
btn_richtig.setBackgroundResource(R.drawable.color_green_btn);
}
};
Normal:
rbl_blinkNormal= new Runnable() {
#Override
public void run() {
btn_richtig.setBackgroundResource(R.drawable.color_black_btn);
}
};
It works fine but like this Im calling the postDelayed() every 250ms. May this impact my application performance and is there any better way to do this?
You can animate your button once you set its color to say GREEN. I mean,
if(answerTrue){
// Set the color of the button to GREEN once.
// Next, animate its visibility with the set color - which is GREEN as follows:
Animation anim = new AlphaAnimation(0.0f, 1.0f);
anim.setDuration(50); //You can manage the blinking time with this parameter
anim.setStartOffset(20);
anim.setRepeatMode(Animation.REVERSE);
anim.setRepeatCount(Animation.INFINITE);
button.startAnimation(anim);
}
Similarly, you can animate the other button and stop animation when you feel like.
Source: Blinking Text in android view
If you want to blink the image only, here is an example.
Button bt_notes = (Button) findViewById(R.id.bt_notes);
int bt_notes_blink = 0;
final Handler handler = new Handler();
handler.postDelayed(new Runnable() {
#Override
public void run() {
runOnUiThread(new Runnable() {
#Override
public void run() {
int DrawableImage[] = {R.drawable.picto_keys, R.drawable.picto_blank};
Resources res = getApplicationContext().getResources();
bt_notes.setCompoundDrawablesWithIntrinsicBounds(null, null, null, res.getDrawable(DrawableImage[bt_notes_blink]));
bt_notes_blink++;
if (bt_notes_blink == 2) { bt_notes_blink = 0; }
handler.postDelayed(this, 500);
}
});
}
}, 0);
I have two separate animations for same progress bar:
#Override
public void onProgressStarted() {
mHandler.post(new Runnable() {
#Override
public void run() {
mProgressBar.setVisibility(View.VISIBLE);
mProgressBar.setProgress(0);
mProgressBar.setMax(1000);
ObjectAnimator animation = ObjectAnimator.ofFloat (mProgressBar, "alpha", 1.0f, 0.5f); // see this max value coming back here, we animale towards that value
animation.setRepeatMode(ValueAnimator.INFINITE);
animation.setDuration (150); //in milliseconds
animation.start();
}
});
}
#Override
public void onProgressUpdate(final int progress) {
mHandler.post(new Runnable() {
#Override
public void run() {
int current = mProgressBar.getProgress();
ObjectAnimator animation = ObjectAnimator.ofInt (mProgressBar, "progress", current, progress*10); // see this max value coming back here, we animale towards that value
animation.setDuration (1000); //in milliseconds
animation.setInterpolator (new DecelerateInterpolator());
animation.start();
}
});
}
How to animate ProgressBar progress while simultaneously i have to animate width of the progress line (infinitely/pulse) or alpha in this particular case?
So what i am trying to achieve is user would open to first page of the view pager, and the view pager would bounce to half of the second page and bounce back to the fist page indicating that there are more pages to scroll to. I was wondering on how i could implement this?
You can use fakeDragBy method to achieve this effect:
viewPager.beginFakeDrag();
viewPager.fakeDragBy(offset); //offset in pixels.
viewPager.endFakeDrag();
EDIT:
I have made method for this:
private int animFactor;
private ValueAnimator animator = new ValueAnimator();
private void animateViewPager(final ViewPager pager, final int offset, final int delay) {
if (!animator.isRunning()) {
animator.removeAllUpdateListeners();
animator.removeAllListeners();
//Set animation
animator.setIntValues(0, -offset);
animator.setDuration(delay);
animator.setRepeatCount(1);
animator.setRepeatMode(ValueAnimator.RESTART);
animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
public void onAnimationUpdate(ValueAnimator animation) {
Integer value = animFactor * (Integer) animation.getAnimatedValue();
if (!pager.isFakeDragging()) {
pager.beginFakeDrag();
}
pager.fakeDragBy(value);
}
});
animator.addListener(new AnimatorListenerAdapter() {
#Override
public void onAnimationStart(Animator animation) {
animFactor = 1;
}
#Override
public void onAnimationEnd(Animator animation) {
pager.endFakeDrag();
}
#Override
public void onAnimationRepeat(Animator animation) {
animFactor = -1;
}
});
animator.start();
}
}
Example of usage:
animateViewPager(pager, 10, 1000);
Edit2: ValueAnimator is class for Api level 11. Also set pager adapter before calling this method.
Adding a note to #Yuraj's answer. Call the method in onWindowFocusChanged when hasFocus==true as follows to avoid indexOutOfBoundsException:
#Override
public void onWindowFocusChanged(boolean hasFocus)
{
super.onWindowFocusChanged(hasFocus);
if(hasFocus)
{
Handler handler = new Handler();
final Runnable r = new Runnable()
{
public void run()
{
if(mViewPager.getCurrentItem() == 0)
{
Context context = Activity_main.this;
String filename="Init";
SharedPreferences stats;
stats = context.getSharedPreferences(filename, 0);
int appOpen = stats.getInt("appOpen", 0);
if(appOpen <= 5)
{
animateViewPager(mViewPager, 10, 300);
appOpen += 1;
SharedPreferences.Editor editor = stats.edit();
editor.putInt("appOpen", appOpen);
editor.commit();
}
}
}
};
handler.postDelayed(r, WAIT_VIEWPAGER_NUDGE);
}
}
Thank you Yuvraj! It worked with a simple modification. If anybody is getting "Invalid index 0, size is 0" error, here's a simple fix for it. If you call animateViewPager() method in onCreate() you might get this error, "Invalid index 0, size is 0". I believe viewpager.beginFakeDrag(); is being called before viewPager items / childs are initialized. So, call animateViewPager() with a delay like so:
new Handler().postDelayed(() -> animateViewPager(viewPager, 10, 1000), 500);
500 is the delay in milisecond
How to animate multiple objects one by one after some intervals android
i am using this code for animation
for (int y = 0; y < 10; y++) {
runOnUiThread(new Runnable() {
#Override
public void run() {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
}
Toast.makeText(ProjectFirstActivity.this, y + "",
Toast.LENGTH_SHORT).show();
ObjectAnimator oa = ObjectAnimator.ofFloat(myimageview[y],
"translationY", 0, -200);
oa.setDuration(1000);
oa.start();
}
});
}
but it is animating all in one go but i want one by one animation of my imageview please help
No need to use Threads and Handlers. Instead of that use,
objectAnimator.setStartDelay(delay);
Using that you can stop that animation for the respective 'delay'
Try this code..
int delay = 1000;
for (int y = 0; y < 10; y++) {
Toast.makeText(ProjectFirstActivity.this, y + "",
Toast.LENGTH_SHORT).show();
ObjectAnimator oa = ObjectAnimator.ofFloat(myimageview[y],
"translationY", 0, -200);
oa.setDuration(1000);
oa.setStartDelay(delay);
oa.start();
delay = delay+1000;
}
You can use for loop to generate AnimatorSet and then play them sequentially using set.playSequentially(yourAnimatorSetListHere);
I haven't used list in below mentioned snippet.
AnimatorSet decSet = new AnimatorSet();
decSet.playTogether(
ObjectAnimator.ofArgb(mTextSlidetoCancel, "visibility", View.GONE, View.VISIBLE),
ObjectAnimator.ofArgb(mBtnMicActive, "visibility", View.GONE, View.VISIBLE),
ObjectAnimator.ofArgb(mChronometer, "visibility", View.GONE, View.VISIBLE));
decSet.setDuration(125);
AnimatorSet decSet2 = new AnimatorSet();
decSet2.playTogether(
ObjectAnimator.ofArgb(mBtnAttach, "visibility", View.VISIBLE, View.GONE),
ObjectAnimator.ofArgb(mBtnEmoji, "visibility", View.VISIBLE, View.GONE),
ObjectAnimator.ofArgb(mEditTExt, "visibility", View.VISIBLE, View.GONE)
);
decSet2.setDuration(125);
AnimatorSet set = new AnimatorSet();
set.playSequentially(decSet2,decSet);
set.start();
Try out this way!
public Integer[] Imgid = {R.drawable.anim2, R.drawable.anim3,
R.drawable.anim4, R.drawable.anim5}; // your image array.
Animation anim;
Handler handler;
ImageView iv;
int count;
Runnable galleryAnimRunnable;
Inside onCreate
iv= (ImageView)findViewById(R.id.imagetype);
handler = new Handler();
galleryAnimRunnable = new Runnable() {
public void run() {
if(count==Imgid.length){
//do any action
}
else{
anim = AnimationUtils.loadAnimation(AnimationScreen.this, R.anim.fade_out); // load your desire animation.
iv.setBackgroundResource(Imgid[count]);
iv.setAnimation(anim);
count++;
handler.postDelayed(galleryAnimRunnable, 300); //set your desire delay time.
}
}
};
Your sleep call isn't helping because when one posted UI job goes to sleep, then next one starts and goes to sleep immediately following that, and so on. Then the first job wakes up and runs, followed closely by the second job awakening and running, etc.
If you want the sleep to help you need to wait before posting each job, which could be as simple as something like the following:
for (int y = 0; y < 10; y++) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
}
runOnUiThread(new Runnable() {
#Override
public void run() {
Toast.makeText(ProjectFirstActivity.this, y + "",
Toast.LENGTH_SHORT).show();
ObjectAnimator oa = ObjectAnimator.ofFloat(myimageview[y],
"translationY", 0, -200);
oa.setDuration(1000);
oa.start();
}
});
}
EDIT: Although the above explains why you were having problems, I would recommend going with something like the answer posted by Jgdsh Seerm using setStartDelay().
Try this way!
ImageView image1;
public int currentimageindex1=0;
Timer timer;
TimerTask task;
private Animation animation1;
private Animation animation2;
int img[] = {R.drawable.aa, R.drawable.bb,
R.drawable.cc,R.drawable.dd,R.drawable.ee,R.drawable.ff,R.drawable.gg,
R.drawable.hh};
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
final Handler mHandler = new Handler();
// Create runnable for posting
final Runnable mUpdateResults = new Runnable() {
public void run() {
AnimateandSlideShow();
}
};
int delay = 1000; // delay for 1 sec.
int period = 4000; // repeat every 4 sec.
Timer timer = new Timer();
timer.scheduleAtFixedRate(new TimerTask() {
public void run() {
mHandler.post(mUpdateResults);
}
}, delay, period);
}
public void onClick(View v) {
finish();
android.os.Process.killProcess(android.os.Process.myPid());
}
/**
* Helper method to start the animation on the splash screen
*/
private void AnimateandSlideShow() {
image1 = (ImageView)findViewById(R.id.imageView1);
image1.setImageResource(img[currentimageindex1%img.length]);
currentimageindex1++;
}
Is there a way to animate a text color change (from anycolor to white)?
The only variant I came up with, is placing two textviews (with the same text) in one place, and fading the top one, so the bottom one (that has a white color) will become visible.
P.S. I scrapped the variant of the 2 TextViews since it looked weird (edges weren't smooth and, since I have a lot of such elements on the screen it was really lagging the scrolling). What I did, was a crazy hack that does the animation with the use of a Thread and setTextColor (that also forces redraw of a textview).
Since I needed only 2 color changes (from red to white, and from green to white) I hardcoded the values and all of the transition colors between them. So here's how it looks:
public class BlinkingTextView extends TextView {
public BlinkingTextView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public void animateBlink(final boolean red) {
if (animator != null) {
animator.drop();
}
animator = new Animator(this, red);
animator.start();
}
public void clearBlinkAnimation() {
if (animator != null) {
animator.drop();
}
}
private Animator animator;
private final static class Animator extends Thread {
public Animator(final TextView textView, final boolean red) {
this.textView = textView;
if (red) {
SET_TO_USE = RED;
} else {
SET_TO_USE = GREEN;
}
}
private TextView textView;
private final int[] SET_TO_USE;
private final static int[] RED = {
-2142396,
-2008754,
-1874854,
-1740697,
-1540490,
-1405563,
-1205099,
-1004634,
-804170,
-669243,
-469036,
-334879,
-200979,
-67337,
-1
};
private final static int[] GREEN = {
-6959821,
-6565826,
-6106293,
-5646758,
-5055894,
-4530309,
-3939444,
-3283042,
-2692177,
-2166592,
-1575728,
-1116193,
-656660,
-262665,
-1
};
private boolean stop;
#Override
public void run() {
int i = 0;
while (i < 15) {
if (stop) break;
final int color = SET_TO_USE[i];
if (stop) break;
textView.post(new Runnable() {
#Override
public void run() {
if (!stop) {
textView.setTextColor(color);
}
}
});
if (stop) break;
i++;
if (stop) break;
try {
Thread.sleep(66);
} catch (InterruptedException e) {}
if (stop) break;
}
}
public void drop() {
stop = true;
}
}
}
You can use new Property Animation Api for color animation:
Integer colorFrom = getResources().getColor(R.color.red);
Integer colorTo = getResources().getColor(R.color.blue);
ValueAnimator colorAnimation = ValueAnimator.ofObject(new ArgbEvaluator(), colorFrom, colorTo);
colorAnimation.addUpdateListener(new AnimatorUpdateListener() {
#Override
public void onAnimationUpdate(ValueAnimator animator) {
textView.setTextColor((Integer)animator.getAnimatedValue());
}
});
colorAnimation.start();
For backward compatability with Android 2.x use Nine Old Androids library from Jake Wharton.
The Easiest solution will be to use Object Animators :
ObjectAnimator colorAnim = ObjectAnimator.ofInt(yourTextView, "textColor",
Color.RED, Color.GREEN);
colorAnim.setEvaluator(new ArgbEvaluator());
colorAnim.start();
No need to keep handles to the two text views. First add the fadeIn/fadeOut animations:
textSwitcher.setInAnimation(AnimationUtils.loadAnimation(this, android.R.anim.fade_in));
textSwitcher.setOutAnimation(AnimationUtils.loadAnimation(this, android.R.anim.fade_out));
then:
TextView currentTextView = (TextView)(textSwitcher.getNextView().equals(
textSwitcher.getChildAt(0)) ?
textSwitcher.getChildAt(1) : textSwitcher.getChildAt(0)
);
// setCurrentText() first to be the same as newText if you need to
textSwitcher.setTextColor(fadeOutColor);
((TextView) textSwitcher.getNextView()).setTextColor(Color.WHITE);
textSwitcher.setText(newText);
Just implemented it like this so proven to work.
best way use ValueAnimator and 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();
textView.setTextColor(ColorUtils.blendARGB(Color.parseColor("#FFFFFF")
, Color.parseColor("#000000")
, fractionAnim));
}
});
valueAnimator.start();
Although I haven't found a totally distinct method, I have tried to use a TextSwitcher (with the fade animation) to create the colour-change effect. A TextSwitcher is a kind of ViewSwitcher which literally animates between two (internal) TextViews. Did you manually implement the same system unknowingly? ;) It manages a bit more of the process for you, so you may find it easier to work with (especially if you want to try more involved animations). I would create new subclass of TextSwitcher and some methods e.g. setColour() which can set the new colour and then trigger an animation. The animation code can then be moved outside of your main application.
make sure you keep a handle on the two TextViews that are put into the switcher
change the colour of the other TextView and call setText() to animate between them
If you are already using a ViewSwitcher then I don't think there is an easier way to implement this.
As others mention, using ObjectAnimator solves for this. However, in the existing posts - I wasn't seeing how to set duration. For me the color change would happen immediately.
The solution below shows:
setting the animation with some interval; thanks to post: https://plus.google.com/+CyrilMottier/posts/X4yoNHHszwq
a way to continuously cycle back and forth between the 2 colors
void animateTextViewColors(TextView textView, Integer colorTo) {
final Property<TextView, Integer> property = new Property<TextView, Integer>(int.class, "textColor") {
#Override
public Integer get(TextView object) {
return object.getCurrentTextColor();
}
#Override
public void set(TextView object, Integer value) {
object.setTextColor(value);
}
};
final ObjectAnimator animator = ObjectAnimator.ofInt(textView, property, colorTo);
animator.setDuration(8533L);
animator.setEvaluator(new ArgbEvaluator());
animator.setInterpolator(new DecelerateInterpolator(2));
animator.start();
}
void oscillateDemo(final TextView textView) {
final int whiteColor = ContextCompat.getColor(TheApp.getAppContext(), R.color.white);
final int yellowColor = ContextCompat.getColor(TheApp.getAppContext(), R.color.yellow);
final int counter = 100;
Thread oscillateThread = new Thread() {
#Override
public void run() {
for (int i = 0; i < counter; i++) {
final int fadeToColor = (i % 2 == 0)
? yellowColor
: whiteColor;
getActivity().runOnUiThread(new Runnable() {
#Override
public void run() {
animateTextViewColors(textView, fadeToColor);
}
});
try {
Thread.sleep(2450);
}
catch (InterruptedException iEx) {}
}
}
};
oscillateThread.start();
}
I scrapped the variant of the 2 TextViews since it looked weird (edges weren't smooth and, since I have a lot of such elements on the screen it was really lagging the scrolling). What I did, was a crazy hack that does the animation with the use of a Thread and setTextColor (that also forces redraw of a textview).
Since I needed only 2 color changes (from red to white, and from green to white) I hardcoded the values and all of the transition colors between them. So here's how it looks:
public class BlinkingTextView extends TextView {
public BlinkingTextView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public void animateBlink(final boolean red) {
if (animator != null) {
animator.drop();
}
animator = new Animator(this, red);
animator.start();
}
public void clearBlinkAnimation() {
if (animator != null) {
animator.drop();
}
}
private Animator animator;
private final static class Animator extends Thread {
public Animator(final TextView textView, final boolean red) {
this.textView = textView;
if (red) {
SET_TO_USE = RED;
} else {
SET_TO_USE = GREEN;
}
}
private TextView textView;
private final int[] SET_TO_USE;
private final static int[] RED = {
-2142396,
-2008754,
-1874854,
-1740697,
-1540490,
-1405563,
-1205099,
-1004634,
-804170,
-669243,
-469036,
-334879,
-200979,
-67337,
-1
};
private final static int[] GREEN = {
-6959821,
-6565826,
-6106293,
-5646758,
-5055894,
-4530309,
-3939444,
-3283042,
-2692177,
-2166592,
-1575728,
-1116193,
-656660,
-262665,
-1
};
private boolean stop;
#Override
public void run() {
int i = 0;
while (i < 15) {
if (stop) break;
final int color = SET_TO_USE[i];
if (stop) break;
textView.post(new Runnable() {
#Override
public void run() {
if (!stop) {
textView.setTextColor(color);
}
}
});
if (stop) break;
i++;
if (stop) break;
try {
Thread.sleep(66);
} catch (InterruptedException e) {}
if (stop) break;
}
}
public void drop() {
stop = true;
}
}
}
The issue I found with valueAnimator as well as ObjectAnimator is that the animator iterates through a number of random colors, and the transition doesn't look smooth. I wrote the following code which worked smoothly. Hope it helps someone else also.
public static void changeTextColor(final TextView textView, int startColor, int endColor,
final long animDuration, final long animUnit){
if (textView == null) return;
final int startRed = Color.red(startColor);
final int startBlue = Color.blue(startColor);
final int startGreen = Color.green(startColor);
final int endRed = Color.red(endColor);
final int endBlue = Color.blue(endColor);
final int endGreen = Color.green(endColor);
new CountDownTimer(animDuration, animUnit){
//animDuration is the time in ms over which to run the animation
//animUnit is the time unit in ms, update color after each animUnit
#Override
public void onTick(long l) {
int red = (int) (endRed + (l * (startRed - endRed) / animDuration));
int blue = (int) (endBlue + (l * (startBlue - endBlue) / animDuration));
int green = (int) (endGreen + (l * (startGreen - endGreen) / animDuration));
textView.setTextColor(Color.rgb(red, green, blue));
}
#Override
public void onFinish() {
textView.setTextColor(Color.rgb(endRed, endGreen, endBlue));
}
}.start();
}