嵌套循环器视图高度不换行的内容 [英] Nested Recycler view height doesn't wrap its content

查看:258
本文介绍了嵌套循环器视图高度不换行的内容的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个管理书籍类别(如播放列表)的应用程序。

我想显示收藏列表,并附有垂直RecyclerView每行,本书中的水平RecyclerView列表里面。

当我设置内水平面RecyclerView的layout_height到300dp,它显示正确,但是当我将其设置为WRAP_CONTENT,它不显示任何内容。 我需要使用WRAP_CONTENT,因为我希望能够改变布局管理器编程,以纵向和横向显示之间切换。

你知道我在做什么错了?

我的片段布局:

 < LinearLayout中的xmlns:机器人=htt​​p://schemas.android.com/apk/res/android
                机器人:layout_width =match_parent
                机器人:layout_height =match_parent
                机器人:背景=@色/白>

    < com.twibit.ui.view.CustomSwipeToRefreshLayout
        机器人:ID =@ + ID / swipe_container
        机器人:layout_width =match_parent
        机器人:layout_height =match_parent>

        <的LinearLayout
            机器人:layout_width =match_parent
            机器人:layout_height =match_parent
            机器人:方向=垂直>

            < android.support.v7.widget.RecyclerView
                机器人:ID =@ + ID / shelf_collection_listview
                机器人:layout_width =match_parent
                机器人:layout_height =match_parent
                机器人:paddingTop =10dp/>

        < / LinearLayout中>

    < /com.twibit.ui.view.CustomSwipeToRefreshLayout>
< / LinearLayout中>
 

集合元素的布局:

 < LinearLayout中的xmlns:机器人=htt​​p://schemas.android.com/apk/res/android
              机器人:layout_width =match_parent
              机器人:layout_height =WRAP_CONTENT
              机器人:方向=垂直>

    < RelativeLayout的的xmlns:机器人=htt​​p://schemas.android.com/apk/res/android
                    机器人:layout_width =match_parent
                    机器人:layout_height =WRAP_CONTENT
                    机器人:后台=#FFF>

        <! - 简单的标题 - >

    < / RelativeLayout的>

    <的FrameLayout
        机器人:layout_width =match_parent
        机器人:layout_height =WRAP_CONTENT>

        <的TextView
            机器人:layout_width =match_parent
            机器人:layout_height =match_parent
            机器人:文本=@字符串/ empty_collection
            机器人:ID =@ + ID / empty_collection_tv
            机器人:能见度=水涨船高
            机器人:重力=中心/>

        < android.support.v7.widget.RecyclerView
            机器人:ID =@ + ID / collection_book_listview
            机器人:layout_width =match_parent
            机器人:layout_height =WRAP_CONTENT/> <  - 安卓!layout_height =300dp - >

    < /的FrameLayout>

< / LinearLayout中>
 

图书列表项:

 <的FrameLayout的xmlns:机器人=htt​​p://schemas.android.com/apk/res/android
              机器人:layout_width =180dp
              机器人:layout_height =220DP
              机器人:layout_gravity =中心>

        < ImageView的
            机器人:ID =@ + ID / shelf_item_cover
            机器人:layout_width =WRAP_CONTENT
            机器人:layout_height =WRAP_CONTENT
            机器人:layout_gravity =中心
            机器人:=了maxWidth150dp
            机器人:=了maxHeight200dp
            机器人:SRC =@可绘制/占位符
            机器人:contentDescription =@字符串/覆盖
            机器人:adjustViewBounds =真
            机器人:背景=@机器人:可绘制/ dialog_holo_light_frame/>

< /的FrameLayout>
 

下面是我收集适配器:

 私有类CollectionsListAdapter扩展RecyclerView.Adapter< CollectionsListAdapter.ViewHolder> {
    私人最终字符串变量= CollectionsListAdapter.class.getSimpleName();
    私人语境mContext;

    //创建ViewHolder类,以保持引用您的意见
    类ViewHolder扩展RecyclerView.ViewHolder {

        私人最终的TextView mHeaderTitleTextView;
        私人最终的TextView mHeaderCountTextView;

        私人最终RecyclerView mHorizo​​ntalListView;
        私人最终的TextView mEmptyTextView;

        公共ViewHolder(查看视图){
            超(视图);

            mHeaderTitleTextView =(TextView中)view.findViewById(R.id.collection_header_tv);
            mHeaderCountTextView =(TextView中)view.findViewById(R.id.collection_header_count_tv);

            mHorizo​​ntalListView =(RecyclerView)view.findViewById(R.id.collection_book_listview);
            mEmptyTextView =(TextView中)view.findViewById(R.id.empty_collection_tv);
        }
    }


    公共CollectionsListAdapter(上下文的背景下){
        mContext =背景;
    }


    @覆盖
    公共ViewHolder onCreateViewHolder(ViewGroup中父,int i)以{
        Log.d(TAG,CollectionsListAdapter.onCreateViewHolder(+ parent.getId()+,+ I +));
        //创建由充气行项目XML的新观点。
        视图V = LayoutInflater.from(parent.getContext())膨胀(R.layout.shelf_collection,父母,假)。

        //视图设置为ViewHolder
        ViewHolder持有人=新ViewHolder(V);

        holder.mHorizo​​ntalListView.setHasFixedSize(假);
        holder.mHorizo​​ntalListView.setHorizo​​ntalScrollBarEnabled(真正的);

        //使用线性布局管理器
        LinearLayoutManager mLayoutManager =新LinearLayoutManager(mContext);
        mLayoutManager.setOrientation(LinearLayoutManager.HORIZONTAL);
        holder.mHorizo​​ntalListView.setLayoutManager(mLayoutManager);

        回报持有人;
    }

    @覆盖
    公共无效onBindViewHolder(ViewHolder持有人,int i)以{
        Log.d(TAG,CollectionsListAdapter.onBindViewHolder(+ holder.getPosition()+,+ I +));

        收藏= mCollectionList.get(我);
        Log.d(TAG,收集+ collection.getLabel());

        holder.mHeaderTitleTextView.setText(collection.getLabel());
        holder.mHeaderCountTextView.setText(+ collection.getBooks()的大小());

        //创建一个适配器如果不存在
        如果(!mBookListAdapterMap.containsKey(collection.getCollectionId())){
            mBookListAdapterMap.put(collection.getCollectionId(),新BookListAdapter(getActivity(),集合));
        }

        holder.mHorizo​​ntalListView.setAdapter(mBookListAdapterMap.get(collection.getCollectionId()));

    }

    @覆盖
    公众诠释getItemCount(){
        返回mCollectionList.size();
    }
}
 

最后,图书适配器:

 私有类BookListAdapter扩展RecyclerView.Adapter< BookListAdapter.ViewHolder>实现View.OnClickListener {
    私人最终字符串变量= BookListAdapter.class.getSimpleName();

    //创建ViewHolder类,以保持引用您的意见
    类ViewHolder扩展RecyclerView.ViewHolder {
        公共ImageView的mCoverImageView;

        公共ViewHolder(查看视图){
            超(视图);
            mCoverImageView =(ImageView的)view.findViewById(R.id.shelf_item_cover);
        }
    }

    @覆盖
    公共无效的onClick(视图v){
        BookListAdapter.ViewHolder支架=(BookListAdapter.ViewHolder)v.getTag();
        INT位置= holder.getPosition();
        。最后一部书= mCollection.getBooks()得到(位置);

        //点​​击封面图片
        如果(v.getId()== holder.mCoverImageView.getId()){
            downloadOrOpenBook(书);
            返回;
        }
    }

    私人无效downloadOrOpenBook(最后一部书){
        //做的东西
    }

    私人语境mContext;
    私人收藏mCollection;

    公共BookListAdapter(上下文的背景下,收藏){
        Log.d(TAG,BookListAdapter(+上下文+,+集+));
        mCollection =收集;
        mContext =背景;
    }

    @覆盖
    公共ViewHolder onCreateViewHolder(ViewGroup中父,int i)以{
        Log.d(TAG,onCreateViewHolder(+ parent.getId()+,+ I +));
        //创建由充气行项目XML的新观点。
        视图V = LayoutInflater.from(parent.getContext())膨胀(R.layout.shelf_grid_item,父母,假)。

        //视图设置为ViewHolder
        ViewHolder持有人=新ViewHolder(V);
        holder.mCoverImageView.setOnClickListener(BookListAdapter.this); //下载或打开

        holder.mCoverImageView.setTag(保持器);

        回报持有人;
    }

    @覆盖
    公共无效onBindViewHolder(ViewHolder持有人,int i)以{
        Log.d(TAG,onBindViewHolder(+ holder.getPosition()+,+ I +));

        。簿书= mCollection.getBooks()获得(一);

        ImageView的ImageView的= holder.mCoverImageView;
        。ImageLoader.getInstance()displayImage(book.getCoverUrl(),ImageView的);
    }

    @覆盖
    公众诠释getItemCount(){
        返回mCollection.getBooks()的大小()。
    }
}
 

解决方案

@ user2302510解决方案的工作还不如你可能期望。完整的解决方法两个方向和动态数据的变化是:

 公共类MyLinearLayoutManager扩展LinearLayoutManager {

    公共MyLinearLayoutManager(上下文的背景下,INT方向,布尔reverseLayout){
        超(背景下,定向,reverseLayout);
    }

    私人INT [] mMeasuredDimension =新INT [2];

    @覆盖
    公共无效onMeasure(RecyclerView.Recycler回收,RecyclerView.State状态,
                          INT widthSpec,诠释heightSpec){
        最终诠释widthMode = View.MeasureSpec.getMode(widthSpec);
        最终诠释heightMode = View.MeasureSpec.getMode(heightSpec);
        最终诠释widthSize = View.MeasureSpec.getSize(widthSpec);
        最终诠释heightSize = View.MeasureSpec.getSize(heightSpec);
        INT宽度= 0;
        INT高= 0;
        的for(int i = 0; I< getItemCount();我++){
            measureScrapChild(回收,我,
                    View.MeasureSpec.makeMeasureSpec(ⅰ,View.MeasureSpec.UNSPECIFIED),
                    View.MeasureSpec.makeMeasureSpec(ⅰ,View.MeasureSpec.UNSPECIFIED),
                    mMeasuredDimension);

            如果(getOrientation()==水平){
                宽度=宽度+ mMeasuredDimension [0];
                如果(我== 0){
                    高度= mMeasuredDimension [1];
                }
            } 其他 {
                高度=身高+ mMeasuredDimension [1];
                如果(我== 0){
                    宽度= mMeasuredDimension [0];
                }
            }
        }
        开关(widthMode){
            案例View.MeasureSpec.EXACTLY:
                宽度= widthSize;
            案例View.MeasureSpec.AT_MOST:
            案例View.MeasureSpec.UNSPECIFIED:
        }

        开关(heightMode){
            案例View.MeasureSpec.EXACTLY:
                身高= heightSize;
            案例View.MeasureSpec.AT_MOST:
            案例View.MeasureSpec.UNSPECIFIED:
        }

        setMeasuredDimension(宽度,高度);
    }

    私人无效measureScrapChild(RecyclerView.Recycler回收,INT地位,诠释widthSpec,
                                   INT heightSpec,INT [] measuredDimension){
        查看查看= recycler.getViewForPosition(位置);
        如果(查看!= 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(视图);
        }
    }
}
 

I have an application that manage collections of books (like playlists).

I want to display a list of collection with a vertical RecyclerView and inside each row, a list of book in an horizontal RecyclerView.

When i set the layout_height of the inner horizontal RecyclerView to 300dp, it is displayed correctly but when i set it to wrap_content, it doesn't display anything. I need to use wrap_content because I want to be able to change the layout manager programmatically to switch between vertical and horizontal display.

Do you know what i'm doing wrong ?

My Fragment layout :

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:background="@color/white">

    <com.twibit.ui.view.CustomSwipeToRefreshLayout
        android:id="@+id/swipe_container"
        android:layout_width="match_parent"
        android:layout_height="match_parent">

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:orientation="vertical">

            <android.support.v7.widget.RecyclerView
                android:id="@+id/shelf_collection_listview"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:paddingTop="10dp"/>

        </LinearLayout>

    </com.twibit.ui.view.CustomSwipeToRefreshLayout>
</LinearLayout>

Collection element layout :

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
              android:layout_width="match_parent"
              android:layout_height="wrap_content"
              android:orientation="vertical">

    <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:background="#FFF">

        <!-- Simple Header -->

    </RelativeLayout>

    <FrameLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content">

        <TextView
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:text="@string/empty_collection"
            android:id="@+id/empty_collection_tv"
            android:visibility="gone"
            android:gravity="center"/>

        <android.support.v7.widget.RecyclerView
            android:id="@+id/collection_book_listview"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"/> <!-- android:layout_height="300dp" -->

    </FrameLayout>

</LinearLayout>

Book list item :

<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
              android:layout_width="180dp"
              android:layout_height="220dp"
              android:layout_gravity="center">

        <ImageView
            android:id="@+id/shelf_item_cover"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="center"
            android:maxWidth="150dp"
            android:maxHeight="200dp"
            android:src="@drawable/placeholder"
            android:contentDescription="@string/cover"
            android:adjustViewBounds="true"
            android:background="@android:drawable/dialog_holo_light_frame"/>

</FrameLayout>

Here is my Collection Adapter :

private class CollectionsListAdapter extends RecyclerView.Adapter<CollectionsListAdapter.ViewHolder> {
    private final String TAG = CollectionsListAdapter.class.getSimpleName();
    private Context mContext;

    // Create the ViewHolder class to keep references to your views
    class ViewHolder extends RecyclerView.ViewHolder {

        private final TextView mHeaderTitleTextView;
        private final TextView mHeaderCountTextView;

        private final RecyclerView mHorizontalListView;
        private final TextView mEmptyTextView;

        public ViewHolder(View view) {
            super(view);

            mHeaderTitleTextView = (TextView) view.findViewById(R.id.collection_header_tv);
            mHeaderCountTextView = (TextView) view.findViewById(R.id.collection_header_count_tv);

            mHorizontalListView = (RecyclerView) view.findViewById(R.id.collection_book_listview);
            mEmptyTextView = (TextView) view.findViewById(R.id.empty_collection_tv);
        }
    }


    public CollectionsListAdapter(Context context) {
        mContext = context;
    }


    @Override
    public ViewHolder onCreateViewHolder(ViewGroup parent, int i) {
        Log.d(TAG, "CollectionsListAdapter.onCreateViewHolder(" + parent.getId() + ", " + i + ")");
        // Create a new view by inflating the row item xml.
        View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.shelf_collection, parent, false);

        // Set the view to the ViewHolder
        ViewHolder holder = new ViewHolder(v);

        holder.mHorizontalListView.setHasFixedSize(false);
        holder.mHorizontalListView.setHorizontalScrollBarEnabled(true);

        // use a linear layout manager
        LinearLayoutManager mLayoutManager = new LinearLayoutManager(mContext);
        mLayoutManager.setOrientation(LinearLayoutManager.HORIZONTAL);
        holder.mHorizontalListView.setLayoutManager(mLayoutManager);

        return holder;
    }

    @Override
    public void onBindViewHolder(ViewHolder holder, int i) {
        Log.d(TAG, "CollectionsListAdapter.onBindViewHolder(" + holder.getPosition() + ", " + i + ")");

        Collection collection = mCollectionList.get(i);
        Log.d(TAG, "Collection : " + collection.getLabel());

        holder.mHeaderTitleTextView.setText(collection.getLabel());
        holder.mHeaderCountTextView.setText("" + collection.getBooks().size());

        // Create an adapter if none exists
        if (!mBookListAdapterMap.containsKey(collection.getCollectionId())) {
            mBookListAdapterMap.put(collection.getCollectionId(), new BookListAdapter(getActivity(), collection));
        }

        holder.mHorizontalListView.setAdapter(mBookListAdapterMap.get(collection.getCollectionId()));

    }

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

And finally, the Book adapter :

private class BookListAdapter extends RecyclerView.Adapter<BookListAdapter.ViewHolder> implements View.OnClickListener {
    private final String TAG = BookListAdapter.class.getSimpleName();

    // Create the ViewHolder class to keep references to your views
    class ViewHolder extends RecyclerView.ViewHolder {
        public ImageView mCoverImageView;

        public ViewHolder(View view) {
            super(view);
            mCoverImageView = (ImageView) view.findViewById(R.id.shelf_item_cover);
        }
    }

    @Override
    public void onClick(View v) {
        BookListAdapter.ViewHolder holder = (BookListAdapter.ViewHolder) v.getTag();
        int position = holder.getPosition();
        final Book book = mCollection.getBooks().get(position);

        // Click on cover image
        if (v.getId() == holder.mCoverImageView.getId()) {
            downloadOrOpenBook(book);
            return;
        }
    }

    private void downloadOrOpenBook(final Book book) {
        // do stuff
    }

    private Context mContext;
    private Collection mCollection;

    public BookListAdapter(Context context, Collection collection) {
        Log.d(TAG, "BookListAdapter(" + context + ", " + collection + ")");
        mCollection = collection;
        mContext = context;
    }

    @Override
    public ViewHolder onCreateViewHolder(ViewGroup parent, int i) {
        Log.d(TAG, "onCreateViewHolder(" + parent.getId() + ", " + i + ")");
        // Create a new view by inflating the row item xml.
        View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.shelf_grid_item, parent, false);

        // Set the view to the ViewHolder
        ViewHolder holder = new ViewHolder(v);
        holder.mCoverImageView.setOnClickListener(BookListAdapter.this); // Download or Open

        holder.mCoverImageView.setTag(holder);

        return holder;
    }

    @Override
    public void onBindViewHolder(ViewHolder holder, int i) {
        Log.d(TAG, "onBindViewHolder(" + holder.getPosition() + ", " + i + ")");

        Book book = mCollection.getBooks().get(i);

        ImageView imageView = holder.mCoverImageView;
        ImageLoader.getInstance().displayImage(book.getCoverUrl(), imageView);
    }

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

解决方案

@user2302510 solution works not as good as you may expected. Full workaround for both orientations and dynamically data changes is:

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++) {
            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 {
                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:
        }

        setMeasuredDimension(width, height);
    }

    private void measureScrapChild(RecyclerView.Recycler recycler, int position, int widthSpec,
                                   int heightSpec, int[] measuredDimension) {
        View view = recycler.getViewForPosition(position);
        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);
        }
    }
}

这篇关于嵌套循环器视图高度不换行的内容的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆