Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Android RecyclerView smooth scroll to view that's animating their height

I have a RecyclerView with Expandable Child Views, when the child ViewGroup is clicked it inflates an amount of views animating the ViewGroup height from 0 to the measured viewgroup height, like the following gif:

example

The problem is: I'm calling smoothScrollToPosition on recyclerView, it smooth scroll to the view position, but it considers the current view height, which is still not expanded, in the above gif i'm touching on the under view of the recyclerview, which dont scroll to position because the view is already visible, but when i touch again (calling the smoothscrolltoposition again) it scroll the view to the correct position, because the view is already expanded.

Is there any approach to scroll the view to the top of screen or just scroll to make content visible?

For references: This is the method called to inflate the views:

collapsible_content.removeAllViews();
for(int i = 0; i < 5; i++) {
        View link_view = getLayoutInflater().inflate(R.layout.list_item_timeline_step_link, collapsible_content, false);
        TextView text = (TextView) link_view.findViewById(R.id.step_link_text);
        text.setText("Test");
        collapsible_content.addView(link_view);
    }

And this is my method to expand:

public void toggle() {
        collapsible_content.measure(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);
        Animation a;
        if (mExpanded) {
            a = new ExpandAnimation(collapsible_content.getLayoutParams().height, 0);
        } else {
            a = new ExpandAnimation(collapsible_content.getLayoutParams().height, getMeasuredHeight());
        }
        a.setDuration(mAnimationDuration);
        collapsible_content.startAnimation(a);
        mExpanded = !mExpanded;
    }

And the animation:

private class ExpandAnimation extends Animation {
        private final int mStartHeight;
        private final int mDeltaHeight;

        public ExpandAnimation(int startHeight, int endHeight) {
            mStartHeight = startHeight;
            mDeltaHeight = endHeight - startHeight;
        }

        @Override
        protected void applyTransformation(float interpolatedTime,
                                           Transformation t) {
            final int newHeight = (int) (mStartHeight + mDeltaHeight *
                    interpolatedTime);
            collapsible_content getLayoutParams().height = newHeight;

            if (newHeight <= 0) {
                collapsible_content setVisibility(View.GONE);
            } else {
                collapsible_content setVisibility(View.VISIBLE);
            }
            collapsible_content requestLayout();
        }


        @Override
        public boolean willChangeBounds() {
            return true;
        }
    }
like image 235
Yuri Heupa Avatar asked Jan 19 '15 13:01

Yuri Heupa


People also ask

How do I make my RecyclerView scroll smooth?

Use the setHasFixedsize method If the height of our RecyclerView items is fixed then we should use the setHasFixedsize method in our XML of our card item. This will fix the height of our RecyclerView item and prevent it from increasing or decreasing the size of our Card Layout.

How can I make my Android scroll smoother?

Uninstall bloatware and unused apps Additionally, too much bloatware and unused apps can cripple your device's performance. In case you have apps you're not using or many preinstalled apps on your device, consider uninstalling or disabling them to make your phone run faster. Gently scroll through the apps.

What is Overscroll android?

Overscrolling effects indicate that the user has reached the end of a scrollable list or page. It informs users that there is no more content available. Overscroll effects can be added at the top, bottom, right and left sides of the screen, depending on the screen structure.


1 Answers

My solution was to constant check for view bottom within applyTransformation method, and compare it with RecyclerView height, if the bottom get higher than the RV height, i scroll by the diff values:

final int bottom = collapsible_content.getBottom();
final int listViewHeight = mRecyclerView.getHeight();
if (bottom > listViewHeight) {
    final int top = collapsible_content.getTop();
    if (top > 0) {
        mRecyclerView.smoothScrollBy(0, Math.min(bottom - listViewHeight + mRecyclerView.getPaddingBottom(), top));
    }
}

The trick was to use Math.min to get the view top, so it don't scroll up making the top not visible.

Solution based on ListViewAnimations

like image 118
Yuri Heupa Avatar answered Sep 23 '22 08:09

Yuri Heupa