onAnimationEnd not get called - android

because animator set doesn't provide REPEAT function,
i am implementing my own repetition logic.
but i have a problem on it.
first, let me show you my sample code like below.
My MainActivity ->
public class MainActivity extends AppCompatActivity {
private ImageView imageView;
private Button button;
private AnimatorSet animatorSet;
private Repetition repetition;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
imageView = (ImageView) findViewById(R.id.image_view);
button = (Button) findViewById(R.id.button);
animatorSet = new AnimatorSet();
repetition = new Repetition();
button.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
startAnimation();
}
});
}
private void startAnimation() {
imageView.post(new Runnable() {
#Override
public void run() {
final ObjectAnimator moveY = ObjectAnimator.ofFloat(imageView, "y", imageView.getY(), imageView.getY() - 200F);
moveY.setDuration(1000);
final ObjectAnimator rotation = ObjectAnimator.ofFloat(imageView, "rotation", 0F, 360F);
rotation.setDuration(1000);
repetition.repeat(animatorSet, 10);
List<Animator> list = new ArrayList<>();
list.add(moveY);
list.add(rotation);
// problem is here, if i run a single animator, repetition class can not get onAnmationEnd callback.
animatorSet.play(moveY);
// if i run playSequentially with multiple animators it works properly;
// animatorSet.playSequentially(list);
animatorSet.start();
}
});
}
}
My support class for REPETITION ->
it's listening animator's lifecycle and if animation ends it compare the desire animation repeat count with current repeat count in onAnimationEnd callback. if i run a single animator.. onAnimationEnd not get called...
just first time of onAnimationEnd is called..
public class Repetition implements Animator.AnimatorListener {
private AnimatorSet animatorSet;
private int repeatCount;
private int currentRepeatCount;
public void repeat(AnimatorSet animatorSet, int repeatCount) {
this.animatorSet = animatorSet;
this.repeatCount = repeatCount;
animatorSet.removeAllListeners();
animatorSet.addListener(this);
}
#Override
public void onAnimationStart(Animator animation) {
Log.d("RepeatitionLog", "onAnimationStart");
}
#Override
public void onAnimationEnd(Animator animation) {
if(currentRepeatCount < repeatCount) {
animatorSet.start();
currentRepeatCount++;
Log.d("RepeatitionLog", "onAnimationRepeat by repetition");
Log.d("RepeatitionLog", "currentRepeatCount : " + currentRepeatCount);
} else {
Log.d("RepeatitionLog", "onAnimationEnd");
}
}
#Override
public void onAnimationCancel(Animator animation) {
Log.d("RepeatitionLog", "onAnimationCancel");
}
#Override
public void onAnimationRepeat(Animator animation) {
Log.d("RepeatitionLog", "onAnimationRepeat");
}
}
I'd appreciate any help!
Thanks.

Related

I want to set animation on ImageView

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.

Animation in custom pager in not starting up

I have a custom pager that uses two animations
final Animation fadeOut = AnimationUtils.loadAnimation(mContext, R.anim.fade_out);
final Animation fadeIn = AnimationUtils.loadAnimation(mContext, R.anim.fade_in);
For some reason, the animations are not starting up. For example, I'm logging
Log.v("TAG", "L1 start animation"); //prints "L1 start animation"
But I'm not logging anything in onAnimationEnd
Log.v("TAG", "L1 animation end"); //nothing is printing out
Here is setAnimation() method of CustomPager class
public void setAnimation(){
final Animation fadeOut = AnimationUtils.loadAnimation(mContext, R.anim.fade_out);
final Animation fadeIn = AnimationUtils.loadAnimation(mContext, R.anim.fade_in);
l1.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Log.v("TAG", "L1 clicked");
if (clicked) {
//do nothing
} else {
clicked = true;
fadeOut.setAnimationListener(new Animation.AnimationListener() {
#Override
public void onAnimationStart(Animation animation) {
Log.v("TAG", "L1 animation start");
}
#Override
public void onAnimationRepeat(Animation animation) {
}
#Override
public void onAnimationEnd(Animation animation) {
Log.v("TAG", "L1 animation end");
l1.setVisibility(View.GONE);
l2.bringToFront();
clicked = false;
}
});
Log.v("TAG", "L1 start animation");
l1.startAnimation(fadeOut);
l2.setVisibility(View.VISIBLE);
l2.startAnimation(fadeIn);
}
}
});
//etc
}
Here is CustomPager class
public class CustomPager extends PagerAdapter {
private Context mContext;
private View l1;
private View l2;
private LayoutInflater inflater;
private ViewGroup layout;
private Bitmap pic;
private Bitmap pic_blurred;
private boolean clicked = false;
public CustomPager(Context context) {
this.mContext = context;
}
#Override
public Object instantiateItem(ViewGroup collection, int position) {
inflater = LayoutInflater.from(mContext);
layout = (ViewGroup) inflater.inflate(R.layout.pager_play_panel, collection, false);
collection.addView(layout);
l1 = layout.findViewById(R.id.l1);
l2 = layout.findViewById(R.id.l2);
pic = BitmapFactory.decodeResource(mContext.getResources(), R.drawable.pic);
picture_blurred = blur(pic, 1, 100);
BitmapDrawable bkg1 = new BitmapDrawable(pic);
l1.setBackgroundDrawable(bkg1);
BitmapDrawable bkg2 = new BitmapDrawable(picture_blurred);
l2.setBackgroundDrawable(bkg2);
setAnimation();
return layout;
}
public void setAnimation(){
final Animation fadeOut = AnimationUtils.loadAnimation(mContext, R.anim.fade_out);
final Animation fadeIn = AnimationUtils.loadAnimation(mContext, R.anim.fade_in);
l1.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Log.v("TAG", "L1 clicked");
if (clicked) {
//do nothing
} else {
clicked = true;
fadeOut.setAnimationListener(new Animation.AnimationListener() {
#Override
public void onAnimationStart(Animation animation) {
Log.v("TAG", "L1 animation start");
}
#Override
public void onAnimationRepeat(Animation animation) {
}
#Override
public void onAnimationEnd(Animation animation) {
Log.v("TAG", "L1 animation end");
l1.setVisibility(View.GONE);
l2.bringToFront();
clicked = false;
}
});
Log.v("TAG", "L1 start animation");
l1.startAnimation(fadeOut);
l2.setVisibility(View.VISIBLE);
l2.startAnimation(fadeIn);
}
}
});
l2.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Log.v("TAG", "L2 clicked");
if (clicked) {
//do nothing
} else {
clicked = true;
fadeOut.setAnimationListener(new Animation.AnimationListener() {
#Override
public void onAnimationStart(Animation animation) {
}
#Override
public void onAnimationRepeat(Animation animation) {
}
#Override
public void onAnimationEnd(Animation animation) {
l2.setVisibility(View.GONE);
l1.bringToFront();
Log.v("TAG", "L2 visibility set to gone");
clicked = false;
}
});
l2.startAnimation(fadeOut);
l1.setVisibility(View.VISIBLE);
l1.startAnimation(fadeIn);
}
}
});
}
//Etc.
}
Looks like the problem was I had to change the scope of my view variables
public void setAnimation(View l1, View l2){
//etc
}
Rather than using them globally
public void setAnimation(){
//etc
}

How to start a function when animation has ended?

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.

Delay while restart of animation

I'm using value animator to animate a image view. I want to add a delay in Animation listener, i.e in "onAnimationRepeat()". How to accomplish this?
Maybe try something like this:
public class Test {
private int repeatNumber == 0;
public void startAnimation() {
Animation animation = AnimationUtils.loadAnimation(this, R.anim.fade_in);
animation.setAnimationListener(new AnimationListener() {
#Override
public void onAnimationStart(Animation animation) {Log.i("start", "start");}
#Override
public void onAnimationEnd(Animation animation) {Log.i("end", "end");}
#Override
public void onAnimationRepeat(Animation animation) {
Test.this.repeatNumber++;
Handler handler = new Handler();
handler.postDelayed(new Runnable() {
#Override
public void run() {
Test.this.startAnimation();
}, 30000 );
}
textView.startAnimation(animation);
}
}

Class to display flash screen

I would like to create a "Flash" class to display a white flash screen (200ms) as easily as a toast, like this:
Flash.create(context).show();
This layer should appear instantly then gradually disappear (alpha transition)
It must not catch events
It must adapt to the screen rotation
It can be created from any activity
I looked for a solution via WindowManager but I am having some difficulties.
What solution do you recommend?
There are some issues with that, as you'll have to pass the Activity and not just a Context into the "Flash" screen. Therefore the handling of screen rotation will be tricky.
I've created and open-sourced a small library called Crouton that can help you.
Currently it still struggles with the issue of orientation changes while a Crouton is being displayed.
So I give my own solution if it can help anybody...
(I changed the call to flash method since my first post)
public class Flasher {
private final static int DURATION_OFFSET = 300;
private final static int DURATION_FADEIN = 50;
private final static int DURATION_FADEOUT = 200;
private Animation fadein;
private Animation fadeout;
private RelativeLayout flash;
private RelativeLayout view;
private Toast toast;
private int count;
public Flasher(Context context) {
fadein = new AlphaAnimation(0, 1);
fadein.setStartOffset(DURATION_OFFSET);
fadein.setDuration(DURATION_FADEIN);
fadein.setAnimationListener(new AnimationListener() {
#Override public void onAnimationStart(Animation anim) {}
#Override public void onAnimationRepeat(Animation anim) {}
#Override public void onAnimationEnd(Animation anim) {
flash.startAnimation(fadeout);
}
});
fadeout = new AlphaAnimation(1, 0);
fadeout.setDuration(DURATION_FADEOUT);
fadeout.setAnimationListener(new AnimationListener() {
#Override public void onAnimationStart(Animation anim) {}
#Override public void onAnimationRepeat(Animation anim) {}
#Override public void onAnimationEnd(Animation anim) {
if(count > 1) {
flash(count - 1);
} else {
cancel();
}
}
});
LayoutParams params = new LayoutParams(-1, -1);
flash = new RelativeLayout(context);
flash.setLayoutParams(params);
flash.setBackgroundColor(0xffffffff);
flash.setVisibility(View.INVISIBLE);
view = new RelativeLayout(context);
view.setLayoutParams(params);
view.addView(flash);
toast = new Toast(context);
toast.setView(view);
toast.setGravity(Gravity.FILL, 0, 0);
}
public final void flash(int count) {
toast.show();
this.count = count;
flash.startAnimation(fadein);
}
public final void cancel() {
toast.cancel();
}
}
MainActivity for test it:
public class MainActivity extends Activity {
private static Flasher flasher;
#Override
public void onCreate(Bundle state) {
super.onCreate(state);
View layout = getLayoutInflater().inflate(R.layout.activity_main, null);
setContentView(layout);
if(flasher == null) {
flasher = new Flasher(this);
}
layout.setOnClickListener(new OnClickListener() {
#Override public void onClick(View v) {
flasher.flash(1);
}
});
}
#Override protected void onDestroy() {
if(isFinishing()) {
flasher = null;
}
super.onDestroy();
}
}
Thank you to Keyboardsurfer for the help!
Edit: a constraint is not satisfied:
The Toast does not dispatch the touch event:
flasher.flash(10);
MainActivity is not touchable during flashes effect
If anybody have a solution to resolve the problem...
After searching for many hours, it seems impossible to delegate events from one window to another. So the final functional solution I've found is to extend an activity so that it achieves this flash effect. For those who are interested in it, here's my subclass:
public class FlmActivity extends Activity {
private final static int DURATION_FADEIN = 50;
private final static int DURATION_FADEOUT = 200;
private final static int DURATION_INTERVAL = 200;
private View view;
private AnimationSet anim;
private int count;
public FlmActivity() {
super();
}
#Override protected void onPostCreate(Bundle state) {
super.onPostCreate(state);
view = new View(this) {{
setBackgroundColor(0xffffffff);
setVisibility(View.INVISIBLE);
}};
anim = new AnimationSet(false) {{
addAnimation(new AlphaAnimation(0, 1) {{
setDuration(DURATION_FADEIN);
}});
addAnimation(new AlphaAnimation(1, 0) {{
setStartOffset(DURATION_FADEIN);
setDuration(DURATION_FADEOUT);
}});
addAnimation(new Animation() {{
setStartOffset(DURATION_FADEIN + DURATION_FADEOUT);
setDuration(DURATION_INTERVAL);
setAnimationListener(new AnimationListener() {
#Override public void onAnimationStart(Animation anim) {}
#Override public void onAnimationRepeat(Animation anim) {}
#Override public void onAnimationEnd(Animation anim) {
flash(count - 1);
}
});
}});
}};
addContentView(view, getWindow().getAttributes());
}
#Override protected void onDestroy() {
((ViewGroup) view.getParent()).removeView(view);
super.onDestroy();
}
public final void flash(int count) {
if((this.count = count) > 0) {
view.startAnimation(anim);
}
}
}
Code to call flash effect in an extended activity:
flash(10);
With this implementation, the events pass through the layer

Categories

Resources