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();
}
}
Related
Here's what I want to achieve.
When I click a FAB button, a menu will toogle display at the bottom of the screen.
When the menu is opened/closed, the map has to be resized so there is no blank space when the menu is animated.
My problem is that when I animate the map's container (ViewPager), the container animates as expected but the map is streched out instead of resizing to the proper dimensions.
I have a ViewPager with a TabLayout that display a fragment per page:
page 1 (google map)
page 2,3 etc..
Here's my toggle menu code:
public void animateFAB(FABStates state) {
if (state.equals(FABStates.show)) {
isFABOpen = true;
viewPager.animate()
.scaleY(1f)
.setInterpolator(INTERPOLATOR)
.setDuration(500);
mapUtilsContainer.animate().scaleY(1f)
.setInterpolator(INTERPOLATOR)
.setDuration(500);
MapView mapV = mapFragment.getMapView();
ViewGroup.LayoutParams lps = mapV.getLayoutParams();
lps.height = ViewGroup.LayoutParams.MATCH_PARENT;
mapV.requestLayout();
// for (int v = 0; v < FABMenu.length; v++) {
// FABMenu[v].animate().translationX(0).setStartDelay(90 * v);
// }
} else {
isFABOpen = false;
mapUtilsContainer.setPivotY(mapUtilsContainer.getMeasuredHeight());
mapUtilsContainer.setPivotX(0);
viewPager.animate()
.scaleY(1.5f)
.setInterpolator(INTERPOLATOR)
.setDuration(500);
mapUtilsContainer.animate()
.scaleY(0f)
.setInterpolator(INTERPOLATOR)
.setDuration(500);
MapView mapV = mapFragment.getMapView();
ViewGroup.LayoutParams lps = mapV.getLayoutParams();
lps.height = ViewGroup.LayoutParams.MATCH_PARENT;
mapV.requestLayout();
// for (int v = 0; v < FABMenu.length; v++) {
// FABMenu[v].animate().translationX(10000).setStartDelay(90 * v);
// }
}
}
Option 2
public void animateFAB(FABStates state) {
if (state.equals(FABStates.show)) {
isFABOpen = true;
ValueAnimator va = ValueAnimator.ofInt(ViewGroup.LayoutParams.WRAP_CONTENT, 0);
va.setDuration(500);
va.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
public void onAnimationUpdate(ValueAnimator animation) {
Integer value = (Integer) animation.getAnimatedValue();
mapUtilsContainer.getLayoutParams().height = value.intValue();
mapUtilsContainer.requestLayout();
}
});
va.start();
View v = findViewById(R.id.coordinator_layout);
v.requestLayout();
// for (int v = 0; v < FABMenu.length; v++) {
// FABMenu[v].animate().translationX(0).setStartDelay(90 * v);
// }
} else {
isFABOpen = false;
ValueAnimator va = ValueAnimator.ofInt(0, ViewGroup.LayoutParams.WRAP_CONTENT);
va.setDuration(500);
va.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
public void onAnimationUpdate(ValueAnimator animation) {
Integer value = (Integer) animation.getAnimatedValue();
mapUtilsContainer.getLayoutParams().height = value.intValue();
mapUtilsContainer.requestLayout();
}
});
va.start();
View v = findViewById(R.id.coordinator_layout);
v.requestLayout();
// for (int v = 0; v < FABMenu.length; v++) {
// FABMenu[v].animate().translationX(10000).setStartDelay(90 * v);
// }
}
}
Is the WRAP_CONTENT used wrongfully here?
I think it is because of scale(). As I have just tested it works fine if you set the height in pixels. Try ValueAnimator to animate height. This way you should take record of opened/closed height of map beforehand. Example:
ValueAnimator va = ValueAnimator.ofInt(oldHeight, newHeight);
va.setDuration(500);
va.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
public void onAnimationUpdate(ValueAnimator animation) {
Integer value = (Integer) animation.getAnimatedValue();
v.getLayoutParams().height = value.intValue();
v.requestLayout();
}
});
Instead of WRAP_CONTENT assign initial height while it is open and use it to reopen:
public void animateFAB(FABStates state) {
if (state.equals(FABStates.show)) {
isFABOpen = true;
initialHeight = mapUtilsContainer.getLayoutParams().height;
ValueAnimator va = ValueAnimator.ofInt(initialHeight, 0);
...
} else {
isFABOpen = false;
ValueAnimator va = ValueAnimator.ofInt(0, initialHeight);
...
}
}
I am trying to increase RecyclerView height on click of Button then decrease it on button click with Animation.
It is increasing and decreasing properly but animation is not working.
Here is my code.
public void expand(View view) {
Button button = (Button) view;
if(button.getText().toString().equalsIgnoreCase("INCREASE")) {
button.setText("DECREASE");
final int height = (int) (recyclerView.getHeight() * 2.5);
Animation a = new Animation() {
#Override
protected void applyTransformation(float interpolatedTime, Transformation t) {
FrameLayout.LayoutParams lp =
new FrameLayout.LayoutParams(RelativeLayout.LayoutParams.MATCH_PARENT, height);
lp.gravity = Gravity.BOTTOM;
recyclerView.setLayoutParams(lp);
}
};
a.setDuration(2000); // in ms
recyclerView.startAnimation(a);
}
else
{
button.setText("INCREASE");
final int height = (int) (recyclerView.getHeight() / 2.5);
Animation a = new Animation() {
#Override
protected void applyTransformation(float interpolatedTime, Transformation t) {
FrameLayout.LayoutParams lp =
new FrameLayout.LayoutParams(RelativeLayout.LayoutParams.MATCH_PARENT, height);
lp.gravity = Gravity.BOTTOM;
recyclerView.setLayoutParams(lp);
}
};
a.setDuration(2000); // in ms
recyclerView.startAnimation(a);
}
}
How do I do it ? I don't want to stretch it. I want to increase its height with some animation effect.
Try using value animator.
ValueAnimator anim = ValueAnimator.ofInt(viewToIncreaseHeight.getMeasuredHeight(), -100);
anim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
#Override
public void onAnimationUpdate(ValueAnimator valueAnimator) {
int val = (Integer) valueAnimator.getAnimatedValue();
ViewGroup.LayoutParams layoutParams = viewToIncreaseHeight.getLayoutParams();
layoutParams.height = val;
viewToIncreaseHeight.setLayoutParams(layoutParams);
}
});
anim.setDuration(DURATION);
anim.start();
I faced a similar issue, i solved it by adding the attribute android:animateLayoutChanges="true" on the container layout in your xml layout description.
As an example:
<LinearLayout
android:id="#+id/container"
android:animateLayoutChanges="true">
<RecyclerView
android:id="#+id/recyclerView"
...
/>
</LinearLayout>
Hope it helps !
I have two recycler views in one screen and in between of them, there is one more button like this.
I want to update the height of recycler view of the upper one to MATCH PARENT with animation, So I had tried this.
binding.moreLl.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
ValueAnimator anim = ValueAnimator.ofInt();
anim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
#Override
public void onAnimationUpdate(ValueAnimator valueAnimator) {
int val = (Integer) valueAnimator.getAnimatedValue();
ViewGroup.LayoutParams layoutParams = binding.fragmentWalletRv.getLayoutParams();
layoutParams.height = val;
binding.fragmentWalletRv.setLayoutParams(layoutParams);
}
});
anim.setDuration(500);
anim.start();
}
});
But unfortunately i cant get the expected result. So please guide me how i can do that thing.
Thanks in advance.
If you just want to have an animation when layout changes, no need to use a custom animation.
Try adding default layout change animation by enabling
android:animateLayoutChanges="true"
to the parent layout in xml.
On your more button click, only change the LayoutParams of the Recyclerview.
To change the speed of animation
LinearLayout layout = mContentView.findViewById(R.id.parent_layout);
LayoutTransition lt = layout.getLayoutTransition();
lt.setDuration(2000);
public class SlideAnimation extends Animation {
int mFromHeight;
int mToHeight;
View mView;
public SlideAnimation(View view, int fromHeight, int toHeight) {
this.mView = view;
this.mFromHeight = fromHeight;
this.mToHeight = toHeight;
}
#Override
protected void applyTransformation(float interpolatedTime, Transformation transformation) {
int newHeight;
if (mView.getHeight() != mToHeight) {
newHeight = (int) (mFromHeight + ((mToHeight - mFromHeight) * interpolatedTime));
mView.getLayoutParams().height = newHeight;
mView.requestLayout();
}
}
#Override
public void initialize(int width, int height, int parentWidth, int parentHeight) {
super.initialize(width, height, parentWidth, parentHeight);
}
#Override
public boolean willChangeBounds() {
return true;
}
}
Use above animation like below
rv1 = findViewById(R.id.rv1);
Animation animation = new SlideAnimation(rv1, rv1.getHeight(), 500);
animation.setInterpolator(new AccelerateInterpolator());
animation.setDuration(500);
rv1.setAnimation(animation);
rv1.startAnimation(animation);
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();
I have a search bar that expands when icon is clicked in toolbar. Now, everything is cool when it is expanded, everything works fine, the thing that is not good is that the height isnt good when the search bar is collapsed. The toolbar upon collapsing search bar has bigger height than it had. Here is the code:
private void expand(View view) {
//set Visible
view.setVisibility(View.VISIBLE);
final int widthSpec = View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED);
final int heightSpec = View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED);
view.measure(widthSpec, heightSpec);
ValueAnimator mAnimator = slideAnimator(0, view.getMeasuredHeight(), view);
mAnimator.start();
}
private ValueAnimator slideAnimator(int start, int end, final View view) {
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 = view.getLayoutParams();
layoutParams.height = value;
view.setLayoutParams(layoutParams);
}
});
return animator;
}
private void collapse(final View view) {
int finalHeight = view.getHeight();
ValueAnimator mAnimator = slideAnimator(finalHeight, 0, view);
mAnimator.addListener(new Animator.AnimatorListener() {
#Override
public void onAnimationStart(Animator animation) {
}
#Override
public void onAnimationEnd(Animator animator) {
//Height=0, but it set visibility to GONE
view.setVisibility(View.INVISIBLE);
}
#Override
public void onAnimationCancel(Animator animation) {
}
#Override
public void onAnimationRepeat(Animator animation) {
}
});
mAnimator.start();
}
Everything is good here, check where you call method if you are changing background or any other property of the toolbar.