Instantly share code, notes, and snippets.

Embed
What would you like to do?
RecyclerView doesn't have an emptyView support, we gotta fix that
import android.content.Context;
import android.support.v7.widget.RecyclerView;
import android.util.AttributeSet;
import android.view.View;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
public class EmptyRecyclerView extends RecyclerView {
@Nullable View emptyView;
public EmptyRecyclerView(Context context) { super(context); }
public EmptyRecyclerView(Context context, AttributeSet attrs) { super(context, attrs); }
public EmptyRecyclerView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
void checkIfEmpty() {
if (emptyView != null) {
emptyView.setVisibility(getAdapter().getItemCount() > 0 ? GONE : VISIBLE);
}
}
final @NotNull AdapterDataObserver observer = new AdapterDataObserver() {
@Override public void onChanged() {
super.onChanged();
checkIfEmpty();
}
};
@Override public void setAdapter(@Nullable Adapter adapter) {
final Adapter oldAdapter = getAdapter();
if (oldAdapter != null) {
oldAdapter.unregisterAdapterDataObserver(observer);
}
super.setAdapter(adapter);
if (adapter != null) {
adapter.registerAdapterDataObserver(observer);
}
}
public void setEmptyView(@Nullable View emptyView) {
this.emptyView = emptyView;
checkIfEmpty();
}
}
@AnirudhaAgashe

This comment has been minimized.

AnirudhaAgashe commented Mar 23, 2015

Consider adding onItemRangeInserted and onItemRangeInserted to the observer

onChange is not fired when notifyItemRangeInserted and notifyItemRangeInserted is called on the adapter.

onItemRangeInserted, called when notifyItemRangeInserted).
Scenario: Initially the list is empty. But after adding items in range it will not be empty

onItemRangeRemoved to, called when notifyItemRangeRemoved is used.
Scenario: All the items might be removed from the data set and it may be empty

Thanks for the gist. I have forked you gist and added the above the changes. Also I have used Android's annotation instead of JetBrains to support Android Studio

@IlyaEremin

This comment has been minimized.

IlyaEremin commented Jun 15, 2015

Hi, you are a popular man!

@mobiRic

This comment has been minimized.

mobiRic commented Sep 3, 2015

Hello, I would like to use this code in future projects of mine.

  • Are you the original author?

Would you be happy if I fork this and add an Apache v2 licence to my copy, with attribution to you?

Thanks,
Richard
Glowworm Software
Cape Town, South Africa

@adelnizamutdinov

This comment has been minimized.

Owner

adelnizamutdinov commented Sep 6, 2015

@mobiRic you can do whatever you want with this code :)

@mobiRic

This comment has been minimized.

mobiRic commented Sep 7, 2015

Thanks - forked to https://gist.github.com/mobiRic/963a814d51259c730467

Can I suggest adding a method for swapAdapter() for completeness:

@Override
public void swapAdapter(Adapter adapter, boolean removeAndRecycleExistingViews) {
    final Adapter oldAdapter = getAdapter();
    if (oldAdapter != null) {
        oldAdapter.unregisterAdapterDataObserver(observer);
    }

    if (adapter != null) {
        adapter.registerAdapterDataObserver(observer);
    }
    super.swapAdapter(adapter, removeAndRecycleExistingViews);
    checkIfEmpty();
}
@sevar83

This comment has been minimized.

sevar83 commented Sep 11, 2015

@AnirudhaAgashe suggestion is correct!

@mmanishh

This comment has been minimized.

mmanishh commented Oct 9, 2015

@notnul coudnl't resolve

@bryant1410

This comment has been minimized.

bryant1410 commented Dec 7, 2015

maybe the emptyView attribute could be private

@subbuboyapati

This comment has been minimized.

subbuboyapati commented Feb 27, 2016

Hi @adelnizamutdinov , This we can achieve in flowing way.
Make two list item one for showing normal data and another one is for empty view

  1. In getitemcount, if count is zero return 1 otherwise size of an adapter.
  2. In itemViewType if size 0 return empty view type otherwise return your normal list item.
@Ghostish

This comment has been minimized.

Ghostish commented Feb 27, 2016

Really appreciate this great idea . It works well.

@Honghe

This comment has been minimized.

Honghe commented Jul 13, 2016

adapter.notifyItemRemoved(position); will not evoke checkIfEmpty()

@wangyiyong

This comment has been minimized.

wangyiyong commented May 4, 2017

But where is the emptyView attached?

@beraybentesen

This comment has been minimized.

beraybentesen commented Jun 10, 2017

Does nothing when I use following method :
recyclerView.postDelayed(() -> Notify RecyclerView

Inflated like this :
View headerView = View.inflate(getActivity(), R.layout.layout_empty_view, null);

@josemigallas

This comment has been minimized.

josemigallas commented Oct 13, 2017

@adelnizamutdinov
Hi, I think there's a small typo on line 25. Shouldn't it be @NonNull instead of @NotNull?

@josemigallas

This comment has been minimized.

josemigallas commented Oct 13, 2017

It is also not working without implementing onItemRangeInserted in the observer. I'm using FirebaseUI.

@Blablablar

This comment has been minimized.

Blablablar commented May 22, 2018

I have the same question, where is the emptyView attached?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment