How to animate LayoutParams x and y in Android - android

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.

Related

Animation set view width from X to 0

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();

Camera Preview Overlay Animation Performance Issue

I am wondering how do we do this properly.
I have seen some apps that does this and the animation is smooth.
Above my camera preview.
I put an ImageView, and then I animate the ImageView's bottom margin. But I can see that the animation is laggy and stuttering.
Here is how I do the animation
final RelativeLayout.LayoutParams params = (RelativeLayout.LayoutParams) imageView.getLayoutParams();
fromValue = dpToPx(fromValue);
toValue = dpToPx(toValue);
final ValueAnimator valueAnimator = ValueAnimator.ofInt(fromValue, toValue);
valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
#Override
public void onAnimationUpdate(ValueAnimator valueAnimator) {
params.bottomMargin = (Integer) valueAnimator.getAnimatedValue();
imageView.requestLayout();
}
});
valueAnimator.setDuration(duration);
valueAnimator.setInterpolator(timeInterpolator);
Any ideas?

How to animate a view programatically in android?

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();

Android: how to expand and collapse cardView size in RecyclerView

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();
}
}

Transform a ImageView while moving animation (keep ratio)

I'm making an animation that a View moving and transform it self to another form at the same time.
Here is animation description:
I don't know how to do it. Any solution for me?
Any advice is appreciated.
=================================================================
UPDATE
I've tried TranslateAnimation + ScaleAnimation with AnimationSet but my ImageView scaled very urgly.
Here is start image, using centerCrop:
Here is result of Translate + ScaleAnimation:
But this is result that I want (centerCrop with same src above):
How to transform + moving but keep image ratio like that ? I don't want my image ratio changed.
Thanks for help.
Here's what you can expect from this answer:
Also note that the code provided here was written for test purposes, and thus isn't optimized.
I have used Animator (available for api >= 11) to achieve the effect you have described as I don't find TranslateAnimation and ScaleAnimation 'good' enough in terms of outcome.
There are 3 things happening here:
width is changing
height is changing
'x' value for the imageview is changing
You will need to provide the final values for these 3 parameters: finalWidth, finalHeight and final X placement.
We will use valueAnimator to get animated values for the width and height on every update, and then use these values to update the LayoutParams of ImageView.
The animate button (in the gif above) calls the following method:
public void animate() {
// This is to get the screen dimensions
final Point p = new Point();
getWindowManager().getDefaultDisplay().getSize(p);
// First, define the starting values
final int startingWidth = mImageView.getWidth();
final int startingHeight = mImageView.getHeight();
final int startingXValue = mImageView.getX():
// Next, define the final values
// For this example, the final width will be half of screen-width
final int finalWidth = p.x / 2;
// Just an arbitrary final value for height. You will have to decide
// what the final height should be
final int finalHeight = p.y - ivv.getTop() - 300;
// final `X` placement of the imageview
int finalXValue = p.x / 2 - finalWidth / 2;
// ValueAnimator to generate changes in width
final ValueAnimator vaW = ValueAnimator.ofInt(startingWidth, finalWidth);
vaW.addUpdateListener(new AnimatorUpdateListener() {
#Override
public void onAnimationUpdate(ValueAnimator animation) {
// Get animated width value update
int newWidth = (int) vaW.getAnimatedValue();
// Get and update LayoutParams from imageview
LinearLayout.LayoutParams lp = (LinearLayout.LayoutParams)
mImageView.getLayoutParams();
lp.width = newWidth;
mImageView.setLayoutParams(lp);
}
});
// ValueAnimator to generate changes in height
final ValueAnimator vaH = ValueAnimator.ofInt(startingHeight, finalHeight);
vaW.addUpdateListener(new AnimatorUpdateListener() {
#Override
public void onAnimationUpdate(ValueAnimator animation) {
// Get animated height value update
int newHeight = (int) vaH.getAnimatedValue();
// Get and update LayoutParams from imageview
LinearLayout.LayoutParams lp = (LinearLayout.LayoutParams)
mImageView.getLayoutParams();
lp.height = newHeight;
mImageView.setLayoutParams(lp);
}
});
// Used to provide translate animation
ObjectAnimator oa = ObjectAnimator.ofFloat(
mImageView, "X", startingXValue,
finalXValue);
// To play these 3 animators together
AnimatorSet as = new AnimatorSet();
as.playTogether(vaW, vaH, oa);
as.setDuration(5000);
as.start();
}
The layout used for the activity in this example is nothing special:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:background="#android:color/holo_blue_dark" >
<Button
android:id="#+id/bAnimate"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="animate"
android:layout_gravity="center_horizontal" />
<ImageView
android:id="#+id/ivToAnimate"
android:layout_width="100dp"
android:layout_height="100dp"
android:text="animate"
android:layout_gravity="right"
android:src="#drawable/index"
android:scaleType="centerCrop" />
</LinearLayout>
Edit: To reset ImageView's position, size & scale:
Declare starting and final values as class variables:
int startingWidth, startingHeight, startingXValue,
finalWidth, finalHeight, finalXValue;
// this method will only be called ONCE.
// Use appropriate values to initialize starting and final values
public void initialize() {
final Point p = new Point();
getWindowManager().getDefaultDisplay().getSize(p);
startingWidth = mImageView.getWidth();
startingHeight = mImageView.getHeight();
startingXValue = mImageView.getX():
finalWidth = p.x / 2;
finalHeight = p.y - ivv.getTop() - 300;
finalXValue = p.x / 2 - finalWidth / 2;
}
// Call this method whenever you need to animate forward
// `animate()` method // refer above for comments
public void animate() {
final ValueAnimator vaW = ValueAnimator.ofInt(startingWidth, finalWidth);
vaW.addUpdateListener(new AnimatorUpdateListener() {
#Override
public void onAnimationUpdate(ValueAnimator animation) {
int newWidth = (int) vaW.getAnimatedValue();
LinearLayout.LayoutParams lp = (LinearLayout.LayoutParams)
mImageView.getLayoutParams();
lp.width = newWidth;
mImageView.setLayoutParams(lp);
}
});
final ValueAnimator vaH = ValueAnimator.ofInt(startingHeight, finalHeight);
vaW.addUpdateListener(new AnimatorUpdateListener() {
#Override
public void onAnimationUpdate(ValueAnimator animation) {
int newHeight = (int) vaH.getAnimatedValue();
LinearLayout.LayoutParams lp = (LinearLayout.LayoutParams)
mImageView.getLayoutParams();
lp.height = newHeight;
mImageView.setLayoutParams(lp);
}
});
ObjectAnimator oa = ObjectAnimator.ofFloat(
mImageView, "X", startingXValue,
finalXValue);
AnimatorSet as = new AnimatorSet();
as.playTogether(vaW, vaH, oa);
as.setDuration(5000);
as.start();
}
Animate back:
// `animateBack()` method // similar execution to `animate()`
// Notice how the starting and final values have been switched
public void animateBack() {
final ValueAnimator vaW = ValueAnimator.ofInt(finalWidth, startingWidth);
vaW.addUpdateListener(new AnimatorUpdateListener() {
#Override
public void onAnimationUpdate(ValueAnimator animation) {
int newWidth = (int) vaW.getAnimatedValue();
LinearLayout.LayoutParams lp = (LinearLayout.LayoutParams)
mImageView.getLayoutParams();
lp.width = newWidth;
mImageView.setLayoutParams(lp);
}
});
final ValueAnimator vaH = ValueAnimator.ofInt(finalHeight, startingHeight);
vaW.addUpdateListener(new AnimatorUpdateListener() {
#Override
public void onAnimationUpdate(ValueAnimator animation) {
int newHeight = (int) vaH.getAnimatedValue();
LinearLayout.LayoutParams lp = (LinearLayout.LayoutParams)
mImageView.getLayoutParams();
lp.height = newHeight;
mImageView.setLayoutParams(lp);
}
});
ObjectAnimator oa = ObjectAnimator.ofFloat(
mImageView, "X", finalXValue, startingXValue);
AnimatorSet as = new AnimatorSet();
as.playTogether(vaW, vaH, oa);
as.setDuration(5000);
as.start();
}
first link is to create a set of animtions.
second link - Animation for Translate.
third link - Animation for Scaling.
create the translate and scaling animation add them to the Animationset
AnimationSet
TranslateAnimation
ScaleAnimation
To keep the same ratio in the ImageView, try to use these attributes:
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:scaleType="centerInside"
android:src="#drawable/your_image" />

Categories

Resources