Currently I set background of a LinearLayout using
BitmapDrawable bd = new BitmapDrawable(getResources(), mBlurredMap);
mLytProfileCover.setBackground(bd);
How can I animation this? For example, a fade-in animation where the background's alpha changes from 0 to 1 in 500ms.
Thanks.
ObjectAnimator alphaAnimator = ObjectAnimator.ofFloat(mLytProfileCover, View.ALPHA, 0.0f, 1.0f);
alphaAnimator.addListener(new AnimatorListenerAdapter() {
#Override
public void onAnimationStart(final Animator animation) {
mLytProfileCover.setBackground(bd);
}
});
alphaAnimator.setDuration(500);
alphaAnimator.start();
Related
I want an ImageView to be rotating all the time and make it bounce when the user clicks on it.
I have both animations but I can't start the bouncing animation without stopping the rotating one.
I don't want to start both animations at once.
Here is what I have.
AnimationSet doesn't seem to be what I need as the second animation has to start on click while the first one is running.
Does anybody know how to do this?
Thank you pskink, it works fine!
Here is the working code:
private ImageView rotating_image;
private AnimatorSet bounceAnimatorSet;
private ObjectAnimator rotationAnimator;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
...
rotating_image = (ImageView) findViewById(R.id.rotating_image);
if (rotating_image != null)
rotating_image.setOnClickListener(this);
setRotation();
rotationAnimator.start();
setBounceAnimators();
...
}
private void setRotation(){
rotationAnimator = ObjectAnimator.ofFloat(rotating_image, "rotation",0,360);
rotationAnimator.setDuration(4000);
rotationAnimator.setRepeatCount(ValueAnimator.INFINITE);
rotationAnimator.setRepeatMode(ValueAnimator.RESTART);
rotationAnimator.setInterpolator(new LinearInterpolator());
}
private void setBounceAnimators(){
bounceAnimatorSet = new AnimatorSet();
ObjectAnimator enlargeX = ObjectAnimator.ofFloat(rotating_image, "scaleX",1,1.5f);
enlargeX.setDuration(800);
enlargeX.setInterpolator(new LinearInterpolator());
ObjectAnimator enlargeY = ObjectAnimator.ofFloat(rotating_image, "scaleY",1,1.5f);
enlargeY.setDuration(800);
enlargeY.setInterpolator(new LinearInterpolator());
ObjectAnimator bounceX = ObjectAnimator.ofFloat(rotating_image, "scaleX", 1.5f, 1);
bounceX.setDuration(1000);
bounceX.setInterpolator(new BounceInterpolator());
ObjectAnimator bounceY = ObjectAnimator.ofFloat(rotating_image, "scaleY", 1.5f, 1);
bounceY.setDuration(1000);
bounceY.setInterpolator(new BounceInterpolator());
bounceAnimatorSet.play(enlargeX).with(enlargeY);
bounceAnimatorSet.play(bounceY).with(bounceX).after(enlargeY);
}
I am trying to implement an enlarge animation like it is in WhatsApp. I have a ListView where I have an ImageView at the left of each ListView item. A click on the ImageView should enlarge the image and show it in the middle (almost full screen width).
I tried the Android developer guide suggestion but it did not work for me. So I googled a little bit but could not find "the perfect answer". Here is what I got so far.
private void enlargeProfilePicture(View view, Drawable drawable, View convertView) {
fullScreenImageView.setImageDrawable(drawable);
Animation scale = new ScaleAnimation(
0f, 1f, 0f, 1f, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f);
scale.setDuration(1000);
final Rect startBounds = new Rect();
final Rect finalBounds = new Rect();
final Point globalOffset = new Point();
convertView.getGlobalVisibleRect(startBounds);
rootView.getGlobalVisibleRect(finalBounds, globalOffset);
finalBounds.offset(-globalOffset.x, -globalOffset.y);
Animation translate
= new TranslateAnimation(startBounds.left,
finalBounds.left,
startBounds.top,
finalBounds.top);
translate.setInterpolator(new AnticipateInterpolator());
translate.setDuration(1000);
// Animation set to join both scaling and moving
AnimationSet animSet = new AnimationSet(true);
animSet.setFillEnabled(true);
animSet.addAnimation(scale);
animSet.addAnimation(translate);
// Launching animation set
animSet.setAnimationListener(new Animation.AnimationListener() {
#Override
public void onAnimationStart(Animation animation) {
fullScreenImageView.setVisibility(View.VISIBLE);
}
#Override
public void onAnimationEnd(Animation animation) {
}
#Override
public void onAnimationRepeat(Animation animation) {
}
});
fullScreenImageView.startAnimation(animSet);
}
So root is the container in which my ListView is defined, fullScreenImageView is the ImageView which is showing the Drawable in its enlarged way, convertView is the view inside the ListView (the ListView item itself) and view is the ImageView clicked on.
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="#+id/root">
<ListView
android:id="#+id/list"
android:layout_width="match_parent"
android:layout_height="match_parent" />
<ImageView
android:id="#+id/full_size_profile_picture"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:visibility="invisible"/>
</RelativeLayout>
So basically what is going wrong is the translation. How can I find the right starting and ending coordinates for the translation? The scaling animation is working fine.
I'd use Animator rather than Animation.
Animator scaleX = ObjectAnimator.ofFloat(view, View.SCALE_X, 2f);
Animator scaleY = ObjectAnimator.ofFloat(view, View.SCALE_Y, 2f);
AnimatorSet animSet = new AnimatorSet();
animSet.setDuration(300).setInterpolator(new AccelerateDecelerateInterpolator());
animSet.playTogether(scaleX, scaleY);
animSet.start();
Animator is better than Animation, because it modifies the view's properties. Animation just modifies the appearance, but not the view itself.
Use that code if your app's minSdk is higher or equal to 14.
If your app requires at least sdk 11 use this one:
Animator scaleX = ObjectAnimator.ofFloat(view, "scaleX", 2f);
Animator scaleY = ObjectAnimator.ofFloat(view, "scaleY", 2f);
Alright, I fixed the issue. The problem was with how I used the animation constructors. I do not know where I got the code from but I just used it from somewhere else it obviously was working but not for my case. Here is one working example.
private void enlargeProfilePicture(View view, Drawable drawable) {
// view is the ImageView holding the image inside one ListView item
fullScreenImageView.setImageDrawable(drawable);
Animation scale = new ScaleAnimation(0f, 1f, 0f, 1f);
scale.setDuration(1000);
scale.setInterpolator(new LinearInterpolator());
final Rect startBounds = new Rect();
final Rect finalBounds = new Rect();
final Point globalOffset = new Point();
view.getGlobalVisibleRect(startBounds);
rootView.getGlobalVisibleRect(finalBounds, globalOffset);
finalBounds.offset(-globalOffset.x, -globalOffset.y);
Animation translate
= new TranslateAnimation(Animation.ABSOLUTE, startBounds.left + view.getWidth()/2,
Animation.ABSOLUTE, finalBounds.left,
Animation.ABSOLUTE, startBounds.top - view.getHeight()/2,
Animation.ABSOLUTE, finalBounds.top);
translate.setInterpolator(new LinearInterpolator());
translate.setDuration(1000);
// Animation set to join both scaling and moving
AnimationSet animSet = new AnimationSet(true);
animSet.setFillEnabled(true);
animSet.addAnimation(scale);
animSet.addAnimation(translate);
// Launching animation set
animSet.setAnimationListener(new Animation.AnimationListener() {
#Override
public void onAnimationStart(Animation animation) {
fullScreenImageView.setVisibility(View.VISIBLE);
}
#Override
public void onAnimationEnd(Animation animation) {
}
#Override
public void onAnimationRepeat(Animation animation) {
}
});
fullScreenImageView.startAnimation(animSet);
}
I am trying to make an combined animation where a view is first moved (TranslateAnimation) and then hidden/revealed (createCircularReveal Animator)(like here). Rigth now, I am accomplishing it by starting the animator after the animation with the onAnimationEnd callback. But the thing is, it does not start right away but is delayed for like half a second which makes it look less smooth.
Is this even the right aaproach to do this, or is there another way to create such an move + property animation?
Is there may be a way to adjust the onAnimationEnd callback so that it really start rigth away?
EDIT: here my final code:
...
final Animator circularReveal = ViewAnimationUtils.createCircularReveal(
....
);
circularReveal.setDuration(3500);
circularReveal.setInterpolator(new AnimationUtils().loadInterpolator(YourWorkouts.this,
android.R.interpolator.linear_out_slow_in));
circularReveal.addListener(new AnimatorListenerAdapter() {
#Override
public void onAnimationStart(Animator animation) {
super.onAnimationStart(animation);
createNewWorkoutDialogCardView.setVisibility(View.VISIBLE);
}
});
final Animator circularHide = ViewAnimationUtils.createCircularReveal(
...
);
circularHide.setDuration(600);
circularHide.setInterpolator(new AnimationUtils().loadInterpolator(YourWorkouts.this,
android.R.interpolator.linear_out_slow_in));
circularHide.addListener(new AnimatorListenerAdapter() {
#Override
public void onAnimationEnd(Animator animation) {
super.onAnimationEnd(animation);
Log.v("YourWorkouts", "onAnimationEnd: set FAB INVISIBLE");
createWorkoutFab.setVisibility(View.GONE);
}
});
final AnimatorSet animSet = new AnimatorSet();
animSet.playTogether(circularHide,circularReveal);
animSet.setStartDelay(300); // the animator waits only 0.3 seconds
Integer fabTranslationDistanceX = fabEndPositionX - (createNewWorkoutFABContainer.getLeft() + createNewWorkoutFABContainer.getWidth()/2);
Integer fabTranslationDistanceY = fabEndPositionY - createWorkoutFab.getHeight()/2 - (createNewWorkoutFABContainer.getTop() + createNewWorkoutFABContainer.getHeight()/2);
Log.v("YourWorkouts", "xDialogCenter" + fabTranslationDistanceX);
TranslateAnimation moveFAB = new TranslateAnimation(0, fabTranslationDistanceX, 0, fabTranslationDistanceY);
moveFAB.setDuration(500); // the translation takes 0.5 seconds
moveFAB.setFillAfter(true);
moveFAB.setInterpolator(new AnimationUtils().loadInterpolator(YourWorkouts.this,
android.R.interpolator.fast_out_linear_in));
animSet.start(); // start animator for property animation
createNewWorkoutFABContainer.startAnimation(moveFAB); // start animation to move view across the screen
you could try this:
anim1 will be the 1st animation, with a duration of 300 ms and anim2 will start after 300 ms
TranslateAnimation anim1 = new TranslateAnimation();
Animator anim2 = ViewAnimationUtils.createCircularReveal(myView, cx, cy, 0, finalRadius);
anim1.setDuration(300);
anim2.setDuration(300);
anim2.setStartOffset(300);
I am trying to make a ProgressWheel where the color change as the wheel fill up (the wheel start green at 0% and finish red at 100% with all the wheel become red over the time : not a rainbow).
So I am using an ObjectAnimator, the wheel take the entry color but I cannot manage to make it change color over time...
final ObjectAnimator animator = ObjectAnimator.ofInt(progressBar, "barColor", Color.GREEN, Color.RED);
animator.setDuration(remainingTime);
animator.setEvaluator(new ArgbEvaluator());
animator.setInterpolator(new DecelerateInterpolator(2));
animator.start();
Any idea?
I finally did this (it comes from another post on StackOverflow):
final ObjectAnimator colorAnimator = ObjectAnimator.ofObject(progressBar, "barColor", new ArgbEvaluator(), green, red);
colorAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
#Override
public void onAnimationUpdate(ValueAnimator animation) {
progressBar.refreshWheel();
}
});
colorAnimator.setInterpolator(new DecelerateInterpolator());
colorAnimator.setDuration(remainingTime);
colorAnimator.start();
and in ProgressWheel.java
public void refreshWheel() {
setupPaints();
}
I applyed a TranslateAnimation to an EditText with the FillAfter=true in order to keep its position at the end of the animation.
The animation works properly but the problem is that I can't enter to the edittext anymore.
I think it's due to the fact that the animation affects only the rendering without modifying the actual view coordinates.
Is there any possibility to maintain the final coordinates with the edittext normally working?
Thanks,
Daniele
Unfotunately the animation only renders the raw pixels of the animated element, but not its "android-intern" position. The best solution (that i am able to come up with) is to use an AnimationListener and set the position of the animated element correctly after the animation has finished. Here is my code to slideDown a searchWrapper:
public void toggleSearchWrapper() {
AnimationSet set = new AnimationSet(true);
// slideDown Animation
Animation animation = new TranslateAnimation(
Animation.RELATIVE_TO_SELF, 0.0f, Animation.RELATIVE_TO_SELF, 0.0f,
Animation.RELATIVE_TO_SELF, 0.0f, Animation.RELATIVE_TO_SELF, 1.0f
);
animation.setDuration(300);
animation.setFillEnabled(false);
animation.setAnimationListener(new AnimationListener() {
#Override
public void onAnimationStart(final Animation anim) {
};
#Override
public void onAnimationRepeat(final Animation anim) {
};
#Override
public void onAnimationEnd(final Animation anim) {
// clear animation to prevent flicker
searchWrapper.clearAnimation();
// set new "real" position of wrapper
RelativeLayout.LayoutParams lp = new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.FILL_PARENT, RelativeLayout.LayoutParams.WRAP_CONTENT);
lp.addRule(RelativeLayout.BELOW, R.id.branchFinderIncludeHeader);
searchWrapper.setLayoutParams(lp);
}
});
set.addAnimation(animation);
// set and start animation
searchWrapper.startAnimation(animation);
}