Reputation: 593
I'm trying to make an empty view that is colored take up the remaining space after a RecyclerView. I've looked at different StackOverflow solutions but nothing works. Essentially I want something like this :
________________________
| |
| |
| |
| Recycler view |
| |
| ------------------- |
| colored empty view |
| |
| |
| |
| |
| |
_________________________
It should shrink as the RecyclerView grows.
________________________
| |
| |
| |
| Recycler view |
| |
| |
| |
| |
| |
| ------------------- |
| colored empty view |
| |
| |
_________________________
However if the RecyclerView exceeds one screen's worth, there should be no empty view. Here's what I have so far:
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:fab="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="@+id/bla_bla_layout">
<android.support.v7.widget.RecyclerView
android:id="@+id/bla_bla_recyclerview"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
<View
android:background="@color/grayBackground"
android:layout_gravity="bottom"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
<com.melnykov.fab.FloatingActionButton
android:id="@+id/fab"
android:contentDescription="@string/add_bla"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="bottom|right"
android:layout_margin="16dp"
android:src="@drawable/add_bla_icon"
fab:fab_colorNormal="@color/primary"
fab:fab_colorPressed="@color/primary_pressed"
fab:fab_colorRipple="@color/ripple" />
</FrameLayout>
EDIT This is not a duplicate of the mentioned question and you could see this if you read both questions. The solution to my question should be purely xml, layout based. By "empty view" I mean just some colored rectangle BELOW the existing RecyclerView, not a textview that actually says "Empty view" when there's no data in the RecylerView.
Upvotes: 14
Views: 12078
Reputation: 960
Recycler view calculate its height at runtime and we uses LinearLayoutManager to specify its height and width.
But problem is that, right now LinearLayoutManager does not support wrap_content it uses always match_parent for it's height.
So you have to use this LinearLayoutManager not android.support.v7.widget.LinearLayoutManager.
copy above java class in your package and use it like below,
LinearLayoutManager linearLayoutManager = new LinearLayoutManager(this,
LinearLayoutManager.VERTICAL, false);
recyclerView.setLayoutManager(linearLayoutManager);
// if it has fixed size
recyclerView.setHasFixedSize(true);
I tested it and its working as you need.
Upvotes: 6
Reputation: 11
Use a custom LinearLayoutManager hopefully its solve your problem.
use this code in your activity
RecycleView rv= (RecyclerView) rootView.findViewById(R.id.recycler_view);
CustomLinearLayoutManager lm= new CustomLinearLayoutManager(mActivity);
lm.setOrientation(LinearLayoutManager.VERTICAL);
lm.setHasFixedSize(true);
rv.setLayoutManager(lm);
Here is my CustomLinearLayoutManager
public class CustomLinearLayoutManager extends LinearLayoutManager {
public CustomLinearLayoutManager(Context context) {
super(context);
}
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);
measureScrapChild(recycler, 0,
View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED),
View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED),
mMeasuredDimension);
int width = mMeasuredDimension[0];
int height = mMeasuredDimension[1];
switch (widthMode) {
case View.MeasureSpec.EXACTLY:
case View.MeasureSpec.AT_MOST:
width = widthSize;
break;
case View.MeasureSpec.UNSPECIFIED:
}
switch (heightMode) {
case View.MeasureSpec.EXACTLY:
case View.MeasureSpec.AT_MOST:
height = heightSize;
break;
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(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();
measuredDimension[1] = view.getMeasuredHeight();
recycler.recycleView(view);
}
}catch(Exception e){
e.printStackTrace();
}
}
}
Upvotes: 0
Reputation: 1088
If you just want a different color in the remaining space, set the FrameLayout
's background to the desired color and set the RecyclerView
item's layout
background to white.
This will result in the remaining space in a separate color and the length of the populated items in recyclerView
will be white just as you need.
If you want some other view in the remaining space like a textView or an ImageView I guess you will have to extend RecyclerView class
and override
the method which calculates it's height.
Upvotes: 0
Reputation: 3470
It looks like you could accomplish with a RelativeLayout
using some align commands.
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<android.support.v7.widget.RecyclerView
android:id="@+id/recycler_view"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"/>
<View
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@+id/recycler_view"
android:layout_alignParentBottom="true"
android:background="@color/blue"/>
</RelativeLayout>
</FrameLayout>
I included the FrameLayout
because you mentioned in another comment that you needed it to use with a FAB.
If you load this into AndroidStudio and start setting sample widths (50dp, 150dp, 300dp...) for the height of the RecyclerView
you will see the View
below it start to adjust its height as well.
Upvotes: 0
Reputation: 3562
Try this
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/bla_bla_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<android.support.v7.widget.RecyclerView
android:id="@+id/bla_bla_recyclerview"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:entries="@array/array_sample" />
<View
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="1"
android:background="@color/grayBackground" />
</LinearLayout>
Upvotes: 1