I am using NineOldAndroid's AnimatorSet on a View
and when i want to get rid of the animation, and make the view gone - nothing happens
how do i make the view go away?
public void showAnimation(boolean show) {
if (show) {
if (mTarget.getVisibility() != View.VISIBLE) {
// play sound
mTarget.setVisibility(View.VISIBLE);
pauseAnimation = false;
// start animation
initTargetAnimation();
}
} else {
pauseAnimation = true; //All of this block gets executed in the debugger, but none of it actually take effect
if (mTarget.getAnimation() != null) {
mTarget.getAnimation().cancel();
mTarget.clearAnimation();
}
mTarget.setVisibility(View.GONE);
}
}
private void initTargetAnimation() {
final AnimatorSet set = new AnimatorSet();
// init animation properties
set.playTogether(ObjectAnimator.ofFloat(mTarget, "scaleX", RELEVANT_ANIMATION_SEQUENCE), ObjectAnimator.ofFloat(mTarget, "scaleY", RELEVANT_ANIMATION_SEQUENCE));
// add animation listener
set.setDuration(1500).addListener(new Animator.AnimatorListener() {
#Override
public void onAnimationStart(Animator animation) {
}
#Override
public void onAnimationEnd(Animator animation) {
// RESTART ANIMATION
if (!pauseAnimation) {
initTargetAnimation(); // TODO fix
}
}
#Override
public void onAnimationCancel(Animator animation) {
}
#Override
public void onAnimationRepeat(Animator animation) {
}
});
// start animation
set.start();
}
After you set the visibility on your View mTarget try calling invalidate() on it. This assumes you call it from the main thread otherwise it's postinvalidate().
Related
I made an animation (ObjectAnimator)for a text view it work correctly but i have a question.
I wanna know is there any method that i can use immediately after animation duration finished ?
(I mean a method like onFinish when we use CountDownTimer)
I want the rest of methods and codes I have in app run when animation finished.Is there a solution for that?
ObjectAnimator deltaXAnimation = ObjectAnimator.ofFloat(winMassage,"scaleX",1f,1.5f);
deltaXAnimation.setDuration(300);
deltaXAnimation.start();
ObjectAnimator deltaYAnimation = ObjectAnimator.ofFloat(winMassage,"scaleY",1f,1.5f);
deltaYAnimation.setDuration(300);
deltaYAnimation.start();
HI there are proper callback methods in which you get Animation Start and end Listeners
ObjectAnimator deltaXAnimation =
ObjectAnimator.ofFloat(winMassage,"scaleX",1f,1.5f);
deltaXAnimation.setDuration(300);
deltaXAnimation.start();
deltaXAnimation.addListener(new Animator.AnimatorListener() {
#Override
public void onAnimationStart(Animator animator) {
}
#Override
public void onAnimationEnd(Animator animator) {
}
#Override
public void onAnimationCancel(Animator animator) {
}
#Override
public void onAnimationRepeat(Animator animator) {
}
});
Below code might be understand well, creating a listener for ObjectAnimator
ObjectAnimator deltaXAnimation =
ObjectAnimator.ofFloat(winMassage,"scaleX",1f,1.5f);
deltaXAnimation.setDuration(300);
deltaXAnimation.start();
anim.setAnimationListener(new Animation.AnimationListener() {
public void onAnimationStart(Animation a) {
//
}
public void onAnimationRepeat(Animation a) {
}
public void onAnimationEnd(Animation a) {
}
});
We can go also to your ObjectAnimator
Handler handler = new Handler();
handler.postDelayed(new Runnable() {
#Override
public void run() {
//stop animation after 5 seconds
deltaXAnimation.cancel();
}
}, 5000); //5000 equals to 5seconds
}
Hope this might help you
I have two functions that animate two different TextViews but they both seem to start at the same time but I am trying to have the animation of the first function finish first and then start the second function.
public Boolean functionFinished = false;
public void runFunction(){
firstFunction();
if(functionFinished = true){
secondFunction();
}
}
public void firstFunction(){
initialCount = (TextView) findViewById(R.id.textView_Fade);
initialCount.setText("3");
final Animation out = new AlphaAnimation(1.0f, 0.0f);
out.setDuration(1000);
initialCount.startAnimation(out);
out.setAnimationListener(new Animation.AnimationListener() {
#Override
public void onAnimationStart(Animation animation) {
}
#Override
public void onAnimationEnd(Animation animation) {
if(initialCount.getText().equals("3")){
initialCount.setText("2");
initialCount.startAnimation(out);
} else if(initialCount.getText().equals("2")){
initialCount.setText("1");
initialCount.startAnimation(out);
} else if (initialCount.getText().equals("1")){
initialCount.setText("START!");
}
}
#Override
public void onAnimationRepeat(Animation animation) {
}
});
functionFinished = true;
}
The second function simply changes its own textView every second counting up from 0.
What did I do wrong / how do I correct this so that the second function runs after the first function has finished? (ie. sets functionFinished to true only when the TextView from the firstFunction is "START!")
public void runFunction() {
firstFunction();
}
public void firstFunction() {
initialCount = (TextView) findViewById(R.id.textView_Fade);
initialCount.setText("3");
final Animation out = new AlphaAnimation(1.0f, 0.0f);
out.setDuration(1000);
out.setAnimationListener(new Animation.AnimationListener() {
#Override
public void onAnimationStart(Animation animation) {
}
#Override
public void onAnimationEnd(Animation animation) {
...
secondFunction();
}
#Override
public void onAnimationRepeat(Animation animation) {
}
});
initialCount.startAnimation(out);
}
Just call second function from onAnimationEnd. Also keep in mind that you should attach listener before start animation.
If your minimum sdk version is 14:-
textView1.animate()
.alpha(0f)
.setDuration(400)
.setAnimationListener(new AnimationListener() {
#Override
public void onAnimationEnd(Animation arg0) {
// animate second textview here....
}
});
Because you assign functionFinished = true at the end of the firstFunction().
And you must misunderstand that initialCount.startAnimation(out) will block the code and firstFunction() completes only after animation ends .
initialCount.startAnimation(out) will not block any code ,and functionFinished = true is run immediately. so secondFunction() will run immediately after firstFunction() finishes instead of animation finishes.
I have a TextView named tvCallToActionBanner that is shown depending on certain events. This method below controls whether said TextView gets shown. This method gets called in the Activity's onResume() and a couple of other methods call it as well.
public void showCallToActionBanner() {
runOnUiThread(new Runnable() {
#Override
public void run() {
if (!mPrefs.getCurrentLiveGameDateId().isEmpty()) {
mPrefs.setCallToActionType(GlobalVars.CTA_IN_GAME);
tvCallToActionBanner.setText(R.string.cta_game_in_progress);
if (!tvCallToActionBanner.isShown()) showCallToActionBanner(true);
}
else if (mPrefs.getLiveGameDateStatus().equals(GlobalVars.LIVE_GAME_DATE_SEARCHING)) {
mPrefs.setCallToActionType(GlobalVars.CTA_LIVE_GAME_DATE_SEARCHING);
tvCallToActionBanner.setText(R.string.cta_live_game_date_searching);
if (!tvCallToActionBanner.isShown()) showCallToActionBanner(true);
}
else if (!mPrefs.getUnratedGameDateIds().isEmpty()) {
mPrefs.setCallToActionType(GlobalVars.CTA_RATE_MATCH);
mPrefs.setCallToActionId(mPrefs.getUnratedGameDateIds().iterator().next());
tvCallToActionBanner.setText(R.string.cta_unrated_match);
if (!tvCallToActionBanner.isShown()) showCallToActionBanner(true);
}
else if (tvCallToActionBanner.isShown()) {
showCallToActionBanner(false);
}
}
});
}
public void showCallToActionBanner(final boolean shouldShow) {
runOnUiThread(new Runnable() {
#Override
public void run() {
if (shouldShow) {
Animation enterAnim = AnimationUtils.loadAnimation(MainActivity.this, R.anim
.banner_slide_down);
enterAnim.setAnimationListener(new Animation.AnimationListener() {
#Override
public void onAnimationStart(Animation animation) {
}
#Override
public void onAnimationEnd(Animation animation) {
int paddingTop = (int) getResources().getDimension(R.dimen
.main_container_top_spacing_for_banner);
mainContainer.setPadding(0, paddingTop, 0, 0);
}
#Override
public void onAnimationRepeat(Animation animation) {
}
});
tvCallToActionBanner.startAnimation(enterAnim);
tvCallToActionBanner.setVisibility(View.VISIBLE);
}
else {
Animation exitAnim = AnimationUtils.loadAnimation(MainActivity.this, R.anim
.banner_slide_up);
exitAnim.setAnimationListener(new Animation.AnimationListener() {
#Override
public void onAnimationStart(Animation animation) {
}
#Override
public void onAnimationEnd(Animation animation) {
mainContainer.setPadding(0, 0, 0, 0);
}
#Override
public void onAnimationRepeat(Animation animation) {
}
});
tvCallToActionBanner.startAnimation(exitAnim);
tvCallToActionBanner.setVisibility(View.GONE);
}
}
});
}
So when I trigger the tvCallToActionBanner to show in Activity A, it shows with no issues.
I create Activity B, and the onResume() gets called and it shows it with no problems.
And then I create Activity C, onResume() gets called and shows tvCallToActionBanner. I call a method which now hides tvCallToActionBanner and it hides with no issues.
I press the back button and it goes back to Activity B, which calls the onResume() and should be hiding the tvCallToActionBanner but it isn't.
I checked the tvCallToActionBanner.isShown() and it is returning false in Activity B after I press the back button from C. But the view is clearly showing and should be returning true.
Is it because the way the order of the Views are drawn? I have tried to move the method call to onPostResume() but that did nothing. How do I get the tvCallToActionBanner.isShown() to return true when it is showing?
Just use a View.getVisibility() method.
if(textView.getVisibility == View.VISIBLE) {
// do stuff
}
isShown() checks also the visibility of its ancestors - so the view itself could be visible but one of its parents isn't (#see here)
textview.viewTreeObserver.addOnGlobalLayoutListener {
Toast.makeText(this,"layout changed "
+textview.isShown
,Toast.LENGTH_LONG)
.show()
Toast.makeText(this,"visible "+
(textView.visibility==View.VISIBLE)
,Toast.LENGTH_LONG)
.show()
}
I got this animation drawable running, and i want to continue only when it is finished. this code results in overlapping images.
public void onClick(View w) {
rangen = r.nextInt(4-1)+1;
frameAnimation.start();
if (rangen==1){
enemyj.setImageResource(R.drawable.paper);
restextj.setText("You Lose!");}
else if (rangen==2){
enemyj.setImageResource(R.drawable.rock);
restextj.setText("Draw");}
else if (rangen==3){
enemyj.setImageResource(R.drawable.sciss);
restextj.setText("You Win!");}}
}
add an animation listener to your frameAnimation before you start it
frameAnimation.setAnimationListener( new AnimationListener() {
#Override
public void onAnimationEnd (Animation animation) {
animation.setAnimationListener(null);
//do whatever work you need done
}
#Override
public void onAnimationRepeat (Animation animation) {
}
#Override
public void onAnimationStart (Animation animation) {
}
});
I've got an activity in which several Views animate. The animations are triggered when a RelativeLayout containing a few images is clicked. It's set up in onCreate() like this:
mContainer.setOnClickListener(new ContainerClicked());
And the ContainerClicked() class looks like this:
private class ContainerClicked implements OnClickListener {
#Override
public void onClick(View arg0) {
Log.i(TAG, "TEST!");
mSomeButton.setOnClickListener(null);
mSomeButton.setEnabled(false);
mAnotherButton.setOnClickListener(null);
mAnotherButton.setEnabled(false);
mYetAnotherButton.setOnClickListener(null);
mYetAnotherButton.setEnabled(false);
mContainer.setOnClickListener(null);
if (mLogo.getVisibility() == View.VISIBLE)
new AnimateToParty().execute();
else
new AnimateFromParty().execute();
}
}
This works, and animates everything just how I want it.
AnimateToParty() looks like this:
private class AnimateToParty extends AsyncTask<Void, Integer, Void> {
#Override
protected void onProgressUpdate(final Integer... values) {
final View theView = findViewById(values[0]);
if (!(values[0] == mBackgroundImage.getId() || values[0] == mContainer
.getId())) {
final Animation animation = AnimationUtils.loadAnimation(
DashboardActivity.this, values[1]);
animation.setAnimationListener(new AnimationListener() {
#Override
public void onAnimationStart(Animation arg0) {
}
#Override
public void onAnimationRepeat(Animation arg0) {
}
#Override
public void onAnimationEnd(Animation arg0) {
theView.setVisibility(View.INVISIBLE);
}
});
theView.startAnimation(animation);
} else if (values[0] == mBackgroundImage.getId()) {
TransitionDrawable transition = (TransitionDrawable) theView
.getBackground();
transition.startTransition(getResources().getInteger(
android.R.integer.config_mediumAnimTime));
} else {
TranslateAnimation animation = new TranslateAnimation(0, 0, 0,
TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,
-60, getResources().getDisplayMetrics()));
animation.setAnimationListener(new AnimationListener() {
#Override
public void onAnimationStart(Animation arg0) {
}
#Override
public void onAnimationRepeat(Animation arg0) {
}
#Override
public void onAnimationEnd(Animation arg0) {
LayoutParams lp = (LayoutParams) mContainer
.getLayoutParams();
lp.bottomMargin = 0;
RelativeLayout parent = (RelativeLayout) mContainer
.getParent();
mSomeButton.setVisibility(View.GONE);
mAnotherButton.setVisibility(View.GONE);
mYetAnotherButton.setVisibility(View.GONE);
mLogo.setVisibility(View.GONE);
// mContainer.setLayoutParams(lp);
// This caused a visible flicker, so I went with the solution below.
parent.removeView(mContainer);
parent.addView(mContainer, lp);
}
});
animation.setDuration(1000);
mContainer.startAnimation(animation);
}
}
#Override
protected Void doInBackground(Void... arg0) {
try {
publishProgress(mContainer.getId());
publishProgress(mLogo.getId(), R.anim.slide_out_up);
Thread.sleep(100);
publishProgress(mSomeButton.getId(), R.anim.slide_out_left);
Thread.sleep(110);
publishProgress(mAnotherButton.getId(), R.anim.slide_out_left);
Thread.sleep(120);
publishProgress(mYetAnotherButton.getId(), R.anim.slide_out_left);
Thread.sleep(130);
publishProgress(mBackgroundImage.getId());
Thread.sleep(550);
} catch (InterruptedException e) {
e.printStackTrace();
}
return null;
}
#Override
protected void onPostExecute(Void result) {
mContainer.setOnClickListener(new LighterClicked());
}
}
The class above animates some buttons and the logo out of the way, and then reveals the container. In order to keep it there, I change it's layoutparams. Just changing them produces a visible flicker where the container jumps 60 dip up for about one frame (the animation doesn't seem to be quite finished), before settling where I want it. I read somewhere to remove it from its parent and put it back in, and this does not produce the same flicker. However, now the rebinding of the onclicklistener does not work!
I've tried just about everything, and I just now noticed that every click that didn't "go through" fires if I press the home button and open the application again.
Is there a better way to avoid the "flicker"? A better way to do the animations? (I'm quite new at animating views) Why do the click-events fire when I reopen the application?
To avoid the flicker you are seeing, you have to call clearAnimation() at the start of onAnimationEnd
#Override
public void onAnimationEnd(Animation arg0) {
theView.clearAnimation()
...
}