Android RecyclerView плавная прокрутка, чтобы увидеть, как анимируется их высота

У меня есть RecyclerView с расширяемыми дочерними представлениями, когда нажимается дочерняя группа просмотра, она увеличивает количество представлений, анимирующих высоту группы просмотра, от 0 до измеренной высоты группы просмотра, например следующий gif:

пример

Проблема в том, что я вызываю smoothScrollToPosition для recyclerView, он плавно прокручивается до позиции просмотра, но учитывает текущую высоту просмотра, которая все еще не расширена, в приведенном выше gif я касаюсь нижнего вида recyclerview, который не прокручивается до позиции, потому что вид уже виден, но когда я снова касаюсь (снова вызывая smoothscrolltoposition), он прокручивает вид до правильной позиции, потому что вид уже расширен.

Есть ли способ прокрутить вид в верхнюю часть экрана или просто прокрутить, чтобы сделать содержимое видимым?

Для справки: это метод, вызываемый для раздувания представлений:

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

И это мой метод расширения:

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

И анимация:

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

person Yuri Heupa    schedule 19.01.2015    source источник


Ответы (2)


Мое решение состояло в том, чтобы постоянно проверять вид снизу в методе applyTransformation и сравнивать его с высотой RecyclerView, если дно становится выше высоты RV, я прокручиваю значения diff:

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

Хитрость заключалась в том, чтобы использовать Math.min для получения верхней части представления, чтобы он не прокручивался вверх, делая верхнюю часть невидимой.

Решение на основе ListViewAnimations

person Yuri Heupa    schedule 19.01.2015

Добавьте анимационный прослушиватель и запустите прокрутку recyclerview после завершения расширяющейся анимации.

person Mann    schedule 19.01.2015
comment
Я сделал это, но я хочу прокручивать, пока представление анимируется, мой подход состоял в том, чтобы добавить прослушиватель анимации, чтобы проверить, находится ли нижний Y представления вне RecyclerView, а затем вызвать smoothscroll, указав значение пикселей, но я не успел как это сделать - person Yuri Heupa; 19.01.2015
comment
Итак, вы хотите параллельную анимацию битов - person Mann; 19.01.2015
comment
Я думаю, вам нужно имитировать высоту обзора, чтобы притвориться более высоким видом. - person Mann; 19.01.2015
comment
Что вы имеете в виду под фальшивой высотой представления? - person Yuri Heupa; 19.01.2015
comment
Возможно, при расширении присвойте представлению фиксированную высоту вместо wrap_content. - person Mann; 20.01.2015