Use Recyclerview Inside Scrollview with Flexible Recycler Item Height

Use RecyclerView inside ScrollView with flexible Recycler item height

I search for answer this question all over the world but I didn't found any direct answer for this popular question. At last I mixed some trick together and solved this problem!

My problem start when my boss asked me to use a RecyclerView inside a ScrollView, and as you know we cannot use two Scrollable objects inside each other except when we set or know fix item height for our RecyclerView. and this is the answer:

Step 1:
at first you should find your RecyclerView flexible item height and this is possible from your RecyclerView>onBindViewHolder

holder.itemView.post(new Runnable() {
@Override
public void run() {

int cellWidth = holder.itemView.getWidth();// this will give you cell width dynamically
int cellHeight = holder.itemView.getHeight();// this will give you cell height dynamically

dynamicHeight.HeightChange(position, cellHeight); //call your iterface hear
}
});

with this code you find your item height as them build and send the item height to your activity with interface.

for those friend who have problem with interface i leave interface code below that should write in Adapter.

public interface DynamicHeight {
void HeightChange (int position, int height);
}

Step 2:
we found our item height so far and now we want to set height to our RecyclerView. first we should calculate the Summation of item height. in this step we do this by BitMap
first implements last step interface and write these code below inside your Activity or Fragment that define your RecyclerView:

@Override
public void HeightChange(int position, int height) {
itemHeight.put(position, height);
sumHeight = SumHashItem (itemHeight);

float density = activity.getResources().getDisplayMetrics().density;
float viewHeight = sumHeight * density;
review_recyclerView.getLayoutParams().height = (int) sumHeight;

int i = review_recyclerView.getLayoutParams().height;
}

int SumHashItem (HashMap<Integer, Integer> hashMap) {
int sum = 0;

for(Map.Entry<Integer, Integer> myItem: hashMap.entrySet()) {
sum += myItem.getValue();
}

return sum;
}

Step 3:
now we have the summation of your RecyclerView height. for last step we should just send the Interface that we write in last step to adapter with some code like this:

reviewRecyclerAdapter = new ReviewRecyclerAdapter(activity, reviewList, review_recyclerView, this);

when you implement interface, you should send it to your with your context that I use this.

Enjoy it

Use RecyclerView inside ScrollView with fixed Recycler item height

I think you have not setLayoutParams. When you change the layout params of a view, you need to set it, eg, this is how you set it for your recyclerview:

 LinearLayout.LayoutParams layoutParams  = mRecyclerView_other.getLayoutParams();
layoutParams.width = 64;
layoutParams.height = 64;
mRecyclerView_other.setLayoutParams(layoutParams);

You are also setting your width and height using integer values instead of pulling them from the dimens.xml - try this:

In your dimens.xml file:

<dimen name="test">64dp</dimen>

Then extract the int value like this:

int valueInPixels = (int) getResources().getDimension(R.dimen.test)

RecyclerView inside ScrollView is not working

use NestedScrollView instead of ScrollView

Please go through NestedScrollView reference document for more information.

and add recyclerView.setNestedScrollingEnabled(false); to your RecyclerView

Recyclerview inside scrollview- How to scroll whole content?

Use the android.support.v4.widget.NestedScrollView then inside both layout
NestedScrollView

recyclerview inside scroll view affects scroll position

This worked for me:

mRecyclerView.setFocusable(false);

Although a lot of good answers here: How to scroll to top of long ScrollView layout?

Making Recyclerview Fixed Height and Scrollable

So what my problem was that for some reason, Recyclerview didnt wrap_contents. I did some research (thanks stackoverflow) and found out a lot of people were having this issue and they posted solutions for this issue.

Basically, I had to use a customized linearlayoutmanger to fix the issue.

I will post the solution they posted and links to their questions. thanks for whoever tried to help, I appreciate it.

This is the extra file I needed. And then I had to set my recyclerview to use this layout instead of the default one.

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

After that. Change this:

 mProductsRecyclerView.setLayoutManager(new LinearLayoutManager(getApplicationContext()));

To this:

mRecyclerView.setLayoutManager(new MyLinearLayoutManager(getApplicationContext(),1,false));

Three new paramets(Context, int Orientation, boolean reverse);
basically, i put 1 for orientation so it shows vertiacally, and false for revers so it shows up how it is ordered in my List.

Links to other people's question with same problem as me.
Nested Recycler view height doesn't wrap its content

Nested Recycler view height doesn't wrap its content

Thanks once again guys. Hope this helps someone else



Related Topics



Leave a reply



Submit