Issue
I am new in android. So I tried to apply shake animation for wrong answers in a quiz app. But it does not work. I also checked similar questions on this website but I could not find my mistake on my code. In terms of syntax, I guess everything is correct. Could you please help me on this?
'''
package com.example.trivaapp;
import androidx.appcompat.app.AppCompatActivity;
import androidx.databinding.DataBindingUtil;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.view.animation.Animation;
import android.view.animation.AnimationUtils;
import android.widget.Toast;
import com.example.trivaapp.data.Repository;
import com.example.trivaapp.databinding.ActivityMainBinding;
import com.example.trivaapp.model.Question;
import java.util.List;
public class MainActivity extends AppCompatActivity{
List<Question> questionArrayList;
ActivityMainBinding binding;
int questionNumber = 0;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
binding = DataBindingUtil.setContentView(this, R.layout.activity_main);
questionArrayList = new Repository().getQuestionList(az ->{
binding.questionText.setText(az.get(questionNumber).getAnswer());
binding.QuestionNumber.setText(questionNumber + "/" + az.size());
});
binding.trueButton.setOnClickListener(view -> {
if(true == questionArrayList.get(questionNumber).isTruenswer()){
Toast.makeText(MainActivity.this, R.string.correct, Toast.LENGTH_SHORT).show();
}
else{
Toast.makeText(MainActivity.this, R.string.incorrect, Toast.LENGTH_SHORT).show();
ShakeAnimation();
}
});
binding.falseButton.setOnClickListener(view -> {
if(false == questionArrayList.get(questionNumber).isTruenswer()){
Toast.makeText(MainActivity.this, R.string.correct, Toast.LENGTH_SHORT).show();
}
else{
Toast.makeText(MainActivity.this, R.string.incorrect, Toast.LENGTH_SHORT).show();
ShakeAnimation();
}
});
}
private void ShakeAnimation() {
Animation shakeAnimation = AnimationUtils.loadAnimation(MainActivity.this, R.anim.shake);
binding.cardView.setAnimation(shakeAnimation);
}
public void Next(View view) {
questionNumber = (questionNumber < questionArrayList.size()) ? ++questionNumber : questionNumber;
binding.questionText.setText(questionArrayList.get(questionNumber).getAnswer());
binding.QuestionNumber.setText(questionNumber + "/" + questionArrayList.size());
}
}
'''
My shake.xml code:
'''
<?xml version="1.0" encoding="utf-8"?>
<rotate xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="150"
android:fromDegrees="-10"
android:pivotX="10%"
android:pivotY="10%"
android:repeatCount="1"
android:repeatMode="reverse"
android:toDegrees="10"
/>
Solution
Every android View
has a protected property mCurrentAnimation
. You can use methods setAnimation
, getAnimation
and clearAnimation
to access this property and attach/detach animation to a view. Generally, аnimation wont start playing if you just set it.
Let's check startAnimation
code:
public void startAnimation(Animation animation) {
animation.setStartTime(Animation.START_ON_FIRST_FRAME);
setAnimation(animation);
invalidateParentCaches();
invalidate(true);
}
You see? It sets start time for your animation to run next frame (immediately), attaches animation to a view with setAnimation
method and calls invalidate (ask android to redraw this view). Without invalidate, animation could not start.
P.S. This is an old API for animation. Check android dev site for up to date API.
Answered By - Leonidos
Answer Checked By - Clifford M. (JavaFixing Volunteer)