RecyclerView пересчитывает WRAP_CONTENT

С версией 23.2 мы теперь можем использовать высоту WRAP_CONTENT для recyclerView, что отлично. Я делаю это, однако я хочу пересчитать высоту после того, как элемент добавлен (или удален) к адаптеру (таким образом увеличивая или уменьшая высоту).

Мой конкретный recyclerView начинается с 1 элемента, а затем добавляет элементы, когда пользователь делает выбор. Поэтому мне нужно, чтобы макет recyclerView увеличивался в высоту, вплоть до точки. В идеале это произойдет с плавной анимацией, когда список будет увеличиваться или уменьшаться.

Как мы можем сделать это WRAP_CONTENT после того, как он был выложен?

Пробовал:

recyclerview.requestLayout();

recyclerview.invalidate();

Ответ 1

Я ожидаю, что он будет работать с View.invalidate().

Если это не сработает, попробуйте вызвать либо requestLayout, либо invalidate в родительском представлении.

Ответ 2

Как RecyclerView изменит размер на основе нового LayoutManger

Виджет RecyclerView предоставляет расширенную и гибкую базу для создания списков и сеток, а также поддержку анимаций. Этот выпуск приносит новую функциональность API LayoutManager: автоматическое измерение! Это позволяет RecyclerView самостоятельно определять размер содержимого. Это означает, что ранее недоступные сценарии, такие как использование WRAP_CONTENT для измерения RecyclerView, теперь возможны. Вы найдете, что все встроенные LayoutManager теперь поддерживают автоматическое измерение.

Из-за этого изменения убедитесь, что вы дважды проверяете параметры макета ваших позиций: ранее игнорируемые параметры макета (такие как MATCH_PARENT в направлении прокрутки) теперь будут полностью соблюдены.

Если у вас есть настраиваемый LayoutManager, который не расширяет один из встроенных LayoutManagers, это API-интерфейс, который вам нужен, вам придется вызывать setAutoMeasureEnabled (true), а также внести некоторые незначительные изменения, как описано в Javadoc of метод.

Обратите внимание, что хотя RecyclerView анимирует свои дочерние элементы, он не изменяет собственные изменения границ. Если вы хотите анимировать границы RecyclerView по мере их изменения, вы можете использовать API перехода.

Пожалуйста, прочитайте this

Ответ 3

Вариант I

Вы видели этот ответ?

Он не использует recyclerView WRAP_CONTENT, но он может работать.

Вы также можете создать свой собственный recyclerView (расширяет RecyclerView) и переопределить метод onMeasure(), вместо этого используя layoutManager в ссылке.

Вариант II

Попробуйте установить параметры макета перед рисованием вида. Я не проверял, вызвано ли это, когда изменяется макет recyclerView, но если это произойдет, то это сработает. Что-то вроде этого (в вашем методе Activity/Fragment onCreate()/onCreateView():

recyclerView.getViewTreeObserver().addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() {
            @Override
            public boolean onPreDraw() { 
                recyclerView.getViewTreeObserver().removeOnPreDrawListener(this);

                YourParentLayoutType.LayoutParams params = (YourParentLayoutType.LayoutParams) recyclerView.getLayoutParams();
                params.height = YourParentLayoutType.LayoutParams.WRAP_CONTENT;
                recyclerView.setLayoutParams(params);

                return true;
            }
        });

Используйте свой тип родительского макета recyclerView вместо YourParentLayoutType в коде. Я не уверен, что это будет работать, когда макет обновится, но, возможно, стоит попробовать.

Ответ 4

Используйте этот класс:

Пожалуйста, используйте 23.2.1, поскольку 23.2 был ошибочным.

Также вы пытались вызвать notifyDataSetChanged в адаптере recyclerview, насколько я думаю, он должен расширяться без проблем, если вы указали wrap_content как высоту recyclerview

else u может использовать этот класс:

import android.content.Context;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.view.View;
import android.view.ViewGroup;

public class MyLinearLayoutManager extends LinearLayoutManager {

    public MyLinearLayoutManager(Context context, int orientation, boolean reverseLayout)    {
        super(context, orientation, reverseLayout);

    }



    private int[] mMeasuredDimension = new int[2];


    @Override
    public void onMeasure(RecyclerView.Recycler recycler, RecyclerView.State state,
                          int widthSpec, int heightSpec) {
        final int widthMode = View.MeasureSpec.getMode(widthSpec);
        final int heightMode = View.MeasureSpec.getMode(heightSpec);
        final int widthSize = View.MeasureSpec.getSize(widthSpec);
        final int heightSize = View.MeasureSpec.getSize(heightSpec);



        int width = 0;
        int height = 0;
        for (int i = 0; i < getItemCount(); i++) {
            if (getOrientation() == HORIZONTAL) {
                measureScrapChild(recycler, i,
                        View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED),
                        heightSpec,
                        mMeasuredDimension);

                width = width + mMeasuredDimension[0];
                if (i == 0) {
                    height = mMeasuredDimension[1];
                }
            } else {
                measureScrapChild(recycler, i,
                        widthSpec,
                        View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED),
                        mMeasuredDimension);

                height = height + mMeasuredDimension[1];
                if (i == 0) {
                    width = mMeasuredDimension[0];
                }
            }
        }


        switch (widthMode) {
            case View.MeasureSpec.EXACTLY:
                width = widthSize;
            case View.MeasureSpec.AT_MOST:
            case View.MeasureSpec.UNSPECIFIED:
        }

        switch (heightMode) {
            case View.MeasureSpec.EXACTLY:
                height = heightSize;
            case View.MeasureSpec.AT_MOST:
            case View.MeasureSpec.UNSPECIFIED:
        }

        int widthDesired = Math.min(widthSize,width);
        setMeasuredDimension(widthDesired, height);
    }

    private void measureScrapChild(RecyclerView.Recycler recycler, int position, int widthSpec,
                                   int heightSpec, int[] measuredDimension) {
        View view = recycler.getViewForPosition(position);
        // For adding Item Decor Insets to view
        super.measureChildWithMargins(view, 0, 0);
        RecyclerView.LayoutParams p = (RecyclerView.LayoutParams) view.getLayoutParams();
        int childWidthSpec = ViewGroup.getChildMeasureSpec(
                widthSpec,
                getPaddingLeft() + getPaddingRight() + getDecoratedLeft(view) + getDecoratedRight(view),
                p.width);
        int childHeightSpec = ViewGroup.getChildMeasureSpec(
                heightSpec,
                getPaddingTop() + getPaddingBottom() + getDecoratedTop(view) + getDecoratedBottom(view) ,
                p.height);
        view.measure(childWidthSpec, childHeightSpec);

        // Get decorated measurements
        measuredDimension[0] = getDecoratedMeasuredWidth(view) + p.leftMargin + p.rightMargin;
        measuredDimension[1] = getDecoratedMeasuredHeight(view) + p.bottomMargin + p.topMargin;
        recycler.recycleView(view);
        }
    }