I am trying to take a CardView (in a RecycleView) from actual width to 0. I am a newbie in android and in android animations. Could you say me what I am doing wrong?
This is my code:
final View v = cardViewHolder.cv;
int actualWidth = v.getMeasuredWidth();
ValueAnimator anim = ValueAnimator.ofInt(actualWidth, 0);
anim.setRepeatMode(ValueAnimator.REVERSE);
anim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
#Override
public void onAnimationUpdate(ValueAnimator valueAnimator) {
int val = (Integer) valueAnimator.getAnimatedValue();
ViewGroup.LayoutParams layoutParams = v.getLayoutParams();
layoutParams.width = val;
v.setLayoutParams(layoutParams);
}
});
anim.setDuration(R.integer.card_flip_time_full);
anim.start();
With a breakpoint I see that val is always 728 (the width) and never changes. What is my fail?
I solved it:
final View v = cardViewHolder.cv;
int actualWidth = v.getMeasuredWidth();
ValueAnimator anim = ValueAnimator.ofInt(actualWidth, 0);
anim.setRepeatMode(ValueAnimator.REVERSE);
anim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
#Override
public void onAnimationUpdate(ValueAnimator valueAnimator) {
// This needs to be declared as Integer instead of int
v.requestLayout(); // #mhenryk advice
Integer val = (Integer) valueAnimator.getAnimatedValue();
int value = val.intValue(); // Then get the int value
ViewGroup.LayoutParams layoutParams = v.getLayoutParams();
layoutParams.width = value;
v.setLayoutParams(layoutParams);
}
});
anim.setDuration(R.integer.card_flip_time_full);
anim.start();
Related
I'm creating an animation for rail items for Android TV. I combined several animations using Value Animator but animations are really slow and there are a lot of frames skipped. It turns out the even if I play just one animation using Value Animator it causes this type of behavior. And I need to use five animations together. Here's my code:
public void setFocus(boolean hasFocus) {
//If card has focus
if (hasFocus) {
animWidth = ValueAnimator.ofInt(rlMain.getMeasuredWidth(), (int)
Utils.convertDpToPixel(215));
animWidth.addUpdateListener(new
ValueAnimator.AnimatorUpdateListener() {
#Override
public void onAnimationUpdate(ValueAnimator valueAnimator) {
int val = (Integer) valueAnimator.getAnimatedValue();
ViewGroup.LayoutParams layoutParams =
rlMain.getLayoutParams();
layoutParams.width = val;
rlMain.setLayoutParams(layoutParams);
}
});
animHeight = ValueAnimator.ofInt(rlMain.getMeasuredHeight(), (int)
Utils.convertDpToPixel(328));
animHeight.addUpdateListener(new
ValueAnimator.AnimatorUpdateListener() {
#Override
public void onAnimationUpdate(ValueAnimator valueAnimator) {
int val = (Integer) valueAnimator.getAnimatedValue();
ViewGroup.LayoutParams layoutParams =
rlMain.getLayoutParams();
layoutParams.height = val;
rlMain.setLayoutParams(layoutParams);
}
});
animTopMargin = ValueAnimator.ofInt((int) Utils.convertDpToPixel(42),
(int) Utils.convertDpToPixel(12));
animTopMargin.addUpdateListener(new
ValueAnimator.AnimatorUpdateListener() {
#Override
public void onAnimationUpdate(ValueAnimator animation) {
RecyclerView.LayoutParams lp = (RecyclerView.LayoutParams)
rlMain.getLayoutParams();
lp.setMargins(0, (Integer) animation.getAnimatedValue(),
(int) Utils.convertDpToPixel(12), 0);
rlMain.setLayoutParams(lp);
}
});
animTranslationX = ValueAnimator.ofFloat(rlContent.getX(),
rlContent.getX() + 15);
animTranslationX.addUpdateListener(new
ValueAnimator.AnimatorUpdateListener() {
#Override
public void onAnimationUpdate(ValueAnimator animation) {
float xAnimatedValue = (float) animation.getAnimatedValue();
rlContent.setX(xAnimatedValue);
}
});
animTranslationY = ValueAnimator.ofFloat(rlContent.getY(),
rlContent.getY() - 17);
animTranslationY.addUpdateListener(new
ValueAnimator.AnimatorUpdateListener() {
#Override
public void onAnimationUpdate(ValueAnimator animation) {
float yAnimatedValue = (float) animation.getAnimatedValue();
rlContent.setY(yAnimatedValue);
}
});
animatorSet = new AnimatorSet();
animatorSet.playTogether(animWidth, animHeight, animTopMargin,
animTranslationX, animTranslationY);
animatorSet.setDuration(1000);
animatorSet.start();
//Focus shadow visible
rlFocus.setVisibility(View.VISIBLE);
animWidth = null;
animHeight = null;
animTopMargin = null;
animTranslationX = null;
animTranslationY = null;
animatorSet = null;
} else {
animWidth = ValueAnimator.ofInt(rlMain.getMeasuredWidth(), (int)
Utils.convertDpToPixel(185));
animWidth.addUpdateListener(new
ValueAnimator.AnimatorUpdateListener() {
#Override
public void onAnimationUpdate(ValueAnimator valueAnimator) {
int val = (Integer) valueAnimator.getAnimatedValue();
ViewGroup.LayoutParams layoutParams =
rlMain.getLayoutParams();
layoutParams.width = val;
rlMain.setLayoutParams(layoutParams);
}
});
animHeight = ValueAnimator.ofInt(rlMain.getMeasuredHeight(), (int)
Utils.convertDpToPixel(278));
animHeight.addUpdateListener(new
ValueAnimator.AnimatorUpdateListener() {
#Override
public void onAnimationUpdate(ValueAnimator valueAnimator) {
int val = (Integer) valueAnimator.getAnimatedValue();
ViewGroup.LayoutParams layoutParams =
rlMain.getLayoutParams();
layoutParams.height = val;
rlMain.setLayoutParams(layoutParams);
}
});
animTopMargin = ValueAnimator.ofInt((int) Utils.convertDpToPixel(12),
(int) Utils.convertDpToPixel(42));
animTopMargin.addUpdateListener(new
ValueAnimator.AnimatorUpdateListener() {
#Override
public void onAnimationUpdate(ValueAnimator animation) {
RecyclerView.LayoutParams lp = (RecyclerView.LayoutParams)
rlMain.getLayoutParams();
lp.setMargins(0, (Integer) animation.getAnimatedValue(),
(int) Utils.convertDpToPixel(12), 0);
rlMain.setLayoutParams(lp);
}
});
animTranslationX = ValueAnimator.ofFloat(rlContent.getX(),
rlContent.getX() - 15);
animTranslationX.addUpdateListener(new
ValueAnimator.AnimatorUpdateListener() {
#Override
public void onAnimationUpdate(ValueAnimator animation) {
float xAnimatedValue = (float) animation.getAnimatedValue();
rlContent.setX(xAnimatedValue);
}
});
animTranslationY = ValueAnimator.ofFloat(rlContent.getY(),
rlContent.getY() + 17);
animTranslationY.addUpdateListener(new
ValueAnimator.AnimatorUpdateListener() {
#Override
public void onAnimationUpdate(ValueAnimator animation) {
float yAnimatedValue = (float) animation.getAnimatedValue();
rlContent.setY(yAnimatedValue);
}
});
animatorSet = new AnimatorSet();
animatorSet.playTogether(animWidth, animHeight, animTopMargin,
animTranslationX, animTranslationY);
animatorSet.setDuration(1000);
animatorSet.start();
//Set focus shadow invisible with delay
new Handler().postDelayed(new Runnable() {
#Override
public void run() {
rlFocus.setVisibility(View.INVISIBLE);
}
}, 1010);
animWidth = null;
animHeight = null;
animTopMargin = null;
animTranslationX = null;
animTranslationY = null;
animatorSet = null;
}
}
Is there any way to make those animations smooth? Any help would be highly appreciated :)
I am making an animated tutorial for the application. I am using a fragment over the activity to show image view sliding effect. I am using Translate animation to move the image view to the specific view to describe its working, but actually I want to animate the image view to move infinite times after reaching to the view.
Assume that view v is suppose to animate
public void ViewExapand(View v)
{
v.setVisibility(View.VISIBLE);
final int widthSpec = View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED);
final int heightSpec = View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED);
v.measure(widthSpec, heightSpec);
ValueAnimator mAnimator = slideAnimator(0, v.getMeasuredHeight(),v);
mAnimator.start();
}
private ValueAnimator slideAnimator(int start, int end, final View v)
{
ValueAnimator animator = ValueAnimator.ofInt(start, end);
animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
#Override
public void onAnimationUpdate(ValueAnimator valueAnimator) {
//Update Height
int value = (Integer) valueAnimator.getAnimatedValue();
ViewGroup.LayoutParams layoutParams = v.getLayoutParams();
layoutParams.height = value;
v.setLayoutParams(layoutParams);
}
});
return animator;
}
You can also use ObjectAnimator
ObjectAnimator.ofInt(your view, "left", 100, 250)
.setDuration(250)
.start();
I need to expand and collapse CardView size in RecyclerView at run time.
I use RecyclerView to display a list and CardView as RecyclerView Item.
As I am new to this concept please help me.
I have expand on run time. like this,
Setting my view on onCreateView()
descriptionCardView.getViewTreeObserver().addOnPreDrawListener(new ViewTreeObserver
.OnPreDrawListener() {
#Override
public boolean onPreDraw() {
detailProductDescription.getViewTreeObserver().removeOnPreDrawListener(this);
// save the full height
descriptionViewFullHeight = detailProductDescription.getHeight();
// initially changing the height to min height
ViewGroup.LayoutParams layoutParams = descriptionCardView.getLayoutParams();
layoutParams.height = (int) getActivity().getResources().getDimension(R.dimen
.product_description_min_height);
descriptionCardView.setLayoutParams(layoutParams);
return true;
}
});
and onClickingcardview
#OnClick(R.id.detail_product_description)
void onProductDescriptionClicked(View view) {
toggleProductDescriptionHeight();
}
i am setting CardView Height to expand and collapse.
private int descriptionViewFullHeight;
private void toggleProductDescriptionHeight() {
int descriptionViewMinHeight = (int) getActivity().getResources().getDimension(R.dimen
.product_description_min_height);
if (descriptionCardView.getHeight() == descriptionViewMinHeight) {
// expand
ValueAnimator anim = ValueAnimator.ofInt(descriptionCardView.getMeasuredHeightAndState(),
descriptionViewFullHeight);
anim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
#Override
public void onAnimationUpdate(ValueAnimator valueAnimator) {
int val = (Integer) valueAnimator.getAnimatedValue();
ViewGroup.LayoutParams layoutParams = descriptionCardView.getLayoutParams();
layoutParams.height = val;
descriptionCardView.setLayoutParams(layoutParams);
}
});
anim.start();
} else {
// collapse
ValueAnimator anim = ValueAnimator.ofInt(descriptionCardView.getMeasuredHeightAndState(),
descriptionViewMinHeight);
anim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
#Override
public void onAnimationUpdate(ValueAnimator valueAnimator) {
int val = (Integer) valueAnimator.getAnimatedValue();
ViewGroup.LayoutParams layoutParams = descriptionCardView.getLayoutParams();
layoutParams.height = val;
descriptionCardView.setLayoutParams(layoutParams);
}
});
anim.start();
}
}
I'm new to android.
I have the following code:
// layoutParams of type WindowManager.LayoutParams
layoutParams.x = someX;
layoutParams.y = someY;
windowManager.updateViewLayout(someView, layoutParams);
How do I animate this change? Something like translation...
You can use ValueAnimator:
int beginValue = 0;
int endValue = 100;
ValueAnimator animator = ValueAnimator.ofInt(beginValue, endValue);
animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
#Override
public void onAnimationUpdate(ValueAnimator animation) {
WindowManager.LayoutParams layoutParams =
(WindowManager.LayoutParams) view.getLayoutParams();
layoutParams.x = (Integer) animation.getAnimatedValue();
layoutParams.y = (Integer) animation.getAnimatedValue();
getWindowManager().updateViewLayout(view, params);
}
});
animator.start();
Rather use Property Value Holders when animating across x an y.
public void animate(final View v, int startX, int endX, int startY, int endY) {
PropertyValuesHolder pvhX = PropertyValuesHolder.ofInt("x", startX, endX);
PropertyValuesHolder pvhY = PropertyValuesHolder.ofInt("y", startY, endY);
ValueAnimator translator = ValueAnimator.ofPropertyValuesHolder(pvhX, pvhY);
translator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
#Override
public void onAnimationUpdate(ValueAnimator valueAnimator) {
WindowManager.LayoutParams layoutParams = (WindowManager.LayoutParams) v.getLayoutParams();
layoutParams.x = (Integer) valueAnimator.getAnimatedValue("x");
layoutParams.y = (Integer) valueAnimator.getAnimatedValue("y");
windowManager.updateViewLayout(v, layoutParams);
}
});
translator.setDuration(100);
translator.start();
}
The easiest solution I've found to similar problem is shown here: https://www.youtube.com/watch?v=55wLsaWpQ4g
In my case I have a RelativeLayout and want to change its android:layout_below value programmatically (it's parent is also RelativeLayout).
So in onCreate I've put:
LayoutTransition layoutTransition = rlListLayout.getLayoutTransition();
layoutTransition.enableTransitionType(LayoutTransition.CHANGING);
and then for example in onClick method changed layout params:
RelativeLayout.LayoutParams params = (RelativeLayout.LayoutParams) rl.getLayoutParams();
params.addRule(RelativeLayout.BELOW, R.id.dummy);
rl.setLayoutParams(params);
That's it. 5 lines of code and no need to calculate position nor measure anything.
I have a view (customView) added to the WindowManager.
WindowManager mWm = (WindowManager)activity.getApplicationContext().getSystemService(Context.WINDOW_SERVICE);
WindowManager.LayoutParams(WindowManager.LayoutParams.FILL_PARENT, 0, PixelFormat.TRANSPARENT);
mWl.dimAmount = 0.0f;
mWm.addView(customView, mWl);
Inside the custom view, I will call a translate animation when close button is pressed.
//// This is the handler for the animation ////
final Handler translateHandler = new Handler();
final Runnable mtranslateUp = new Runnable() {
public void run() {
Log.v("TEST","mtranslateUp Runnable");
startAnimation(translateUp);
}
};
//// This is the listener for the close button////
View.OnClickListener closeButtonListener = new View.OnClickListener() {
public void onClick(View v) {
translateHandler.post(mtranslateUp);
}
};
//// This is the translate up animation ////
translateUp = new TranslateAnimation(0,0,0,-200);
translateUp.setFillAfter(true);
translateUp.setDuration(1000);
translateUp.setAnimationListener(new AnimationListener(){
#Override
public void onAnimationEnd(Animation animation) {
Log.v("TEST","translateUp onAnimationEnd");
}
#Override
public void onAnimationRepeat(Animation animation) {
}
#Override
public void onAnimationStart(Animation animation) {
Log.v("TEST","translateUp onAnimationStart");
}}
);
If the customView is added to an activity, these code works fine!
When the customView is added to a WindowManager, the Log inside the onAnimationStart didn't show but the Log inside the Runnable can be shown.
Can anybody tells how to do animation on a view that is added to the WindowManager?
You should animate the view LayoutParameters. For example I use a method to update the view layout:
public void updateViewLayout(View view, Integer x, Integer y, Integer w, Integer h){
if (view!=null) {
WindowManager.LayoutParams lp = (WindowManager.LayoutParams) view.getLayoutParams();
if(x != null)lp.x=x;
if(y != null)lp.y=y;
if(w != null && w>0)lp.width=w;
if(h != null && h>0)lp.height=h;
mWindowService.updateViewLayout(view, lp);
}
}
Obviously mWindowService is context.getSystemService(Context.WINDOW_SERVICE).
I trigger this method in the animation:
public static void overlayAnimation(final View view2animate, int viewX, int endX) {
ValueAnimator translateLeft = ValueAnimator.ofInt(viewX, endX);
translateLeft.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
#Override
public void onAnimationUpdate(ValueAnimator valueAnimator) {
int val = (Integer) valueAnimator.getAnimatedValue();
updateViewLayout(view2animate, val, null, null, null);
}
});
translateLeft.setDuration(ANIMATION_DURATION);
translateLeft.start();
}
I was facing similar problem with a View attached to WindowManager.Try adding ViewGroup to WindoManager than View directly. It should work.
windowManager need a animation by android system. so the custom animation will not work
I had a problem.
When i use updateViewLayout in onAnimationUpdate, and i set the LayoutParams's width, the animation has dropped frames.
But i set the LayoutParams's x or y, the animation is ok.
like the below code:
mViewWidth = 800;
mViewHeight = 800;
final int oldX = mFloatWindowParams.x;
final int oldWidth = mFloatWindowParams.width;
final int oldHeight = mFloatWindowParams.height;
final int deltaWidth = mViewWidth - oldWidth;
final int deltaHeight = mViewHeight - oldHeight;
final boolean isWidthLarger = deltaWidth > deltaHeight;
int first = isWidthLarger ? oldWidth : oldHeight;
int end = isWidthLarger ? mViewWidth : mViewHeight;
ValueAnimator va = ValueAnimator.ofInt(first, end);
va.setDuration(1000);
va.setInterpolator(new LinearInterpolator());
va.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
public void onAnimationUpdate(ValueAnimator animation) {
int value = (Integer) animation.getAnimatedValue();
float fraction = animation.getAnimatedFraction();
Log.i("onAnimationUpdate", value + "");
if (isWidthLarger) {
mFloatWindowParams.width = value;
mFloatWindowParams.height = oldHeight + (int) (deltaHeight * fraction);
} else {
mFloatWindowParams.width = oldWidth + (int) (deltaWidth * fraction);
mFloatWindowParams.height = value;
}
mFloatWindowParams.x = oldX - (int) (deltaWidth * fraction);
mWindowManager.updateViewLayout(mRootView, mFloatWindowParams);
}
});
va.start();