嵌套循环器视图高度不换行的内容 [英] Nested Recycler view height doesn't wrap its content
问题描述
我有一个管理书籍类别(如播放列表)的应用程序。
我想显示收藏列表,并附有垂直RecyclerView每行,本书中的水平RecyclerView列表里面。
当我设置内水平面RecyclerView的layout_height到300dp,它显示正确,但是当我将其设置为WRAP_CONTENT,它不显示任何内容。 我需要使用WRAP_CONTENT,因为我希望能够改变布局管理器编程,以纵向和横向显示之间切换。
你知道我在做什么错了?
我的片段布局:
< LinearLayout中的xmlns:机器人=http://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:机器人=http://schemas.android.com/apk/res/android
机器人:layout_width =match_parent
机器人:layout_height =WRAP_CONTENT
机器人:方向=垂直>
< RelativeLayout的的xmlns:机器人=http://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:机器人=http://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 mHorizontalListView;
私人最终的TextView mEmptyTextView;
公共ViewHolder(查看视图){
超(视图);
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);
}
}
公共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.mHorizontalListView.setHasFixedSize(假);
holder.mHorizontalListView.setHorizontalScrollBarEnabled(真正的);
//使用线性布局管理器
LinearLayoutManager mLayoutManager =新LinearLayoutManager(mContext);
mLayoutManager.setOrientation(LinearLayoutManager.HORIZONTAL);
holder.mHorizontalListView.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.mHorizontalListView.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屋!