How to Have a Listview/Recyclerview Inside a Parent Recyclerview

How to have a ListView/RecyclerView inside a parent RecyclerView?

I got this issue few days ago and finally solved it. All you have to do is @override the layout manager onMeasure function as below:

CustomLinearLayoutManager

public class CustomLinearLayoutManager extends LinearLayoutManager {

private static final String TAG = CustomLinearLayoutManager.class.getSimpleName();

public CustomLinearLayoutManager(Context context) {
super(context);
}

public CustomLinearLayoutManager(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) {
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();
}
}
}

You can just copy and paste this CustomLinearLayoutManager set it to your child RecyclerView like this:

RecyclerView.LayoutManager layoutManager = new CustomLinearLayoutManager(mContext);
holder.childRecyclerView.setLayoutManager(layoutManager);

Remember : Don't use CustomLinearLayoutManager in parent RecyclerView, or it will throw error.

putting recyclerview in other Listview

I have implemented something similar i made a main listview instead of recycle view and made horizontal recycleview as row of llistview. Adding some code snippets Hope it help.

Main Activity - only simple list view
listview= (ListView) findViewById(R.id.listView);
ListAdapter adapter=new ListAdapter(this);
listview.setAdapter(adapter);

List Adapter
public class ListAdapter extends BaseAdapter {
private Context context;

private int lengt=4;
private String[] names={"Item 1","Item 2","Item 3 ","Item 4","Item 5"};
LayoutInflater layoutInflater;
RecyclerAdapter recyclerAdapter;
public ListAdapter(Context context){
this.context=context;
layoutInflater=(LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);

recyclerAdapter=new RecyclerAdapter(context);
}

@Override
public int getCount() {
return lengt;
}

@Override
public Object getItem(int i) {
return null;
}

@Override
public long getItemId(int i) {
return 0;
}

@Override
public View getView(final int i, View view, ViewGroup viewGroup) {
View view1=layoutInflater.inflate(R.layout.recyclelayout,null,false);
// here was text view
// TextView tittle=(TextView)view1.findViewById(R.id.textView);
// tittle.setText(names[i]);
// TextView se=(TextView)view1.findViewById(R.id.textView2);
// se.setText("See All >");
RecyclerView recyclerView=(RecyclerView)view1.findViewById(R.id.recycler);
recyclerView.setAdapter(recyclerAdapter);

LinearLayoutManager linearLayoutManager=new LinearLayoutManager(context,LinearLayoutManager.HORIZONTAL,false);
recyclerView.setLayoutManager(linearLayoutManager);
return view1;
}

}

xml of row of listview that is recyclelayout

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="match_parent"
android:clipToPadding="false">
<android.support.v7.widget.RecyclerView
android:layout_width="match_parent"
android:layout_height="150dp"
android:id="@+id/recycler">
</android.support.v7.widget.RecyclerView>

And the Recycleview adapter class is this.

class RecyclerAdapter extends RecyclerView.Adapter<RecyclerAdapter.RecyclerHolder> {
public int[] image={R.drawable.ic_close_24dp,R.drawable.ic_more_vert_24dp,R.drawable.ic_play_arrow_24dp,R.drawable.ic_skip_next_24dp};
private Context context;
public RecyclerAdapter(Context context){
this.context=context;
}
@Override
public RecyclerHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View v= LayoutInflater.from(parent.getContext()).inflate(R.layout.recyclercontent,parent,false);
RecyclerHolder vh=new RecyclerHolder(v);
return vh;
}

@Override
public void onBindViewHolder(RecyclerHolder holder, int position) {
holder.imageView.setImageResource(image[position]);
}

@Override
public int getItemCount() {
return image.length;
}

public class RecyclerHolder extends RecyclerView.ViewHolder implements View.OnClickListener{
public ImageView imageView;
public CardView cardView;
public RecyclerHolder(View itemView) {
super(itemView);
imageView=(ImageView)itemView.findViewById(R.id.imageView2);
cardView=(CardView)itemView.findViewById(R.id.carview);
imageView.setOnClickListener(this);
}

@Override
public void onClick(View view) {
if (view.getId() == imageView.getId()) {
Toast.makeText(view.getContext(),"Item Pressed =" + String.valueOf(getAdapterPosition()),Toast.LENGTH_SHORT).show();
// Intent intent=new Intent(context,ItemInfo.class);
// context.startActivity(intent);
}
}
}

}

It Looks Like this with each row have recycleview
Any doubt just let me know. Hope it helps you.

EDIT- adding remaining xml files

recyclercontent.xml

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="#ffffff"
android:outlineProvider="bounds">
<android.support.v7.widget.CardView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_margin="10dp"
android:translationZ="10dp"
android:id="@+id/carview">
<ImageView
android:layout_width="150dp"
android:layout_height="145dp"
android:id="@+id/imageView2"
android:layout_marginLeft="0dp" />
</android.support.v7.widget.CardView>

swipelayout.xml

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

<ImageView
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:id="@+id/imageView"
android:layout_gravity="center_vertical" />

Do I need to use list view inside recyclerView or recyclerView inside recyclerView?

Don't use ListView anymore, because it has been replaced by RecyclerView. I don't understand, why do you need to use RecyclerView inside RecyclerView?

If you paragraph is not very long, you can just use TextView inside a ScrollView.

If you paragraph is very long, you can use RecyclerView and use TextView as the View for the line item. Since RecyclerView use ViewHolder pattern, it will good for performance.



Related Topics



Leave a reply



Submit