Odpowiednik ListView.setEmptyView w RecyclerView

Odpowiedzi:

69

Dzięki nowej funkcji wiązania danych możesz to również osiągnąć bezpośrednio w swoim układzie:

<TextView
   android:text="No data to display."
   android:visibility="@{dataset.size() > 0 ? View.GONE : View.VISIBLE}" />

W takim przypadku wystarczy dodać zmienną i import do sekcji danych w pliku XML:

<data>
<import type="android.view.View"/>
<variable
    name="dataset"
    type="java.util.List&lt;java.lang.String&gt;"
    />
</data>
André Diermann
źródło
6
Powyższy przykład jest uproszczony, aby podkreślić podejście do wiązania danych. Powiązanie danych jest bardzo elastyczne. Możesz oczywiście zaimportować Adapterzamiast zestawu danych i użyć jego getItemCount()lub zawinąć wszystko w a ViewModeli ustawić android:visibilityna viewModel.getEmptyViewVisibility().
André Diermann
4
To powinno być ocenione wyżej, jest to doskonały przykład możliwości wiązania danych
Ed George
1
@javmarina Nie, dla mnie układ nie aktualizował się dalej. Jeśli mój adapter zaczyna się od rozmiaru 0, a później zestaw danych rośnie, układ nie zostanie zaktualizowany zgodnie z wymaganiami. Wygląda na to, że wiązanie danych nie zadziała. :-(
meisteg
3
Czy to się zaktualizuje, nawet jeśli adapter dynamicznie rośnie lub zmniejsza się do zera? Wątpię w to.
david
1
@ a11n Nie aktualizuje układu, gdy lista zmniejsza się do 0 lub pobiera dane, musimy ustawić wartość powiązania z klasy za każdym razem, gdy wprowadzamy jakiekolwiek zmiany na liście, czy istnieje sposób na samodzielną aktualizację układu?
Deweloperzy Om Infowave
114

Oto klasa podobna do @dragon born's, ale bardziej kompletna. Na podstawie tego sedna .

public class EmptyRecyclerView extends RecyclerView {
    private View emptyView;
    final private AdapterDataObserver observer = new AdapterDataObserver() {
        @Override
        public void onChanged() {
            checkIfEmpty();
        }

        @Override
        public void onItemRangeInserted(int positionStart, int itemCount) {
            checkIfEmpty();
        }

        @Override
        public void onItemRangeRemoved(int positionStart, int itemCount) {
            checkIfEmpty();
        }
    };

    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 && getAdapter() != null) {
            final boolean emptyViewVisible = getAdapter().getItemCount() == 0;
            emptyView.setVisibility(emptyViewVisible ? VISIBLE : GONE);
            setVisibility(emptyViewVisible ? GONE : VISIBLE);
        }
    }

    @Override
    public void setAdapter(Adapter adapter) {
        final Adapter oldAdapter = getAdapter();
        if (oldAdapter != null) {
            oldAdapter.unregisterAdapterDataObserver(observer);
        }
        super.setAdapter(adapter);
        if (adapter != null) {
            adapter.registerAdapterDataObserver(observer);
        }

        checkIfEmpty();
    }

    public void setEmptyView(View emptyView) {
        this.emptyView = emptyView;
        checkIfEmpty();
    }
}
Marc Plano-Lesay
źródło
czy możesz wyjaśnić, jak mogę korzystać z tej klasy?
Ololoking
Dokładnie tak, jak w przypadku RecyclerView, po prostu dodaje setEmptyViewmetodę, którą możesz wywołać za każdym razem, gdy chcesz zdefiniować pusty widok. Zobacz ListView.setEmptyViewdokumentację, jeśli jest niejasna, to ten sam pomysł.
Marc Plano-Lesay
5
Podobna implementacja z Google Samples: github.com/googlesamples/android-XYZTouristAttractions/blob/ ...
jase
2
Fajne rozwiązanie, ale nazwa klasy jest dziwna =)
Шах
1
@AJW Myślę, że to głównie kwestia tego, co chcesz osiągnąć. Różnica między tymi dwiema implementacjami jest naprawdę niewielka i nic nie pozostaje, gdy tylko adapter zostanie ustawiony. Jeśli nie zmienisz adaptera (a tak jest najprawdopodobniej), nie ma różnicy.
Marc Plano-Lesay,
26

Rozwiązanie podane w tym linku wydaje się idealne. Używa viewType do identyfikowania, kiedy pokazać emptyView. Nie ma potrzeby tworzenia niestandardowego RecyclerView

Dodanie kodu z powyższego linku:

package com.example.androidsampleproject;
import java.util.ArrayList;
import java.util.List;
import android.app.Activity;
import android.os.Bundle;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;

public class RecyclerViewActivity extends Activity {

RecyclerView recyclerView;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_recycler_view);
    recyclerView = (RecyclerView) findViewById(R.id.myList);
    recyclerView.setLayoutManager(new LinearLayoutManager(this));
    recyclerView.setAdapter(new MyAdapter());
}


private class MyAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
    private List<String> dataList = new ArrayList<String>();

    public class EmptyViewHolder extends RecyclerView.ViewHolder {
        public EmptyViewHolder(View itemView) {
            super(itemView);
        }
    }

    public class ViewHolder extends RecyclerView.ViewHolder {
        TextView data;

        public ViewHolder(View v) {
            super(v);
            data = (TextView) v.findViewById(R.id.data_view);
        }
    }

    @Override
    public int getItemCount() {
        return dataList.size() > 0 ? dataList.size() : 1;
    }

    @Override
    public int getItemViewType(int position) {
        if (dataList.size() == 0) {
            return EMPTY_VIEW;
        }
        return super.getItemViewType(position);
    }


    @Override
    public void onBindViewHolder(RecyclerView.ViewHolder vho, final int pos) {
        if (vho instanceof ViewHolder) {
            ViewHolder vh = (ViewHolder) vho;
            String pi = dataList.get(pos);
        }
    }

    @Override
    public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        View v;

        if (viewType == EMPTY_VIEW) {
            v = LayoutInflater.from(parent.getContext()).inflate(R.layout.empty_view, parent, false);
            EmptyViewHolder evh = new EmptyViewHolder(v);
            return evh;
        }

        v = LayoutInflater.from(parent.getContext()).inflate(R.layout.data_row, parent, false);
        ViewHolder vh = new ViewHolder(v);
        return vh;
    }

    private static final int EMPTY_VIEW = 10;
}

}
Sudhasri
źródło
6
Myślę, że rozszerzenie RecyclerView jest bardziej przystępnym rozwiązaniem niż to, ponieważ generalnie mam wiele adapterów recyklerów i chcę uniknąć dodawania tego rodzaju logiki do każdego z nich.
Gunhan
To ma sens @Gunhan, gdy używasz wielu adapterów recyklerów. Możesz także spróbować rozszerzyć pojedynczy adapter BaseAdapter dostosowany do typowych rzeczy we wszystkich
Sudhasri
2
Nawet jeśli masz tylko jeden adapter i jeden widok recyklera, nie jest to odpowiedzialność adaptera. Adapter służy do prezentacji przedmiotów, a nie ich braku.
Marc Plano-Lesay
@Kernald Zależy od twojego przypadku użycia. Osobiście uważam, że jest o wiele czystszy, tak jak zrobił to Sudhasri. Zwłaszcza jeśli chcesz pokazać inny widok w przypadku braku prezentów, np .: „Brak przedmiotów, idź na zakupy!” czy coś w tym rodzaju
AgentKnopf
@Zainodis Jak powiedziałeś, to inny widok. Nie jest to odpowiedzialność adaptera, która polega na wyświetlaniu elementów w widoku recyklingu, nic więcej. Zgadzam się, że technicznie rzecz biorąc, oba rozwiązania działają i są prawie równe. Ale elementy adaptera nie są przeznaczone do wyświetlania takich widoków.
Marc Plano-Lesay
10

Wolałbym po prostu proste rozwiązanie, takie jak:

mieć RecyclerView wewnątrz FrameLayout lub RelativeLayout z TextView lub innym widokiem z wyświetlaniem pustego komunikatu danych z widocznością GONE domyślnie, a następnie w klasie adaptera zastosuj logikę

Tutaj mam jeden TextView z komunikatem bez danych

@Override
public int getItemCount() {
    textViewNoData.setVisibility(data.size() > 0 ? View.GONE : View.VISIBLE);
    return data.size();
}
Lalit Poptani
źródło
3

Spróbuj RVEmptyObserver:

Jest to implementacja, AdapterDataObserverktóra pozwala po prostu ustawić Viewjako domyślny pusty układ dla twojego RecylerView. W ten sposób zamiast używać niestandardowego RecyclerViewi utrudniać sobie życie, możesz łatwo użyć go z istniejącym kodem:


Przykładowe zastosowanie:

RVEmptyObserver observer = new RVEmptyObserver(recyclerView, emptyView)
rvAdapter.registerAdapterDataObserver(observer);

Możesz zobaczyć kod i przykładowe użycie w rzeczywistej aplikacji tutaj.


Klasa:

public class RVEmptyObserver extends RecyclerView.AdapterDataObserver {
    private View emptyView;
    private RecyclerView recyclerView;

    public RVEmptyObserver(RecyclerView rv, View ev) {
        this.recyclerView = rv;
        this.emptyView    = ev;
        checkIfEmpty();
    }

    private void checkIfEmpty() {
        if (emptyView != null && recyclerView.getAdapter() != null) {
            boolean emptyViewVisible = recyclerView.getAdapter().getItemCount() == 0;
            emptyView.setVisibility(emptyViewVisible ? View.VISIBLE : View.GONE);
            recyclerView.setVisibility(emptyViewVisible ? View.GONE : View.VISIBLE);
        }
    }

    public void onChanged() { checkIfEmpty(); }
    public void onItemRangeInserted(int positionStart, int itemCount) { checkIfEmpty(); }
    public void onItemRangeRemoved(int positionStart, int itemCount) { checkIfEmpty(); }
}
Sheharyar
źródło
2

Moja wersja oparta na https://gist.github.com/adelnizamutdinov/31c8f054d1af4588dc5c

public class EmptyRecyclerView extends RecyclerView {
    @Nullable
    private 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);
    }

    private void checkIfEmpty() {
        if (emptyView != null && getAdapter() != null) {
            emptyView.setVisibility(getAdapter().getItemCount() > 0 ? GONE : VISIBLE);
        }
    }

    private final AdapterDataObserver observer = new AdapterDataObserver() {
        @Override
        public void onChanged() {
            checkIfEmpty();
        }

        @Override
        public void onItemRangeInserted(int positionStart, int itemCount) {
            checkIfEmpty();
        }

        @Override
        public void onItemRangeRemoved(int positionStart, int itemCount) {
            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);
        }
        checkIfEmpty();
    }

    @Override
    public void setVisibility(int visibility) {
        super.setVisibility(visibility);
        if (null != emptyView && (visibility == GONE || visibility == INVISIBLE)) {
            emptyView.setVisibility(GONE);
        } else {
            checkIfEmpty();
        }
    }

    public void setEmptyView(@Nullable View emptyView) {
        this.emptyView = emptyView;
        checkIfEmpty();
    }
}
Lokalny Gospodarz
źródło
3
Dobry pomysł na ponowne wdrożenie setVisibility.
Marc Plano-Lesay
2

Wolałbym zaimplementować tę funkcjonalność w Recycler.Adapter

W swojej nadpisanej metodzie getItemCount wprowadź tam puste kody kontrolne:

@Override
public int getItemCount() {
    if(data.size() == 0) listIsEmtpy();
    return data.size();
}
Bilal
źródło
3
To nie jest odpowiedzialność adaptera. Adapter służy do prezentacji przedmiotów, a nie ich braku.
Marc Plano-Lesay
@Kernald To nasz kod i nasz własny sposób, jak go dostosowujemy i używamy.
Lalit Poptani,
@LalitPoptani pewnie. Ale jest to witryna z pytaniami i odpowiedziami, w której ludzie szukają odpowiedzi, przez większość czasu bez zastanawiania się, tylko „jaki jest znowu skrót do kopiowania?”. Wskazanie, że rozwiązanie jest błędne semantycznie (a ponadto, gdy masz również rozwiązania „praw”) nie jest tak naprawdę bezużyteczne…
Marc Plano-Lesay
@Kernald cóż, myślę, że to rozwiązanie jest najprostsze ze wszystkich i jest również dobrym rozwiązaniem, ponieważ za każdym razem, gdy adapter zostanie powiadomiony, zostanie to wywołane i może być użyte do sprawdzenia rozmiaru danych!
Lalit Poptani,
1
@ MarcPlano-Lesay ma rację. Ta odpowiedź jest niekompletna, ponieważ nie obsługuje przypadku, gdy pusty widok musi być niewidoczny po wypełnieniu elementów. Po wdrożeniu tej części rozwiązanie to staje się nieefektywne, ponieważ za każdym razem, gdy adapter pyta o liczbę elementów, setVisibility()zostaje wywołany. Oczywiście, możesz dodać kilka flag, aby to skompensować, ale wtedy staje się to bardziej złożone.
razzledazzle
2

Jeśli chcesz obsługiwać więcej stanów, takich jak stan ładowania, stan błędu, możesz sprawdzić https://github.com/rockerhieu/rv-adapter-states . W przeciwnym razie obsługę pustego widoku można łatwo zaimplementować za pomocą RecyclerViewAdapterWrapperfrom ( https://github.com/rockerhieu/rv-adapter ). Główną zaletą tego podejścia jest to, że można łatwo obsługiwać pusty widok bez zmiany logiki istniejącego adaptera:

public class StatesRecyclerViewAdapter extends RecyclerViewAdapterWrapper {
    private final View vEmptyView;

    @IntDef({STATE_NORMAL, STATE_EMPTY})
    @Retention(RetentionPolicy.SOURCE)
    public @interface State {
    }

    public static final int STATE_NORMAL = 0;
    public static final int STATE_EMPTY = 2;

    public static final int TYPE_EMPTY = 1001;

    @State
    private int state = STATE_NORMAL;

    public StatesRecyclerViewAdapter(@NonNull RecyclerView.Adapter wrapped, @Nullable View emptyView) {
        super(wrapped);
        this.vEmptyView = emptyView;
    }

    @State
    public int getState() {
        return state;
    }

    public void setState(@State int state) {
        this.state = state;
        getWrappedAdapter().notifyDataSetChanged();
        notifyDataSetChanged();
    }

    @Override
    public int getItemCount() {
        switch (state) {
            case STATE_EMPTY:
                return 1;
        }
        return super.getItemCount();
    }

    @Override
    public int getItemViewType(int position) {
        switch (state) {
            case STATE_EMPTY:
                return TYPE_EMPTY;
        }
        return super.getItemViewType(position);
    }

    @Override
    public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        switch (viewType) {
            case TYPE_EMPTY:
                return new SimpleViewHolder(vEmptyView);
        }
        return super.onCreateViewHolder(parent, viewType);
    }

    @Override
    public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
        switch (state) {
            case STATE_EMPTY:
                onBindEmptyViewHolder(holder, position);
                break;
            default:
                super.onBindViewHolder(holder, position);
                break;
        }
    }

    public void onBindEmptyViewHolder(RecyclerView.ViewHolder holder, int position) {
    }

    public static class SimpleViewHolder extends RecyclerView.ViewHolder {
        public SimpleViewHolder(View itemView) {
            super(itemView);
        }
    }
}

Stosowanie:

Adapter adapter = originalAdapter();
StatesRecyclerViewAdapter statesRecyclerViewAdapter = new StatesRecyclerViewAdapter(adapter, emptyView);
rv.setAdapter(endlessRecyclerViewAdapter);

// Change the states of the adapter
statesRecyclerViewAdapter.setState(StatesRecyclerViewAdapter.STATE_EMPTY);
statesRecyclerViewAdapter.setState(StatesRecyclerViewAdapter.STATE_NORMAL);
Hieu Rocker
źródło
Użyłem twojego kodu jako podstawy do podobnego rozwiązania. Dzięki!
Albert Vila Calvo,
2

Naprawiłem to:
Utworzono plik layout_recyclerview_with_emptytext.xml układu.
Utworzono EmptyViewRecyclerView.java
---------

EmptyViewRecyclerView emptyRecyclerView = (EmptyViewRecyclerView) findViewById (R.id.emptyRecyclerViewLayout);
emptyRecyclerView.addAdapter (mPrayerCollectionRecyclerViewAdapter, "Nie ma modlitwy dla wybranej kategorii.");

plik layout_recyclerview_with_emptytext.xml

    <?xml version="1.0" encoding="utf-8"?>
    <merge xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/switcher"
>

<android.support.v7.widget.RecyclerView
    android:id="@+id/recyclerView"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    />

<com.ninestars.views.CustomFontTextView android:id="@+id/recyclerViewEmptyTextView"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:text="Empty Text"
    android:layout_gravity="center"
    android:gravity="center"
    android:textStyle="bold"
    />

    </merge>


EmptyViewRecyclerView.java

public class EmptyViewRecyclerView extends ViewSwitcher {
private RecyclerView mRecyclerView;
private CustomFontTextView mRecyclerViewExptyTextView;

public EmptyViewRecyclerView(Context context) {
    super(context);
    initView(context);
}

public EmptyViewRecyclerView(Context context, AttributeSet attrs) {
    super(context, attrs);
    initView(context);
}


private void initView(Context context) {
    LayoutInflater.from(context).inflate(R.layout.layout_recyclerview_with_emptytext, this, true);
    mRecyclerViewExptyTextView = (CustomFontTextView) findViewById(R.id.recyclerViewEmptyTextView);
    mRecyclerView = (RecyclerView) findViewById(R.id.recyclerView);
    mRecyclerView.setLayoutManager(new LinearLayoutManager(context));
}

public void addAdapter(final RecyclerView.Adapter<?> adapter) {
    mRecyclerView.setAdapter(adapter);
    adapter.registerAdapterDataObserver(new RecyclerView.AdapterDataObserver() {
        @Override
        public void onChanged() {
            super.onChanged();
            if(adapter.getItemCount() > 0) {
                if (R.id.recyclerView == getNextView().getId()) {
                    showNext();
                }
            } else {
                if (R.id.recyclerViewEmptyTextView == getNextView().getId()) {
                    showNext();
                }
            }
        }
    });
}

public void addAdapter(final RecyclerView.Adapter<?> adapter, String emptyTextMsg) {
    addAdapter(adapter);
    setEmptyText(emptyTextMsg);
}

public RecyclerView getRecyclerView() {
    return mRecyclerView;
}

public void setEmptyText(String emptyTextMsg) {
    mRecyclerViewExptyTextView.setText(emptyTextMsg);
}

}
Ashwani
źródło
1
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();
  }
}

coś takiego może pomóc

Munawwar Hussain Shelia
źródło
2
To jest niekompletne. Prawdopodobnie będziesz musiał ukryć, RecyclerViewgdy emptyViewjest widoczny (i odwrotnie). Musisz także zadzwonić checkIfEmpty()do onItemRangeInserted()i onItemRangeRemoved(). Aha, i mogłeś zacytować swoje źródło: gist.github.com/adelnizamutdinov/31c8f054d1af4588dc5c
Marc Plano-Lesay
1

Możesz po prostu pomalować tekst, RecyclerViewgdy jest pusty. Poniższy zwyczaj podklasa podpory empty, failed, loading, i offlinetryby. Aby kompilacja przebiegła pomyślnie, dodaj recyclerView_stateTextkolor do zasobów.

/**
 * {@code RecyclerView} that supports loading and empty states.
 */
public final class SupportRecyclerView extends RecyclerView
{
    public enum State
    {
        NORMAL,
        LOADING,
        EMPTY,
        FAILED,
        OFFLINE
    }

    public SupportRecyclerView(@NonNull Context context)
    {
        super(context);

        setUp(context);
    }

    public SupportRecyclerView(@NonNull Context context, @Nullable AttributeSet attrs)
    {
        super(context, attrs);

        setUp(context);
    }

    public SupportRecyclerView(@NonNull Context context, @Nullable AttributeSet attrs, int defStyle)
    {
        super(context, attrs, defStyle);

        setUp(context);
    }

    private Paint textPaint;
    private Rect textBounds;
    private PointF textOrigin;

    private void setUp(Context c)
    {
        textPaint = new Paint();
        textPaint.setAntiAlias(true);
        textPaint.setColor(ContextCompat.getColor(c, R.color.recyclerView_stateText));

        textBounds = new Rect();
        textOrigin = new PointF();
    }

    private State state;

    public State state()
    {
        return state;
    }

    public void setState(State newState)
    {
        state = newState;
        calculateLayout(getWidth(), getHeight());
        invalidate();
    }

    private String loadingText = "Loading...";

    public void setLoadingText(@StringRes int resId)
    {
        loadingText = getResources().getString(resId);
    }

    private String emptyText = "Empty";

    public void setEmptyText(@StringRes int resId)
    {
        emptyText = getResources().getString(resId);
    }

    private String failedText = "Failed";

    public void setFailedText(@StringRes int resId)
    {
        failedText = getResources().getString(resId);
    }

    private String offlineText = "Offline";

    public void setOfflineText(@StringRes int resId)
    {
        offlineText = getResources().getString(resId);
    }

    @Override
    public void onDraw(Canvas canvas)
    {
        super.onDraw(canvas);

        String s = stringForCurrentState();
        if (s == null)
            return;

        canvas.drawText(s, textOrigin.x, textOrigin.y, textPaint);
    }

    private void calculateLayout(int w, int h)
    {
        String s = stringForCurrentState();
        if (s == null)
            return;

        textPaint.setTextSize(.1f * w);
        textPaint.getTextBounds(s, 0, s.length(), textBounds);

        textOrigin.set(
         w / 2f - textBounds.width() / 2f - textBounds.left,
         h / 2f - textBounds.height() / 2f - textBounds.top);
    }

    @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh)
    {
        super.onSizeChanged(w, h, oldw, oldh);

        calculateLayout(w, h);
    }

    private String stringForCurrentState()
    {
        if (state == State.EMPTY)
            return emptyText;
        else if (state == State.LOADING)
            return loadingText;
        else if (state == State.FAILED)
            return failedText;
        else if (state == State.OFFLINE)
            return offlineText;
        else
            return null;
    }
}
Aleks N.
źródło
1

Z mojego punktu widzenia najłatwiejszym sposobem na wykonanie pustego widoku jest utworzenie nowego pustego widoku RecyclerView z układem, który chcesz nadmuchać jako tło. Ten pusty adapter jest ustawiany podczas sprawdzania rozmiaru zbioru danych.

user7108272
źródło