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();
Related
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
I know how it can be applied to the toolbar w.r.t. any scrollView in Coordinator layout.
I wanna do the same thing with the button w.r.t. RecycleView.
Just like the bottomNav in the app Pinterest.
Thanks!
A simple way that comes to mind is to use the TranslateAnimation provided by Android and to check if the RecyclerView is being scrolled. Here is what you need to do
Add a scroll listener to the RecyclerView and check if the scrolling direction is downward or upward
YourRecyclerView.addScrollListener(new ScrollListener() {
someScrollListenerMethod() {
if (scrolling up) {
showButton();
} else {
hideButton();
}
}
);
Create an animation for sliding the button up and down.
slideDownAnimation = TranslateAnimation(0f, 0f, 0f, ScreenHeight)
slideDownAnimation.duration = 1000f //1 second
slideUpAnimation = TranslateAnimation(0f, 0f, ScreenHeight, 0f)
slideUpAnimation.duration = 1000f //1 second
Create the show and hide button methods which will show and hide the button
private void showButton() {
yourButton.visibility = View.VISIBLE;
yourButton.startAnimation(slideUpAnimation);
}
private void hideButton() {
yourButton.visibility = View.INVISIBLE;
yourButton.startAnimation(slideDownAnimation);
}
Just a note, the code shared in step 1 is not the actual library code (I could not remember the exact code) but you can easily find it out.
Here's the applied code as explained by Bilal. Just in case anybody need it,
private void buttonSlideAnimation() {
addButton = findViewById(R.id.bottom_add_button);
DisplayMetrics displayMetrics = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(displayMetrics);
int height = displayMetrics.heightPixels;
final TranslateAnimation slideDownAnimation = new TranslateAnimation(0f, 0f, 0f, height);
final TranslateAnimation slideUpAnimation = new TranslateAnimation(0f, 0f, height, 0f);
slideDownAnimation.setDuration(1000);
slideUpAnimation.setDuration(1000);
recyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {
#Override
public void onScrollStateChanged(#NonNull RecyclerView recyclerView, int newState) {
super.onScrollStateChanged(recyclerView, newState);
}
#Override
public void onScrolled(#NonNull RecyclerView recyclerView, int dx, int dy) {
super.onScrolled(recyclerView, dx, dy);
if (dy>0){
addButton.setVisibility(View.INVISIBLE);
addButton.startAnimation(slideDownAnimation);
} else {
addButton.setVisibility(View.VISIBLE);
addButton.startAnimation(slideUpAnimation);
}
}
});
}
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
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
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;