web-dev-qa-db-ja.com

要素が1つだけのCardViewをRecyclerViewの中央に配置します

TextViewおよびImageView(すべてのカードは都市を表します)を持つCardViewsを含むRecyclerViewを使用しています。また、すべてのカードにonClickListenerがあり、市内の博物館のリストに移動します。 (RecyclerViewはArrayListによって設定されます)。リストは、垂直にスクロールする同じCardviewで構成されたRecyclerViewです。

都市に博物館が1つしかない場合、画面の中央に一意のCardViewを表示するにはどうすればよいですか?

これはアクティビティxmlです。

    <?xml version="1.0" encoding="utf-8"?>
 <RelativeLayout
    xmlns:Android="http://schemas.Android.com/apk/res/Android"
    xmlns:tools="http://schemas.Android.com/tools"
    Android:layout_width="match_parent"
    Android:layout_height="match_parent"
    Android:paddingBottom="@dimen/activity_vertical_margin"
    Android:paddingLeft="@dimen/activity_horizontal_margin"
    Android:paddingRight="@dimen/activity_horizontal_margin"
    Android:paddingTop="@dimen/activity_vertical_margin"
    tools:context="com.bebbo203.mymuseum.MuseumActivity">

    <Android.support.v7.widget.RecyclerView
        Android:layout_width="wrap_content"
        Android:layout_height="wrap_content"
        Android:id="@+id/recyclerViewMuseum"
        Android:scrollbars="vertical"
        Android:scrollIndicators="none"
        Android:gravity="center_horizontal"
        />
</RelativeLayout>

そして、これはRecyclerView xmlです:

 <RelativeLayout xmlns:Android="http://schemas.Android.com/apk/res/Android"
              Android:layout_width="match_parent"
              Android:layout_height="match_parent"
              Android:baselineAligned="false"
              xmlns:card_view="http://schemas.Android.com/apk/res-auto">

    <Android.support.v7.widget.CardView
        xmlns:card_view="http://schemas.Android.com/apk/res-auto"
        Android:layout_width="match_parent"
        Android:layout_height="150dp"
        Android:id="@+id/cardView"
        card_view:cardCornerRadius="2dp"
        card_view:cardUseCompatPadding="true"
        Android:gravity="center_horizontal"
        Android:animateLayoutChanges="true"
        >
        <FrameLayout
            Android:layout_width="match_parent"
            Android:layout_height="match_parent">

            <ImageView
                Android:layout_width="match_parent"
                Android:layout_height="150dp"
                Android:id="@+id/imageViewList"
                Android:layout_gravity="center_horizontal|top"
                Android:adjustViewBounds="true"
                Android:scaleType="centerCrop"/>

            <TextView
                Android:id="@+id/textViewList"
                Android:layout_width="match_parent"
                Android:layout_height="150dp"
                Android:textSize="40sp"
                Android:textIsSelectable="false"
                Android:textAlignment="center"
                Android:gravity="fill"
                Android:textStyle="bold"
                Android:layout_weight="1"
                Android:layout_gravity="center_horizontal|top"/>

        </FrameLayout>

    </Android.support.v7.widget.CardView>


</RelativeLayout>`

手伝ってくれてありがとう。

これがMainActivityです。都市のリスト。ここですべてが良いです。 enter image description here

美術館が1つしかないParigiをクリックすると、画面の中央に単一のカードビューが表示されます。

enter image description here

(可能であれば、画面の上部からではなく、画面の中央からカードビューを作成したいと思います。アクティビティを開いたときに中央のカードビューが常に中央にあるように。たとえば、他の順序)

enter image description here

35
Roberto Aureli

単純なHelloWorldアプリを実装しました。このアプリは、都市のリストを表示し、所有する博物館の数に基づいて、フルサイズの都市カードまたは中央のラップされたバージョンを表示します。

enter image description here

(はい、私は芸術がまったく得意ではありません:-))

ここに私がそれをした方法があります。

TL; DR:

重要な部分はItemDecorationです:適切なアイテムオフセットを設定すると、必要なものが得られます。これが私がやった方法です:

    RecyclerView recyclerViewMuseum = (RecyclerView)findViewById(R.id.recyclerViewMuseum);
    recyclerViewMuseum.setLayoutManager(new LinearLayoutManager(this, LinearLayoutManager.VERTICAL, false));
    recyclerViewMuseum.setAdapter(adapter);
    recyclerViewMuseum.addItemDecoration(new RecyclerView.ItemDecoration() {

        @Override
        public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) {
            if (view instanceof CityWithOneMuseumCardView) {
                int totalWidth = parent.getWidth();
                int cardWidth = getResources().getDimensionPixelOffset(R.dimen.small_card_width);
                int sidePadding = (totalWidth - cardWidth) / 2;
                sidePadding = Math.max(0, sidePadding);
                outRect.set(sidePadding, 0, sidePadding, 0);
            }
        }
    });

モデルは次のとおりです-CityおよびMuseumクラス:

public class Museum {
    public String title;
    public Museum(String title) {
        this.title = title;
    }
}

public class City {
    public String title;
    public int imageRes;
    public List<Museum> museums = new ArrayList<>();

    public City(String title, int imageRes) {
        this.title = title;
        this.imageRes = imageRes;
    }
}

次にビュー:CityWithManyMuseumsCardViewおよびCityWithOneMuseumCardView。どちらもヘルパーインターフェイスIItemDisplayerを使用しています。

public class CityWithOneMuseumCardView extends CardView implements IItemDisplayer<City> {

    public CityWithOneMuseumCardView(Context context) {
        super(context);
        LayoutInflater.from(context).inflate(R.layout.one_museum_layout, this);
    }

    @Override
    public void displayItem(City city) {
        TextView cityTitleTextView = (TextView)findViewById(R.id.cityTitleTextView);
        cityTitleTextView.setText(city.title);
    }
}

public class CityWithManyMuseumsCardView extends CardView implements IItemDisplayer<City> {

    public CityWithManyMuseumsCardView(Context context) {
        super(context);
        LayoutInflater.from(context).inflate(R.layout.many_museums_layout, this);
    }

    @Override
    public void displayItem(City city) {
        ImageView cityBackgroundImageView = (ImageView)findViewById(R.id.cityBackgroundImageView);
        cityBackgroundImageView.setImageResource(city.imageRes);
        TextView cityTitleTextView = (TextView)findViewById(R.id.cityTitleTextView);
        cityTitleTextView.setText(city.title);
        TextView cityNumberOrMuseumsTextView = (TextView)findViewById(R.id.cityNumberOrMuseumsTextView);
        cityNumberOrMuseumsTextView.setText(String.valueOf(city.museums.size()));
    }
}

public interface IItemDisplayer<TItem> {
    public void displayItem(TItem item);
}

そしてそのレイアウト:

<!-- One Museum card -->
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout
    xmlns:Android="http://schemas.Android.com/apk/res/Android"
    Android:background="#BB2050AB"
    Android:layout_width="@dimen/small_card_width"
    Android:layout_height="200dp">

    <TextView
        Android:background="#AA000000"
        Android:textColor="#FFFFFF"
        Android:text="Only one museum available"
        Android:textSize="16sp"
        Android:padding="4dp"
        Android:layout_width="wrap_content"
        Android:layout_height="wrap_content" />

    <TextView
        Android:id="@+id/cityTitleTextView"
        Android:layout_gravity="bottom"
        Android:background="#AAFFFFFF"
        Android:textColor="#000000"
        Android:textSize="24sp"
        Android:paddingStart="16dp"
        Android:paddingEnd="16dp"
        Android:gravity="center"
        Android:layout_width="match_parent"
        Android:layout_height="48dp" />
</FrameLayout>

<!-- Many museums card -->
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout
    xmlns:Android="http://schemas.Android.com/apk/res/Android"
    Android:layout_width="match_parent"
    Android:layout_height="240dp">
    <ImageView
        Android:id="@+id/cityBackgroundImageView"
        Android:scaleType="fitXY"
        Android:layout_width="500dp"
        Android:layout_height="match_parent" />

    <TextView
        Android:id="@+id/cityNumberOrMuseumsTextView"
        Android:layout_gravity="top|end"
        Android:background="#AA000000"
        Android:textColor="#FFFFFF"
        Android:textSize="16sp"
        Android:padding="4dp"
        Android:layout_width="wrap_content"
        Android:layout_height="wrap_content" />

    <TextView
        Android:id="@+id/cityTitleTextView"
        Android:layout_gravity="bottom"
        Android:background="#AA000000"
        Android:textColor="#FFFFFF"
        Android:textSize="24sp"
        Android:paddingStart="16dp"
        Android:paddingEnd="16dp"
        Android:gravity="center_vertical"
        Android:layout_width="match_parent"
        Android:layout_height="48dp" />
</FrameLayout>

次に、RecyclerViewCityAdapter.Javaのアダプターを作成する必要があります

public class CityAdapter  extends RecyclerView.Adapter<RecyclerView.ViewHolder> {

    final static int ITEM_TYPE_MANY_MUSEUMS = 0;
    final static int ITEM_TYPE_ONE_MUSEUM = 1;

    private List<City> items;

    public CityAdapter(List<City> items) {
        this.items = items;
    }

    @Override
    public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup viewGroup, int viewType) {
        switch (viewType) {
            case ITEM_TYPE_MANY_MUSEUMS:
                return new ViewHolder(new CityWithManyMuseumsCardView(viewGroup.getContext()));
            case ITEM_TYPE_ONE_MUSEUM:
                return new ViewHolder(new CityWithOneMuseumCardView(viewGroup.getContext()));
            default:
                throw new IllegalArgumentException(String.format("Unexpected viewType: %d", viewType));
        }
    }

    @Override
    public int getItemViewType(int position) {
        if (items == null || items.size() < position) {
            throw new IllegalArgumentException("Wrong position!");
        }

        if (items.get(position).museums.size() > 1) {
            return ITEM_TYPE_MANY_MUSEUMS;
        } else if (items.get(position).museums.size() == 1){
            return ITEM_TYPE_ONE_MUSEUM;
        }

        throw new IllegalArgumentException("Wrong number of museums!");
    }

    @Override
    public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
        ((IItemDisplayer<City>) holder.itemView).displayItem(items.get(position));
    }

    @Override
    public int getItemCount() {
        return items.size();
    }

    public class ViewHolder extends RecyclerView.ViewHolder {

        public ViewHolder(View itemView) {
            super(itemView);
        }
    }
}

このプロジェクトをDropboxにアップロードしました-お気軽に チェックアウト !それが役に立てば幸い。

18

これを試すことができます:

import Android.content.Context;
import Android.graphics.Rect;
import Android.support.v4.view.ViewCompat;
import Android.support.v7.widget.RecyclerView;
import Android.util.Log;
import Android.view.View;

import Java.lang.reflect.Field;

/**
 * {@link Android.support.v7.widget.LinearLayoutManager} which wraps its content. Note that this class will always
 * wrap the content regardless of {@link Android.support.v7.widget.RecyclerView} layout parameters.
 * <p/>
 * Now it's impossible to run add/remove animations with child views which have arbitrary dimensions (height for
 * VERTICAL orientation and width for HORIZONTAL). However if child views have fixed dimensions
 * {@link #setChildSize(int)} method might be used to let the layout manager know how big they are going to be.
 * If animations are not used at all then a normal measuring procedure will run and child views will be measured during
 * the measure pass.
 */
public class WrapContentLinearLayoutManager extends Android.support.v7.widget.LinearLayoutManager {

    private static boolean canMakeInsetsDirty = true;
    private static Field insetsDirtyField = null;

    private static final int CHILD_WIDTH = 0;
    private static final int CHILD_HEIGHT = 1;
    private static final int DEFAULT_CHILD_SIZE = 100;

    private final int[] childDimensions = new int[2];
    private final RecyclerView view;

    private int childSize = DEFAULT_CHILD_SIZE;
    private boolean hasChildSize;
    private int overScrollMode = ViewCompat.OVER_SCROLL_ALWAYS;
    private final Rect tmpRect = new Rect();

    @SuppressWarnings("UnusedDeclaration")
    public WrapContentLinearLayoutManager(Context context) {
        super(context);
        this.view = null;
    }

    @SuppressWarnings("UnusedDeclaration")
    public WrapContentLinearLayoutManager(Context context, int orientation, boolean reverseLayout) {
        super(context, orientation, reverseLayout);
        this.view = null;
    }

    @SuppressWarnings("UnusedDeclaration")
    public WrapContentLinearLayoutManager(RecyclerView view) {
        super(view.getContext());
        this.view = view;
        this.overScrollMode = ViewCompat.getOverScrollMode(view);
    }

    @SuppressWarnings("UnusedDeclaration")
    public WrapContentLinearLayoutManager(RecyclerView view, int orientation, boolean reverseLayout) {
        super(view.getContext(), orientation, reverseLayout);
        this.view = view;
        this.overScrollMode = ViewCompat.getOverScrollMode(view);
    }

    public void setOverScrollMode(int overScrollMode) {
        if (overScrollMode < ViewCompat.OVER_SCROLL_ALWAYS || overScrollMode > ViewCompat.OVER_SCROLL_NEVER)
            throw new IllegalArgumentException("Unknown overscroll mode: " + overScrollMode);
        if (this.view == null) throw new IllegalStateException("view == null");
        this.overScrollMode = overScrollMode;
        ViewCompat.setOverScrollMode(view, overScrollMode);
    }

    public static int makeUnspecifiedSpec() {
        return View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED);
    }

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

        final boolean hasWidthSize = widthMode != View.MeasureSpec.UNSPECIFIED;
        final boolean hasHeightSize = heightMode != View.MeasureSpec.UNSPECIFIED;

        final boolean exactWidth = widthMode == View.MeasureSpec.EXACTLY;
        final boolean exactHeight = heightMode == View.MeasureSpec.EXACTLY;

        final int unspecified = makeUnspecifiedSpec();

        if (exactWidth && exactHeight) {
            // in case of exact calculations for both dimensions let's use default "onMeasure" implementation
            super.onMeasure(recycler, state, widthSpec, heightSpec);
            return;
        }

        final boolean vertical = getOrientation() == VERTICAL;

        initChildDimensions(widthSize, heightSize, vertical);

        int width = 0;
        int height = 0;

        // it's possible to get scrap views in recycler which are bound to old (invalid) adapter entities. This
        // happens because their invalidation happens after "onMeasure" method. As a workaround let's clear the
        // recycler now (it should not cause any performance issues while scrolling as "onMeasure" is never
        // called whiles scrolling)
        recycler.clear();

        final int stateItemCount = state.getItemCount();
        final int adapterItemCount = getItemCount();
        // adapter always contains actual data while state might contain old data (f.e. data before the animation is
        // done). As we want to measure the view with actual data we must use data from the adapter and not from  the
        // state
        for (int i = 0; i < adapterItemCount; i++) {
            if (vertical) {
                if (!hasChildSize) {
                    if (i < stateItemCount) {
                        // we should not exceed state count, otherwise we'll get IndexOutOfBoundsException. For such items
                        // we will use previously calculated dimensions
                        measureChild(recycler, i, widthSize, unspecified, childDimensions);
                    } else {
                        logMeasureWarning(i);
                    }
                }
                height += childDimensions[CHILD_HEIGHT];
                if (i == 0) {
                    width = childDimensions[CHILD_WIDTH];
                }
                if (hasHeightSize && height >= heightSize) {
                    break;
                }
            } else {
                if (!hasChildSize) {
                    if (i < stateItemCount) {
                        // we should not exceed state count, otherwise we'll get IndexOutOfBoundsException. For such items
                        // we will use previously calculated dimensions
                        measureChild(recycler, i, unspecified, heightSize, childDimensions);
                    } else {
                        logMeasureWarning(i);
                    }
                }
                width += childDimensions[CHILD_WIDTH];
                if (i == 0) {
                    height = childDimensions[CHILD_HEIGHT];
                }
                if (hasWidthSize && width >= widthSize) {
                    break;
                }
            }
        }

        if (exactWidth) {
            width = widthSize;
        } else {
            width += getPaddingLeft() + getPaddingRight();
            if (hasWidthSize) {
                width = Math.min(width, widthSize);
            }
        }

        if (exactHeight) {
            height = heightSize;
        } else {
            height += getPaddingTop() + getPaddingBottom();
            if (hasHeightSize) {
                height = Math.min(height, heightSize);
            }
        }

        setMeasuredDimension(width, height);

        if (view != null && overScrollMode == ViewCompat.OVER_SCROLL_IF_CONTENT_SCROLLS) {
            final boolean fit = (vertical && (!hasHeightSize || height < heightSize))
                    || (!vertical && (!hasWidthSize || width < widthSize));

            ViewCompat.setOverScrollMode(view, fit ? ViewCompat.OVER_SCROLL_NEVER : ViewCompat.OVER_SCROLL_ALWAYS);
        }
    }

    private void logMeasureWarning(int child) {
        if (BuildConfig.DEBUG) {
            Log.w("LinearLayoutManager", "Can't measure child #" + child + ", previously used dimensions will be reused." +
                    "To remove this message either use #setChildSize() method or don't run RecyclerView animations");
        }
    }

    private void initChildDimensions(int width, int height, boolean vertical) {
        if (childDimensions[CHILD_WIDTH] != 0 || childDimensions[CHILD_HEIGHT] != 0) {
            // already initialized, skipping
            return;
        }
        if (vertical) {
            childDimensions[CHILD_WIDTH] = width;
            childDimensions[CHILD_HEIGHT] = childSize;
        } else {
            childDimensions[CHILD_WIDTH] = childSize;
            childDimensions[CHILD_HEIGHT] = height;
        }
    }

    @Override
    public void setOrientation(int orientation) {
        // might be called before the constructor of this class is called
        //noinspection ConstantConditions
        if (childDimensions != null) {
            if (getOrientation() != orientation) {
                childDimensions[CHILD_WIDTH] = 0;
                childDimensions[CHILD_HEIGHT] = 0;
            }
        }
        super.setOrientation(orientation);
    }

    public void clearChildSize() {
        hasChildSize = false;
        setChildSize(DEFAULT_CHILD_SIZE);
    }

    public void setChildSize(int childSize) {
        hasChildSize = true;
        if (this.childSize != childSize) {
            this.childSize = childSize;
            requestLayout();
        }
    }

    private void measureChild(RecyclerView.Recycler recycler, int position, int widthSize, int heightSize, int[] dimensions) {
        final View child;
        try {
            child = recycler.getViewForPosition(position);
        } catch (IndexOutOfBoundsException e) {
            if (BuildConfig.DEBUG) {
                Log.w("LinearLayoutManager", "LinearLayoutManager doesn't work well with animations. Consider switching them off", e);
            }
            return;
        }

        final RecyclerView.LayoutParams p = (RecyclerView.LayoutParams) child.getLayoutParams();

        final int hPadding = getPaddingLeft() + getPaddingRight();
        final int vPadding = getPaddingTop() + getPaddingBottom();

        final int hMargin = p.leftMargin + p.rightMargin;
        final int vMargin = p.topMargin + p.bottomMargin;

        // we must make insets dirty in order calculateItemDecorationsForChild to work
        makeInsetsDirty(p);
        // this method should be called before any getXxxDecorationXxx() methods
        calculateItemDecorationsForChild(child, tmpRect);

        final int hDecoration = getRightDecorationWidth(child) + getLeftDecorationWidth(child);
        final int vDecoration = getTopDecorationHeight(child) + getBottomDecorationHeight(child);

        final int childWidthSpec = getChildMeasureSpec(widthSize, hPadding + hMargin + hDecoration, p.width, canScrollHorizontally());
        final int childHeightSpec = getChildMeasureSpec(heightSize, vPadding + vMargin + vDecoration, p.height, canScrollVertically());

        child.measure(childWidthSpec, childHeightSpec);

        dimensions[CHILD_WIDTH] = getDecoratedMeasuredWidth(child) + p.leftMargin + p.rightMargin;
        dimensions[CHILD_HEIGHT] = getDecoratedMeasuredHeight(child) + p.bottomMargin + p.topMargin;

        // as view is recycled let's not keep old measured values
        makeInsetsDirty(p);
        recycler.recycleView(child);
    }

    private static void makeInsetsDirty(RecyclerView.LayoutParams p) {
        if (!canMakeInsetsDirty) {
            return;
        }
        try {
            if (insetsDirtyField == null) {
                insetsDirtyField = RecyclerView.LayoutParams.class.getDeclaredField("mInsetsDirty");
                insetsDirtyField.setAccessible(true);
            }
            insetsDirtyField.set(p, true);
        } catch (NoSuchFieldException e) {
            onMakeInsertDirtyFailed();
        } catch (IllegalAccessException e) {
            onMakeInsertDirtyFailed();
        }
    }

    private static void onMakeInsertDirtyFailed() {
        canMakeInsetsDirty = false;
        if (BuildConfig.DEBUG) {
            Log.w("LinearLayoutManager", "Can't make LayoutParams insets dirty, decorations measurements might be incorrect");
        }
    }
}

このWrapContentLinearLayoutManagerをリサイクラービューに配置します

mRecyclerView.setLayoutManager(new WrapContentLinearLayoutManager(activity));

そして、これはxmlで(親に親を持つ)

<Android.support.v7.widget.RecyclerView
            Android:layout_width="match_parent"
            Android:layout_height="wrap_content"
            Android:layout_centerInParent="true"
            Android:id="@+id/recyclerViewMuseum"
            Android:scrollbars="vertical"
            Android:scrollIndicators="none"/>

これは動作するはずです:)

2
koni

アイテムが1つ以上ある場合は、RecyclerViewの高さを設定してみてください。そのためには このトピック を参照してください。アイテムが1つだけの場合は、RecyclerViewWRAP_CONTENTに設定します。アイテムが複数ある場合は、RecyclerViewMATCH_CONTENTに設定します。幸運を!

1
Phan Sinh

1. recyclerviewに1つの子がある場合、LayoutParams CENTER_IN_PARENTを設定してください
2。またはFrameLayoutrecyclerViewの親として使用し、layout_gravity 3.またはcardviewの上のスペースを計算し、marginToprecyclerViewまたはsetTranslationYに設定してrecyclerViewに設定します4.または、スペースの高さでitemDecarationを追加しますRecylerviewで。

RelativeLayout.LayoutParams rLp = (RelativeLayout.LayoutParams) recyclerView.getLayoutParams();
    if(data != null || data.size()>1){
        rLp.removeRule(RelativeLayout.CENTER_IN_PARENT);
    }else{
        rLp.addRule(RelativeLayout.CENTER_IN_PARENT, RelativeLayout.TRUE);
    }
    recyclerView.setLayoutParams(rLp);

RecyclerViewの子が1つだけの場合、このLayoutManagerを使用します。

import Android.content.Context;
import Android.support.v7.widget.LinearLayoutManager;
import Android.support.v7.widget.RecyclerView;
import Android.util.Log;
import Android.view.View;
import Android.view.ViewGroup;

public class FullyLinearLayoutManager extends LinearLayoutManager {

    private static final String TAG = FullyLinearLayoutManager.class.getSimpleName();
    private MeasureEndListener mMeasureEndListener;

    public FullyLinearLayoutManager(Context context) {
        super(context);
    }
    private float divHeight =0;
    public FullyLinearLayoutManager(Context context,float height) {
        super(context);
        divHeight = height;
    }

    public FullyLinearLayoutManager(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);

        Log.i(TAG, "onMeasure called. \nwidthMode " + widthMode
                + " \nheightMode " + heightSpec
                + " \nwidthSize " + widthSize
                + " \nheightSize " + heightSize
                + " \ngetItemCount() " + getItemCount());

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

            if (getOrientation() == HORIZONTAL) {
                width = width + mMeasuredDimension[0];
                if (i == 0) {
                    height = mMeasuredDimension[1];
                }
            } else {
//                LogUtils.e(mMeasuredDimension[1]);
                height = height + mMeasuredDimension[1];
                if(i!= getItemCount()-1){
                    height += divHeight;
//                    LogUtils.e(divHeight + "xxx add"+DensityUtils.dp2px(divHeight));
                }else{
                    height += 2*divHeight;
//                    LogUtils.e(divHeight+ "xxx no add"+ DensityUtils.dp2px(divHeight));
                }
                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:
        }
        if(mMeasureEndListener!=null){
            mMeasureEndListener.onMeasureEnd(width,height);
//            new Thread().interrupt();
        }
        setMeasuredDimension(width, height);
    }

    private void measureScrapChild(RecyclerView.Recycler recycler, int position, int widthSpec,
                                   int heightSpec, int[] measuredDimension) {
        try {
            View view = recycler.getViewForPosition(0);//fix 动态添加时报IndexOutOfBoundsException

            if (view != null) {
                RecyclerView.LayoutParams p = (RecyclerView.LayoutParams) view.getLayoutParams();

                int childWidthSpec = ViewGroup.getChildMeasureSpec(widthSpec,
                        getPaddingLeft() + getPaddingRight(), p.width);

                int childHeightSpec = ViewGroup.getChildMeasureSpec(heightSpec,
                        getPaddingTop() + getPaddingBottom(), p.height);

                view.measure(childWidthSpec, childHeightSpec);
                measuredDimension[0] = view.getMeasuredWidth() + p.leftMargin + p.rightMargin;
                measuredDimension[1] = view.getMeasuredHeight() + p.bottomMargin + p.topMargin;
                recycler.recycleView(view);
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
        }
    }

    public interface MeasureEndListener{
        void onMeasureEnd(int width,int height);
    }

    public void setMeasureEndListener(MeasureEndListener mMeasureEndListener){
        this.mMeasureEndListener = mMeasureEndListener;
    }
}
1
tiny sunlight
        <Android.support.v7.widget.RecyclerView
            Android:id="@+id/recyclerview"
            Android:layout_width="wrap_content"
            Android:layout_height="match_parent"
            Android:layout_marginTop="@dimen/margin_twenty"
            app:layout_constraintLeft_toLeftOf="parent"
            app:layout_constraintRight_toRightOf="parent"

            Android:layout_marginBottom="@dimen/margin_twenty">
        </Android.support.v7.widget.RecyclerView>
0
nithin joseph