java Android RecyclerView 平滑滚动以查看其高度动画

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/28025425/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-11-02 12:52:06  来源:igfitidea点击:

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

javaandroidandroid-animationandroid-recyclerviewandroid-scroll

提问by Yuri Heupa

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:

我有一个带有可扩展子视图的 RecyclerView,当子 ViewGroup 被单击时,它会膨胀一定数量的视图,将 ViewGroup 高度从 0 动画化到测量的视图组高度,如下面的 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.

问题是:我在recyclerView上调用smoothScrollToPosition,它平滑滚动到视图位置,但它考虑了当前视图高度,它仍未展开,在上面的gif中,我正在触摸recyclerview的下视图,它不会滚动到位置,因为视图已经可见,但是当我再次触摸(再次调用 smoothscrolltoposition)时,它会将视图滚动到正确的位置,因为视图已经展开。

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

采纳答案by Yuri Heupa

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:

我的解决方案是在 applyTransformation 方法中不断检查视图底部,并将其与 RecyclerView 高度进行比较,如果底部高于 RV 高度,我会滚动差异值:

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.

诀窍是使用 Math.min 来获取视图顶部,因此它不会向上滚动使顶部不可见。

Solution based on ListViewAnimations

基于ListViewAnimations的解决方案

回答by Mann

Add an animationlistener and start the scrolling of the recyclerview after the expanding animation is finished.

添加animationlistener并在展开动画完成后开始recyclerview的滚动。