Animating Fab on click (zoom in/out) - java

I am trying to mimic animation and the color change for the following floating action button.
The way the floating action button works is white is off and blue is on.
However, I have been unsuccessful with the animation and changing the color.
These have been my attempts at doing this, as you can see I have commented out all the different ways I have tried to do this.
This is my code:
#SuppressWarnings("unused")
#OnClick(R.id.fabMovieFavourite)
public void addMovieFavourite(View view) {
/* final Animator animator = AnimatorInflater.loadAnimator(getActivity(), R.animator.add_favourite_movie);
animator.setTarget(view);)
animator.start();
*/
/*
AnimatorSet animatorSet = new AnimatorSet();
PropertyValuesHolder propertyValuesHolderX = PropertyValuesHolder.ofFloat(View.SCALE_X, 1.1f);
PropertyValuesHolder propertyValuesHolderY = PropertyValuesHolder.ofFloat(View.SCALE_Y, 1.1f);
ObjectAnimator objectAnimator = ObjectAnimator.ofPropertyValuesHolder(view, propertyValuesHolderX, propertyValuesHolderY);
objectAnimator.setDuration(300);
objectAnimator.setInterpolator(new OvershootInterpolator(10f));
*/
/*
objectAnimator.setRepeatCount(1);
objectAnimator.setRepeatMode(ObjectAnimator.REVERSE);
*/
/*
PropertyValuesHolder propertyValuesHolderX2 = PropertyValuesHolder.ofFloat(View.SCALE_X, 0.9f);
PropertyValuesHolder propertyValuesHolderY2 = PropertyValuesHolder.ofFloat(View.SCALE_Y, 0.9f);
ObjectAnimator objectAnimator2 = ObjectAnimator.ofPropertyValuesHolder(view, propertyValuesHolderX2, propertyValuesHolderY2);
objectAnimator.setDuration(300);
objectAnimator2.setInterpolator(new OvershootInterpolator(10f));
animatorSet.playSequentially(objectAnimator, objectAnimator2);
objectAnimator.start();
*/
// view.BackgroundTintList(ContextCompat.getColorStateList(getContext(), R.color.primary));
//view.setBackgroundColor(ContextCompat.getColor(getActivity(), R.color.primary));
if(Build.VERSION.SDK_INT > Build.VERSION_CODES.LOLLIPOP) {
Timber.d("start translationZ");
ObjectAnimator objectAnimator = ObjectAnimator.ofFloat(view, View.TRANSLATION_Z, 12f);
objectAnimator.setDuration(300);
objectAnimator.setInterpolator(new OvershootInterpolator(10f));
objectAnimator.setTarget(view);
objectAnimator.start();
}
}
Many thanks for any suggestions.

There're two phases in this animation. First one scales X and Y axis, and second one downscales it. So, we can divide them into two AnimatorSets and play them sequentially.
The key point of the animation is to find appropriate interpolator for the second AnimatorSet, because it's not standard one.
See, we want fab to overshoot, then undershoot and then finally settle up to the specified value in the animator.
Luckily, there's very handy PathInterpolator, which will create an interpolator for us with provided Path.
Path path = new Path();
path.moveTo(0.0f, 0.0f);
path.lineTo(0.5f, 1.3f);
path.lineTo(0.75f, 0.8f);
path.lineTo(1.0f, 1.0f);
PathInterpolator pathInterpolator = new PathInterpolator(path);
So, let's create the first animation:
final float from = 1.0f;
final float to = 1.3f;
ObjectAnimator scaleX = ObjectAnimator.ofFloat(fab, View.SCALE_X, from, to);
ObjectAnimator scaleY = ObjectAnimator.ofFloat(fab, View.SCALE_Y, from, to);
ObjectAnimator translationZ = ObjectAnimator.ofFloat(fab, View.TRANSLATION_Z, from, to);
AnimatorSet set1 = new AnimatorSet();
set1.playTogether(scaleX, scaleY, translationZ);
set1.setDuration(100);
set1.setInterpolator(new AccelerateInterpolator());
set1.addListener(new AnimatorListenerAdapter() {
#Override
public void onAnimationEnd(Animator animation) {
fab.setImageResource(isActive ? R.drawable.heart_active : R.drawable.heart_passive);
fab.setBackgroundTintList(ColorStateList.valueOf(isActive ? colorActive : colorPassive));
isActive = !isActive;
}
});
We are scaling both x, y. Also, we are changing z translation to have appropriate shadow effect. When animation ends, we want to change fab state (color of heart and fab background).
Now let's create the animation to settle back:
ObjectAnimator scaleXBack = ObjectAnimator.ofFloat(fab, View.SCALE_X, to, from);
ObjectAnimator scaleYBack = ObjectAnimator.ofFloat(fab, View.SCALE_Y, to, from);
ObjectAnimator translationZBack = ObjectAnimator.ofFloat(fab, View.TRANSLATION_Z, to, from);
AnimatorSet set2 = new AnimatorSet();
set2.playTogether(scaleXBack, scaleYBack, translationZBack);
set2.setDuration(300);
set2.setInterpolator(pathInterpolator);
See here, we used pathInterpolator that we created earlier.
We want to play those two AnimatorSets sequentially:
final AnimatorSet set = new AnimatorSet();
set.playSequentially(set1, set2);
set.addListener(new AnimatorListenerAdapter() {
#Override
public void onAnimationEnd(Animator animation) {
fab.setClickable(true);
}
#Override
public void onAnimationStart(Animator animation) {
fab.setClickable(false);
}
});
Also, we want to disable clicks on fab whilst animating it. So we are turning it on/off depending on animation state.
Finally, we launch the animation when a click happens:
fab.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
set.start();
}
});
Result:
Source code at github

Related

How to delay a line of code after a button press

I am new to Java and am trying to delay one line of code after a user presses a button. The line of code incraments an array, i++. The reason I would like to do this is because I am animating two textViews by fading them. The one textView fades out while the other fades in and I am trying to change the word being displayed by only incrementing my array index after they have the same Alpha which is half of the animations set duration, 500. I have looked online and I have seen some suggesting a swing timer and other suggesting to use thread.sleep. Any suggestions? Here is the code for that button :).
public void nextWord(View view) { //nextWord is the onclick of the button
Button nextButton = findViewById(R.id.nextButton);
Button showTextButton = findViewById(R.id.showTextButton);
TextView wordTextView = findViewById(R.id.wordTextView);
EditText editTextView = findViewById(R.id.enterEditText);
ImageView logoImageView = findViewById(R.id.logoImageView);
TextView wordTextView1 = findViewById(R.id.wordTextView1);
i++; // need to delay this
String displayHint;
String displayText;
displayText = enterWord() + chooseArray();
displayHint = chooseArray();
wordTextView.setText(displayText);
editTextView.setHint(displayHint);
wordTextView1.setText(displayText) ;
enteredWords[i] = editTextView.getText().toString();
if (i%2 == 0) {
ObjectAnimator alphaAnimation = ObjectAnimator.ofFloat(wordTextView, View.ALPHA, 1f, 0f);
alphaAnimation.setDuration(1000);
ObjectAnimator otherAlphaAnimation = ObjectAnimator.ofFloat(wordTextView1, View.ALPHA, 0f, 1f);
otherAlphaAnimation.setDuration(1000);
AnimatorSet animatorSet = new AnimatorSet();
animatorSet.playTogether(otherAlphaAnimation,alphaAnimation);
animatorSet.start();
} else {
ObjectAnimator alphaAnimation = ObjectAnimator.ofFloat(wordTextView, View.ALPHA, 0f, 1f);
alphaAnimation.setDuration(1000);
ObjectAnimator otherAlphaAnimation = ObjectAnimator.ofFloat(wordTextView1, View.ALPHA, 1f, 0f);
otherAlphaAnimation.setDuration(1000);
AnimatorSet animatorSet = new AnimatorSet();
animatorSet.playTogether(otherAlphaAnimation,alphaAnimation);
animatorSet.start();
}
}
Try with
new Handler().postDelayed(Runnable r, long delay)
Use it like
new Handler().postDelayed(new Runnable() {
#Override
public void run() {
// fade in new text view
}
}, 1000); // time needed for first animation to finish
Now, when first animation takes 1000 ms to finish, then second will start after 1000 ms too. You can put it inside final value to manipulate those delays at once to keep them synchronized

How to Bounce or Zoom Animation on press on button [duplicate]

I am trying to mimic animation and the color change for the following floating action button.
The way the floating action button works is white is off and blue is on.
However, I have been unsuccessful with the animation and changing the color.
These have been my attempts at doing this, as you can see I have commented out all the different ways I have tried to do this.
This is my code:
#SuppressWarnings("unused")
#OnClick(R.id.fabMovieFavourite)
public void addMovieFavourite(View view) {
/* final Animator animator = AnimatorInflater.loadAnimator(getActivity(), R.animator.add_favourite_movie);
animator.setTarget(view);)
animator.start();
*/
/*
AnimatorSet animatorSet = new AnimatorSet();
PropertyValuesHolder propertyValuesHolderX = PropertyValuesHolder.ofFloat(View.SCALE_X, 1.1f);
PropertyValuesHolder propertyValuesHolderY = PropertyValuesHolder.ofFloat(View.SCALE_Y, 1.1f);
ObjectAnimator objectAnimator = ObjectAnimator.ofPropertyValuesHolder(view, propertyValuesHolderX, propertyValuesHolderY);
objectAnimator.setDuration(300);
objectAnimator.setInterpolator(new OvershootInterpolator(10f));
*/
/*
objectAnimator.setRepeatCount(1);
objectAnimator.setRepeatMode(ObjectAnimator.REVERSE);
*/
/*
PropertyValuesHolder propertyValuesHolderX2 = PropertyValuesHolder.ofFloat(View.SCALE_X, 0.9f);
PropertyValuesHolder propertyValuesHolderY2 = PropertyValuesHolder.ofFloat(View.SCALE_Y, 0.9f);
ObjectAnimator objectAnimator2 = ObjectAnimator.ofPropertyValuesHolder(view, propertyValuesHolderX2, propertyValuesHolderY2);
objectAnimator.setDuration(300);
objectAnimator2.setInterpolator(new OvershootInterpolator(10f));
animatorSet.playSequentially(objectAnimator, objectAnimator2);
objectAnimator.start();
*/
// view.BackgroundTintList(ContextCompat.getColorStateList(getContext(), R.color.primary));
//view.setBackgroundColor(ContextCompat.getColor(getActivity(), R.color.primary));
if(Build.VERSION.SDK_INT > Build.VERSION_CODES.LOLLIPOP) {
Timber.d("start translationZ");
ObjectAnimator objectAnimator = ObjectAnimator.ofFloat(view, View.TRANSLATION_Z, 12f);
objectAnimator.setDuration(300);
objectAnimator.setInterpolator(new OvershootInterpolator(10f));
objectAnimator.setTarget(view);
objectAnimator.start();
}
}
Many thanks for any suggestions.
There're two phases in this animation. First one scales X and Y axis, and second one downscales it. So, we can divide them into two AnimatorSets and play them sequentially.
The key point of the animation is to find appropriate interpolator for the second AnimatorSet, because it's not standard one.
See, we want fab to overshoot, then undershoot and then finally settle up to the specified value in the animator.
Luckily, there's very handy PathInterpolator, which will create an interpolator for us with provided Path.
Path path = new Path();
path.moveTo(0.0f, 0.0f);
path.lineTo(0.5f, 1.3f);
path.lineTo(0.75f, 0.8f);
path.lineTo(1.0f, 1.0f);
PathInterpolator pathInterpolator = new PathInterpolator(path);
So, let's create the first animation:
final float from = 1.0f;
final float to = 1.3f;
ObjectAnimator scaleX = ObjectAnimator.ofFloat(fab, View.SCALE_X, from, to);
ObjectAnimator scaleY = ObjectAnimator.ofFloat(fab, View.SCALE_Y, from, to);
ObjectAnimator translationZ = ObjectAnimator.ofFloat(fab, View.TRANSLATION_Z, from, to);
AnimatorSet set1 = new AnimatorSet();
set1.playTogether(scaleX, scaleY, translationZ);
set1.setDuration(100);
set1.setInterpolator(new AccelerateInterpolator());
set1.addListener(new AnimatorListenerAdapter() {
#Override
public void onAnimationEnd(Animator animation) {
fab.setImageResource(isActive ? R.drawable.heart_active : R.drawable.heart_passive);
fab.setBackgroundTintList(ColorStateList.valueOf(isActive ? colorActive : colorPassive));
isActive = !isActive;
}
});
We are scaling both x, y. Also, we are changing z translation to have appropriate shadow effect. When animation ends, we want to change fab state (color of heart and fab background).
Now let's create the animation to settle back:
ObjectAnimator scaleXBack = ObjectAnimator.ofFloat(fab, View.SCALE_X, to, from);
ObjectAnimator scaleYBack = ObjectAnimator.ofFloat(fab, View.SCALE_Y, to, from);
ObjectAnimator translationZBack = ObjectAnimator.ofFloat(fab, View.TRANSLATION_Z, to, from);
AnimatorSet set2 = new AnimatorSet();
set2.playTogether(scaleXBack, scaleYBack, translationZBack);
set2.setDuration(300);
set2.setInterpolator(pathInterpolator);
See here, we used pathInterpolator that we created earlier.
We want to play those two AnimatorSets sequentially:
final AnimatorSet set = new AnimatorSet();
set.playSequentially(set1, set2);
set.addListener(new AnimatorListenerAdapter() {
#Override
public void onAnimationEnd(Animator animation) {
fab.setClickable(true);
}
#Override
public void onAnimationStart(Animator animation) {
fab.setClickable(false);
}
});
Also, we want to disable clicks on fab whilst animating it. So we are turning it on/off depending on animation state.
Finally, we launch the animation when a click happens:
fab.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
set.start();
}
});
Result:
Source code at github

how to Ceate ObjectAnimator animation to mp4 Video?

I am trying to Create ObjectAnimator animation to m4 video .
Anybody give me solution ?
ObjectAnimator animation CODE :
public void animation(){
ObjectAnimator fadeOut = ObjectAnimator.ofFloat(aniView, "alpha", 0f);
fadeOut.setDuration(1000);
ObjectAnimator mover = ObjectAnimator.ofFloat(aniView, "translationY", -700f, 0f);
mover.setDuration(1000);
ObjectAnimator fadeIn = ObjectAnimator.ofFloat(aniView, "alpha", 0.8f, 1f);
fadeIn.setDuration(1000);
AnimatorSet animatorSet = new AnimatorSet();
// animatorSet.play(mover).with(fadeIn).after(fadeOut);
animatorSet.play(fadeOut).after(mover).with(fadeIn);
animatorSet.start();
}
You can not create ObjectAnimator to video. You can only animate View that will used to show the video.

Rotate and scale image at same time

I have this code and I want to rotate and scale an ImageView at the same time:
public class LayoutPunteggio extends RelativeLayout {
TextView ok;
LayoutInflater inflater;
RotateAnimation rotateAnimation1;
public LayoutPunteggio(Context context) {
super(context);
inflater = LayoutInflater.from(context);
init();
}
public void init() {
mano = new ImageView(getContext());
mano.setImageResource(R.drawable.mano);
mano.setX(100);
mano.setY(100);
addView(mano);
startScale(mano);
rotate();
}
public void rotate() {
rotateAnimation1.setInterpolator(new LinearInterpolator());
rotateAnimation1.setDuration(1000);
rotateAnimation1.setRepeatCount(-1);
mano.startAnimation(rotateAnimation1);
}
public void startScale(View view){
ScaleAnimation animation;
animation=new ScaleAnimation(1,2,1,2,1000, 1000);
animation.setDuration(1000);
view.startAnimation(animation);
}
}
I tried to apply the method rotate() then startScale(), but this doesn't work for both.
Does anyone have a solution?
You can use a library called NineOldAndroids.
There you have playTogether function of the AnimatorSet.
AnimatorSet animation = new AnimatorSet();
animation.playTogether(
ObjectAnimator.ofFloat(yourImageView, "rotation", 0, 360),
ObjectAnimator.ofFloat(yourImageView, "scaleX", 1, 2f),
ObjectAnimator.ofFloat(yourImageView, "scaleY", 1, 2f)
);
animation.setDuratio(1000);
animation.start();
You can also add a listener
animation.addListener(new AnimationListener(){
onAnimationStart....
onAnimationRepeat...
onAnimationEnd...
onAnimationCancel...
});
You can use this library: https://github.com/Yalantis/uCrop
Just pick the image or code the image path(if you don't want the user to change the image).
I guess you should use AnimationSet:
AnimationSet as = new AnimationSet(true);
// config rotation animation
RotateAnimation ra = new RotateAnimation(...);
ra.setDuration(1000);
...
// config scale animation
ScaleAnimation sa = new ScaleAnimation(...);
sa.setDuration(1000);
...
// Add animations
as.addAnimation(ra);
as.addAnimation(sa);
as.start();
Starting from Honeycomb animations are lot easier to implement, source: ViewPropertyAnimator
For instance changing coordinates of view:
ObjectAnimator animX = ObjectAnimator.ofFloat(myView, "x", 50f);
ObjectAnimator animY = ObjectAnimator.ofFloat(myView, "y", 100f);
AnimatorSet animSetXY = new AnimatorSet();
animSetXY.playTogether(animX, animY);
animSetXY.start();

How do I make a smooth objector animator animation?

When I click the image, I want there to be a smooth object animator animation. Right now it hops to the coordinates, then it animates. Any suggestions? Here's the code:
testImage = (ImageView) findViewById(R.id.testImage);
testImage.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
if (depends) {
anim = ObjectAnimator.ofFloat(testImage, "translationY", 0.f, +90);
anim.setDuration(1000);
anim.start();
depends = false;
} else {
depends = true;
anim = ObjectAnimator.ofFloat(testImage, "translationY", 0.f, -90);
anim.setDuration(1000);
anim.start();
}
}
});
Don't give him a start value, pass only the target value. It will use getTranslationY() to get the start value.
anim = ObjectAnimator.ofFloat(testImage, "translationY", depends ? +90 : -90);
anim.setDuration(1000);
anim.start();
depends = !depends;

Categories

Resources