How to make the code next after using the animation wait for the animation to complete? Now it starts to run in parallel with the launch of the animation.

Method using animation:

private void moveToHistory() { Animation animation = AnimationUtils.loadAnimation(this, R.anim.move_operation); animation.setAnimationListener(new Animation.AnimationListener() { @Override public void onAnimationStart(Animation animation) { } @Override public void onAnimationEnd(Animation animation) { historyField.setText(getNumberField()); historyOperation.setText(operationField.getText().toString()); numberField.setText(" "); operationField.setText(" "); } @Override public void onAnimationRepeat(Animation animation) { } }); numberField.startAnimation(animation); operationField.startAnimation(animation); } 

Another method with animation:

 private void clearCalculation() { Animation animation = AnimationUtils.loadAnimation(MainActivity.this, R.anim.dissolution); animation.setAnimationListener(new Animation.AnimationListener() { @Override public void onAnimationStart(Animation animation) { } @Override public void onAnimationEnd(Animation animation) { numberField.setText(" "); operationField.setText(" "); historyField.setText(" "); historyOperation.setText(" "); isPercentCalculation = false; isResult = false; } @Override public void onAnimationRepeat(Animation animation) { } }); numberField.startAnimation(animation); operationField.startAnimation(animation); historyField.startAnimation(animation); historyOperation.startAnimation(animation); } 

An example of code in which methods with animation can be called:

 private void addNumber(String s) { if (isResult || isError()) clearCalculation(); //есть анимация if (!isEmpty(operationField)) moveToHistory(); //есть анимация //вот эта часть начинает выполняться сразу после запуска анимации //не дожидаясь результата работы onAnimationEnd() if (getCountNumbers(numberField) < 11) { if (getNumberField().equals("0")) { String temp = "0." + s; numberField.setText(temp); } else { String temp = getNumberField() + s; numberField.setText(temp); } } } 

Methods with animation are called in many places of the program. Often, after calling these methods, other code follows, which starts before the animation ends. And I need him to wait, because the onAnimationEnd () blocks execute what needs to be completed before executing further code.

Moving the entire code to the onAnimationEnd () block is not a solution.

  • Here, stackoverflow.com/questions/5321344/... found something similar to the solution. Create an object to encapsulate the animation lifetime. But not enough knowledge and English to figure out how to use it. Can someone help? - kulikovman

1 answer 1

UPD: Well, let's understand the reasons for what is happening:

Immediately after starting the animation, you call the code block:

 //вот эта часть начинает выполняться сразу после запуска анимации //не дожидаясь результата работы onAnimationEnd() if (getCountNumbers(numberField) < 11) { if (getNumberField().equals("0")) { String temp = "0." + s; numberField.setText(temp); } else { String temp = getNumberField() + s; numberField.setText(temp); } } 

In the documentation they write that the animation is performed in the same thread in which it was called. So why is your code block executed during animation, if the stream is the same?

The point is that the animation execution fights on “program frames”, the execution of which is transmitted to the Looper UI stream (hereinafter referred to as the Main stream). Each frame of the animation is called in the Main thread sequentially, but not necessarily continuously one after the other. Different animations of several View elements occur as if simultaneously, because such frames are mixed and sequentially executed over a frame from each animation.

Your code block is also running in the main thread. Most likely even before the first frame of the animation is executed, because your block is already in the Looper main thread, at the time when the first frame of the animation has just been formed and planned.

Now, as for the execution of your block at the end of the animation. You can guarantee to execute your block of code at the end of the animation by running it in your Listener -a method onAnimationEnd .

The difficulty arises only due to the fact that you have 2 animations on 6 View fields. And so in one method, where you have 4 calls of animation will be called 4 times onAnimationEnd , in another method 2 times.

You need to bring your final code block to a separate method, for example, finalMethod() - define the name and signature for yourself. Then determine the end of the last animation, for example by adding a counter.

An example for one of the methods:

 int mAnimationCount; private void clearCalculation() { Animation animation = AnimationUtils.loadAnimation(MainActivity.this, R.anim.dissolution); animation.setAnimationListener(new Animation.AnimationListener() { @Override public void onAnimationStart(Animation animation) { } @Override public void onAnimationEnd(Animation animation) { numberField.setText(" "); operationField.setText(" "); historyField.setText(" "); historyOperation.setText(" "); isPercentCalculation = false; isResult = false; if (--mAnimationCount == 0) { finalMethod(); } } @Override public void onAnimationRepeat(Animation animation) { } }); numberField.startAnimation(animation); operationField.startAnimation(animation); historyField.startAnimation(animation); historyOperation.startAnimation(animation); mAnimationCount = 4; // количество запущенных Вами анимаций } 

This is just an example, I don’t know the features of your code, so pick yourself the most convenient way to determine.

UPD 2: I can not provide an example and the reasons why you can not use the right way, except that you are too lazy to resolve conflicts arising from the simultaneous calling of the onAnimationEnd method of animations. But if it's really too lazy, you can transfer the final code blocks to the execution queue, an example for your question from the comments, how to delay the start of the code for 200 ms:

 private void addNumber(String s) { if (isResult || isError()) clearCalculation(); //есть анимация if (!isEmpty(operationField)) moveToHistory(); //есть анимация new Handler().postDelayed(new Runnable() { @Override public void run() { if (getCountNumbers(numberField) < 11) { if (getNumberField().equals("0")) { String temp = "0." + s; numberField.setText(temp); } else { String temp = getNumberField() + s; numberField.setText(temp); } } } }, 200); // время задержки в миллисекундах 

Of course, this option is less correct if the sequence of the end of the animation and your code block is important, as well as if a large delay between the sequence of these events is unacceptable.

Do not forget that you do not have to create the Handler yourself, you can use it through the nearest View , for example mTextView.postDelayed(...) .

The option of creating a parallel thread seems unnecessary and will incur more problems than trying to resolve possible conflicts in the onAnimationEnd method.

  • This code only works outside the context of another code. And if you run a lot of code, inside of which, for example, the field cleaning method is called, in which the animation of this cleaning is implemented, then you can of course do something at the end of the animation, but the problem remains. The code that is executed "after" begins to be executed during the animation process, which only aggravates the situation, because the fields that need to be cleared before executing the code will in fact be cleared only at the end of the animation. - kulikovman
  • Why so many words, so much text :) In fact, you have one animation on two TextViews. I did not understand anything, but mb Your problem is because of this?) You should come two times End, determine for which TextView it came. - Artilirium
  • I did not write that I have only one animation and two fields in the program, this is just an example. And the program does not end with the execution of the onAnimationEnd () method. Read carefully my addition to the question. - kulikovman
  • Updated the answer - the same thought, but in more detail :) - Artilirium
  • You again reduced everything to the execution of the onAnimationEnd () block. Let's imagine that there is nothing there and you don’t need to count the number of running animations, because it doesn’t affect the essence of the problem. After the animation, in any case, there is another code that is always executed simultaneously with the animation. How can I slow down his performance? For example, at 200ms. I tried to use an alternative thread with a delay and a delayed start, but this either does not work or hangs (in different versions). - kulikovman