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()
...
}
Related
i want to make a toss app ..it is spining all time and will not stop to show a head or tail..i want that when i click on the coin then it should spin for 2 3 seconds and then stops to show head or tail at random selection...but it is continuously spinning.
Here is the code...
public class MainActivity extends AppCompatActivity {
ImageView Coin;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Coin=(ImageView) findViewById(R.id.ImgViewcoin);
Coin.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Animation animation = new AlphaAnimation(1, 0);
animation.setInterpolator(new DecelerateInterpolator());
animation.setDuration(3000);
Coin.startAnimation(animation);
animation.setAnimationListener(new Animation.AnimationListener() {
#Override
public void onAnimationStart(Animation animation) {
final int[] photos = {R.drawable.heads, R.drawable.tails};
final ImageView image = (ImageView) findViewById(R.id.ImgViewcoin);
final Random ran = new Random();
int i = ran.nextInt(photos.length);
image.setImageResource(photos[i]);
image.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
int k = ran.nextInt(photos.length);
image.setImageResource(photos[k]);
}
}
);
}
#Override
public void onAnimationEnd(Animation animation) {
}
#Override
public void onAnimationRepeat(Animation animation) {
}
});
Coin.startAnimation(animation);
}
});
}
}
Remove the findviewbyid from onclick and use with Coin instance you have.
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 an activity where an TextView show up, and after that it fades out. However, everytime it has fade out, it pops back in. I tried
wtext.setText("");
But then my text just disappeares without fading out(after fading in). Does anyone knows how to fix this? Thanks! Kind regards.
This is my code:
public class SplashScreen extends Activity {
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
setContentView(R.layout.splash);
super.onCreate(savedInstanceState);
setContentView(R.layout.splash);
Handler handler = new Handler();
final TextView wtext = (TextView) (findViewById(R.id.wtext));
Animation animation = AnimationUtils.loadAnimation(this, R.anim.abc_fade_in);
wtext.startAnimation(animation);
Runnable task = new Runnable() {
#Override
public void run() {
Animation animation1 = AnimationUtils.loadAnimation(getApplicationContext(), R.anim.abc_fade_out);
wtext.startAnimation(animation1);
wtext.setText("");
}
};
handler.postDelayed(task, 5000);
}
If you want something to happen after an animation is complete (in this case, hide a textview), you'll have to use an AnimationListener
Animation.AnimationListener myListener = new Animation.AnimationListener() {
#Override
public void onAnimationStart(Animation animation) {
}
#Override
public void onAnimationRepeat(Animation animation) {
}
#Override
public void onAnimationEnd(Animation animation) {
wtext.setVisibility(View.INVISIBLE);
}
};
animation1.setAnimationListener(myListener);
You could use a ViewPropertyAnimator, which will change the view's actual properties rather than just its appearance, so that it will not jump back to the original state after the animation is complete.
wtext.animate().alpha(0);
You could try setting fillAfter flag to true on the element: it will apply the final transformation to it after the animation is finished.
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()
}
How to start an activity after the animation has ended. I have added android:oneshot="true" in the xml but how to start a new activity after this animation has stopped.I have attached the entire code below. Please let me know how to start new activity.If I use this code without showing my animation it goes to the another acitivity.
public class MainActivity extends Activity {
ImageView iv;
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
public void onWindowFocusChanged (boolean hasFocus) {
super.onWindowFocusChanged(hasFocus);
AnimationDrawable animation = (AnimationDrawable) iv.getBackground();
if(hasFocus) {
animation.start();
startActivity(new Intent(MainActivity.this,second.class));
} else {
animation.stop();
}
}
public void onStart() {
{
super.onStart();
iv = (ImageView)findViewById(R.id.imageView1);
iv.setBackgroundResource(R.animator.animation);
}
}
}
One way for sure you can use onAnimationListener, and be really interested into implementing the onAnimationEnd method of the listener interface.
Something like this:
animation.setAnimationListener(new Animation.AnimationListener() {
#Override
public void onAnimationStart(Animation animation) {
}
#Override
public void onAnimationEnd(Animation animation) {
startActivity(new Intent(MainActivity.this,second.class));
}
#Override
public void onAnimationRepeat(Animation animation) {
}
});