Come mostrare una vista vuota con un RecyclerView?


271

Sono abituato a inserire una vista speciale all'interno del file di layout come descritto nella ListActivitydocumentazione da visualizzare in assenza di dati . Questa vista ha l'id "android:id/empty".

<TextView
    android:id="@android:id/empty"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="@string/no_data" />

Mi chiedo come si possa fare questo con il nuovo RecyclerView?


2
Puoi usare github.com/rockerhieu/rv-adapter-states , supporta non solo la vista vuota ma anche il caricamento della vista e della vista errori. E puoi usarlo senza cambiare la logica dell'adattatore esistente.
Hieu Rocker,

20
Non è per nulla affascinante che non sembra esserci un setEmptyView()metodo semplice contro un RecyclerView...
Subby,

Ecco la mia risposta, controlla questo link stackoverflow.com/a/58411351/5449220
Rakesh Verma

@Subby, d'accordo, ma setEmptyView()aveva anche uno svantaggio. Durante il caricamento dei dati, non volevamo mostrare la vista vuota in ListView, ma lo ha fatto. Quindi, abbiamo dovuto implementare un po 'di logica. Attualmente uso stackoverflow.com/a/48049142/2914140 .
CoolMind

Risposte:


306

Nello stesso layout in cui è definito il RecyclerView, aggiungere il TextView:

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

<TextView
    android:id="@+id/empty_view"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:gravity="center"
    android:visibility="gone"
    android:text="@string/no_data_available" />

Al onCreatecallback appropriato o si controlla se il set di dati che alimenta RecyclerViewè vuoto. Se il set di dati è vuoto, anche quello RecyclerViewè vuoto. In tal caso, il messaggio appare sullo schermo. In caso contrario, cambia la sua visibilità:

private RecyclerView recyclerView;
private TextView emptyView;

// ...

recyclerView = (RecyclerView) rootView.findViewById(R.id.recycler_view);
emptyView = (TextView) rootView.findViewById(R.id.empty_view);

// ...

if (dataset.isEmpty()) {
    recyclerView.setVisibility(View.GONE);
    emptyView.setVisibility(View.VISIBLE);
}
else {
    recyclerView.setVisibility(View.VISIBLE);
    emptyView.setVisibility(View.GONE);
}

11
Ciò non funziona per me perché il layout della vista del riciclatore è gonfiato nel frammento mentre la decisione se mostrare un layout normale di un articolo o un layout di nessun articolo viene presa nell'adattatore.
JJD

1
@JJD quando si utilizza un frammento, si applica la stessa cosa. Quando si gonfia la vista frammento, si ha la vista recyclerview e quindi un altro layout che verrebbe utilizzato per la vista vuota. Di solito nei miei frammenti avrò le seguenti visualizzazioni: 1) recyclerview, 2) vista vuota e 3) vista della barra di avanzamento. Di solito passo l'adattatore qualunque sia l'elenco, ma in base alle dimensioni dell'elenco nasconderò il recyclerview e mostrerò il vuoto o viceversa. Se un recyclerview ha un elenco vuoto, non fa nulla con esso. Vedi solo una vista vuota.
Ray Hunter,

1
@stackex La verifica deve essere nel callback onCreateView del frammento o onResume of Activity. In questo modo, la verifica verrà effettuata immediatamente prima che lo schermo venga visualizzato per l'utente e funzionerà per entrambi, aumentando o diminuendo la quantità di righe nel set di dati.
slellis,

2
@Zapnologica Puoi fare il contrario: Usa un Eventbus (come i greenrobot Eventbus o Otto), quindi inserisci l'adapter sul Eventbus quando il set di dati cambia. Nel frammento tutto ciò che fai è creare un metodo i cui parametri corrispondono a ciò che l'adapter sta passando nel metodo Eventbus.post e quindi modificare il layout di conseguenza. Un approccio più semplice ma anche più accoppiato è quello di creare un'interfaccia di callback nell'adattatore, e al momento della creazione dell'adattatore è necessario implementare il frammento.
AgentKnopf,

2
Nel layout ottengo più tag di root. Che aspetto ha il tuo file di layout completo?
powder366

192

Per i miei progetti ho realizzato questa soluzione ( RecyclerViewcon setEmptyViewmetodo):

public class RecyclerViewEmptySupport extends RecyclerView {
    private View emptyView;

    private AdapterDataObserver emptyObserver = new AdapterDataObserver() {


        @Override
        public void onChanged() {
            Adapter<?> adapter =  getAdapter();
            if(adapter != null && emptyView != null) {
                if(adapter.getItemCount() == 0) {
                    emptyView.setVisibility(View.VISIBLE);
                    RecyclerViewEmptySupport.this.setVisibility(View.GONE);
                }
                else {
                    emptyView.setVisibility(View.GONE);
                    RecyclerViewEmptySupport.this.setVisibility(View.VISIBLE);
                }
            }

        }
    };

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

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

    public RecyclerViewEmptySupport(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
    }

    @Override
    public void setAdapter(Adapter adapter) {
        super.setAdapter(adapter);

        if(adapter != null) {
            adapter.registerAdapterDataObserver(emptyObserver);
        }

        emptyObserver.onChanged();
    }

    public void setEmptyView(View emptyView) {
        this.emptyView = emptyView;
    }
}

E dovresti usarlo al posto della RecyclerViewclasse:

<com.maff.utils.RecyclerViewEmptySupport android:id="@+id/list1"
    android:layout_height="match_parent"
    android:layout_width="match_parent"
    />

<TextView android:id="@+id/list_empty"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="Empty"
    />

e

RecyclerViewEmptySupport list = 
    (RecyclerViewEmptySupport)rootView.findViewById(R.id.list1);
list.setLayoutManager(new LinearLayoutManager(context));
list.setEmptyView(rootView.findViewById(R.id.list_empty));

2
Hai preso questo codice da questa risposta o da qui ?
Sufian,

@Sufian No, non ho visto quella risposta, ho trovato allo stesso modo. Ma quel codice sembra decisamente più bello del mio :)
maff91

2
Ho provato a combinarlo con FirebaseRecyclerAdapter, non ha funzionato. Questo perché FirebaseRecyclerAdapter non chiama onChange (di AdapterDataObserver), ma chiama i metodi onItem *. Per farlo funzionare aggiungere: `Override public void onItemRangeRemoved (int positionStart, int itemCount) {// the check} Override public void onItemRangeMoved (int fromPosition, int toPosition, int itemCount) {// the check} // etc ..`
FrankkieNL,

1
Perché controlli se l'adattatore è nullo nell'osservatore? se l'adattatore è nullo, l'osservatore non dovrebbe mai essere chiamato.
Stimsoni,

16
Devo dire che questo è solo il classico Google BS. Devo implementarlo solo per aggiungere una vista vuota? Dovrebbe essere incluso nel loro SDK cr @ psh1t! Per l'amor di Dio!
Neon Warge,

62

Ecco una soluzione che utilizza solo un adattatore personalizzato con un tipo di vista diverso per la situazione vuota.

public class EventAdapter extends 
    RecyclerView.Adapter<EventAdapter.ViewHolder> {

    private static final int VIEW_TYPE_EVENT = 0;
    private static final int VIEW_TYPE_DATE = 1;
    private static final int VIEW_TYPE_EMPTY = 2;

    private ArrayList items;

    public EventAdapter(ArrayList items) {
        this.items = items;
    }

    @Override
    public int getItemCount() {
        if(items.size() == 0){
            return 1;
        }else {
            return items.size();
        }
    }

    @Override
    public int getItemViewType(int position) {
        if (items.size() == 0) {
            return VIEW_TYPE_EMPTY;
        }else{
            Object item = items.get(position);
            if (item instanceof Event) {
                return VIEW_TYPE_EVENT;
            } else {
                return VIEW_TYPE_DATE;
            }
        }
    }

    @Override
    public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        View v;
        ViewHolder vh;
        if (viewType == VIEW_TYPE_EVENT) {
            v = LayoutInflater.from(parent.getContext()).inflate(
                R.layout.item_event, parent, false);
            vh = new ViewHolderEvent(v);
        } else if (viewType == VIEW_TYPE_DATE) {
            v = LayoutInflater.from(parent.getContext()).inflate(
                R.layout.item_event_date, parent, false);
            vh = new ViewHolderDate(v);
        } else {
            v = LayoutInflater.from(parent.getContext()).inflate(
                R.layout.item_event_empty, parent, false);
            vh = new ViewHolder(v);
        }

        return vh;
    }

    @Override
    public void onBindViewHolder(EventAdapter.ViewHolder viewHolder, 
                                 final int position) {
        int viewType = getItemViewType(position);
        if (viewType == VIEW_TYPE_EVENT) {
            //...
        } else if (viewType == VIEW_TYPE_DATE) {
            //...
        } else if (viewType == VIEW_TYPE_EMPTY) {
            //...
        }
    }

    public static class ViewHolder extends ParentViewHolder {
        public ViewHolder(View v) {
            super(v);
        }
    }

    public static class ViewHolderDate extends ViewHolder {

        public ViewHolderDate(View v) {
            super(v);
        }
    }

    public static class ViewHolderEvent extends ViewHolder {

        public ViewHolderEvent(View v) {
            super(v);
        }
    }

}

3
@ sfk92fksdf Perché è soggetto a errori? Questo è il modo in cui dovresti gestire più tipi di vista in
recyclerview

@billynomates, perché getItemCount()dovrebbe essere un oneliner ma qui abbiamo un non banale ifcon qualche logica nascosta. Questa logica appare anche goffamente in getItemViewTypee dio sa dove altro
Alexey Andronov

3
Non deve essere una riga. Se hai più tipi di vista, questo è il modo di farlo.
MSpeed,

@ sfk92fksdf Cosa intendi per logica nascosta? Il codice è proprio lassù ▲
radu122

1
a mio avviso questa risposta dovrebbe essere la risposta accettata. È davvero il modo di gestire diversi tipi di vista
Ivo Beckers,

45

Uso ViewSwitcher

<ViewSwitcher
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:id="@+id/switcher"
    >

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

    <TextView android:id="@+id/text_empty"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:text="@string/list_empty"
        android:gravity="center"
        />

</ViewSwitcher>

nel codice controllerai il cursore / set di dati e cambierai vista.

void showItems(Cursor items) {
    if (items.size() > 0) {

        mAdapter.switchCursor(items);

        if (R.id.list == mListSwitcher.getNextView().getId()) {
            mListSwitcher.showNext();
        }
    } else if (R.id.text_empty == mListSwitcher.getNextView().getId()) {
        mListSwitcher.showNext();
    }
}

Inoltre puoi impostare animazioni se lo desideri con un paio di righe di codice

mListSwitcher.setInAnimation(slide_in_left);
mListSwitcher.setOutAnimation(slide_out_right);

È davvero un romanzo
Zhang Xiang,

Soluzione pulita.
Ojonugwa Jude Ochalifu,

30

Dal momento che la risposta di Kevin non è completa.
Questa è la risposta più corretta se usi RecyclerAdapter's notifyItemInsertedenotifyItemRemoved di aggiornamento di dati. Guarda la versione di Kotlin che un altro utente ha aggiunto di seguito.

Giava:

mAdapter.registerAdapterDataObserver(new RecyclerView.AdapterDataObserver() {

    @Override
    public void onChanged() {
        super.onChanged();
        checkEmpty();
    }

    @Override
    public void onItemRangeInserted(int positionStart, int itemCount) {
        super.onItemRangeInserted(positionStart, itemCount);
        checkEmpty();
    }

    @Override
    public void onItemRangeRemoved(int positionStart, int itemCount) {
        super.onItemRangeRemoved(positionStart, itemCount);
        checkEmpty();
    }

    void checkEmpty() {
        mEmptyView.setVisibility(mAdapter.getItemCount() == 0 ? View.VISIBLE : View.GONE);
    }
});

Kotlin

adapter.registerAdapterDataObserver(object : RecyclerView.AdapterDataObserver() {
    override fun onChanged() {
        super.onChanged()
        checkEmpty()
    }

    override fun onItemRangeInserted(positionStart: Int, itemCount: Int) {
        super.onItemRangeInserted(positionStart, itemCount)
        checkEmpty()
    }

    override fun onItemRangeRemoved(positionStart: Int, itemCount: Int) {
        super.onItemRangeRemoved(positionStart, itemCount)
        checkEmpty()
    }

    fun checkEmpty() {
        empty_view.visibility = (if (adapter.itemCount == 0) View.VISIBLE else View.GONE)
    }
})

2
Questa è un'ottima soluzione Sto proponendo una modifica che includerà la versione di kotlin.
jungledev,

Questo sembra buono ma potrebbe non funzionare se chiami swapAdapter () o addirittura setAdapter () più di una volta.
Glauco

Penso che sia la soluzione più elegante!
Appassionato di Android il

Ottimo lavoro. non dimenticare di nascondere RecyclerView quando mostra l'etichetta
MrG

18

RVEmptyObserver

Invece di utilizzare una personalizzazione RecyclerView, l'estensione di AdapterDataObserverè una soluzione più semplice che consente di impostare una personalizzazione Viewche viene visualizzata quando non ci sono elementi nell'elenco:

Esempio di utilizzo:

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

Classe:

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

Credo che sarà più veloce se non si chiama checkIfEmpty()in onChanged()eonItemRangeInserted()
Geekarist

Sono d'accordo (ed è quello che ho fatto personalmente) ma questo doveva essere solo un punto di partenza per le persone che affrontano questo problema.
Sheharyar,

9

Nel tuo adattatore getItemViewTypecontrolla se l'adattatore ha 0 elementi e restituisce un viewType diverso in tal caso.

Quindi onCreateViewHoldercontrolla se viewType è quello che hai restituito in precedenza e gonfia una vista diversa. In questo caso un file di layout con quel TextView

MODIFICARE

Se il problema persiste, ti consigliamo di impostare le dimensioni della vista in modo programmatico in questo modo:

Point size = new Point();
((WindowManager)itemView.getContext().getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay().getSize(size);

E poi quando si gonfia la chiamata di visualizzazione:

inflatedView.getLayoutParams().height = size.y;
inflatedView.getLayoutParams().width = size.x;

Suona bene. Tuttavia non ho ricevuto in onCreateViewHolderquando il mio insieme di dati è nullo svuotare dal momento che ho di tornare 0in getItemCount.
JJD,

Quindi restituire 1 se è null :)
Pedro Oliveira il

Funziona un po '. Grazie. - Il dettaglio minore è che non riesco a centrare verticalmente la voce dell'elenco vuota nella vista del riciclatore. La visualizzazione del testo rimane nella parte superiore dello schermo, tuttavia ho impostato android:layout_gravity="center"e android:layout_height="match_parent"per la vista del riciclatore principale.
JJD

Dipende dal layout della riga che stai utilizzando. Dovrebbe match_parent sulla sua altezza. Se non riesci ancora a farlo funzionare, aggiungi un listener di layout globale e imposta i parametri di layout in modo che abbiano la stessa altezza e larghezza dello schermo.
Pedro Oliveira,

Tutti i contenitori (attività, frammento, layout lineare, vista riciclatore, vista testo) sono impostati su android:layout_height="match_parent". Sebbene la riga non si espanda all'altezza dello schermo.
JJD

8

Ecco la mia classe per mostrare la vista vuota, riprovare la vista (quando il caricamento dell'API non è riuscito) e il caricamento dell'avanzamento per RecyclerView

public class RecyclerViewEmptyRetryGroup extends RelativeLayout {
    private RecyclerView mRecyclerView;
    private LinearLayout mEmptyView;
    private LinearLayout mRetryView;
    private ProgressBar mProgressBar;
    private OnRetryClick mOnRetryClick;

    public RecyclerViewEmptyRetryGroup(Context context) {
        this(context, null);
    }

    public RecyclerViewEmptyRetryGroup(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public RecyclerViewEmptyRetryGroup(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }

    @Override
    public void onViewAdded(View child) {
        super.onViewAdded(child);
        if (child.getId() == R.id.recyclerView) {
            mRecyclerView = (RecyclerView) findViewById(R.id.recyclerView);
            return;
        }
        if (child.getId() == R.id.layout_empty) {
            mEmptyView = (LinearLayout) findViewById(R.id.layout_empty);
            return;
        }
        if (child.getId() == R.id.layout_retry) {
            mRetryView = (LinearLayout) findViewById(R.id.layout_retry);
            mRetryView.setOnClickListener(new OnClickListener() {
                @Override
                public void onClick(View v) {
                    mRetryView.setVisibility(View.GONE);
                    mOnRetryClick.onRetry();
                }
            });
            return;
        }
        if (child.getId() == R.id.progress_bar) {
            mProgressBar = (ProgressBar) findViewById(R.id.progress_bar);
        }
    }

    public void loading() {
        mRetryView.setVisibility(View.GONE);
        mEmptyView.setVisibility(View.GONE);
        mProgressBar.setVisibility(View.VISIBLE);
    }

    public void empty() {
        mEmptyView.setVisibility(View.VISIBLE);
        mRetryView.setVisibility(View.GONE);
        mProgressBar.setVisibility(View.GONE);
    }

    public void retry() {
        mRetryView.setVisibility(View.VISIBLE);
        mEmptyView.setVisibility(View.GONE);
        mProgressBar.setVisibility(View.GONE);
    }

    public void success() {
        mRetryView.setVisibility(View.GONE);
        mEmptyView.setVisibility(View.GONE);
        mProgressBar.setVisibility(View.GONE);
    }

    public RecyclerView getRecyclerView() {
        return mRecyclerView;
    }

    public void setOnRetryClick(OnRetryClick onRetryClick) {
        mOnRetryClick = onRetryClick;
    }

    public interface OnRetryClick {
        void onRetry();
    }
}

activity_xml

<...RecyclerViewEmptyRetryGroup
        android:id="@+id/recyclerViewEmptyRetryGroup">

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

        <LinearLayout
            android:id="@+id/layout_empty">
            ...
        </LinearLayout>

        <LinearLayout
            android:id="@+id/layout_retry">
            ...
        </LinearLayout>

        <ProgressBar
            android:id="@+id/progress_bar"/>

</...RecyclerViewEmptyRetryGroup>

inserisci qui la descrizione dell'immagine

La fonte è qui https://github.com/PhanVanLinh/AndroidRecyclerViewWithLoadingEmptyAndRetry


7

Utilizzare AdapterDataObserver in RecyclerView personalizzato

Kotlin:

RecyclerViewEnum.kt

enum class RecyclerViewEnum {
    LOADING,
    NORMAL,
    EMPTY_STATE
}

RecyclerViewEmptyLoadingSupport.kt

class RecyclerViewEmptyLoadingSupport : RecyclerView {

    var stateView: RecyclerViewEnum? = RecyclerViewEnum.LOADING
        set(value) {
            field = value
            setState()
        }
    var emptyStateView: View? = null
    var loadingStateView: View? = null


    constructor(context: Context) : super(context) {}

    constructor(context: Context, attrs: AttributeSet) : super(context, attrs) {}

    constructor(context: Context, attrs: AttributeSet, defStyle: Int) : super(context, attrs, defStyle) {}


    private val dataObserver = object : AdapterDataObserver() {
        override fun onChanged() {
            onChangeState()
        }

        override fun onItemRangeRemoved(positionStart: Int, itemCount: Int) {
            super.onItemRangeRemoved(positionStart, itemCount)
            onChangeState()
        }

        override fun onItemRangeInserted(positionStart: Int, itemCount: Int) {
            super.onItemRangeInserted(positionStart, itemCount)
            onChangeState()
        }
    }


    override fun setAdapter(adapter: RecyclerView.Adapter<*>?) {
        super.setAdapter(adapter)
        adapter?.registerAdapterDataObserver(dataObserver)
        dataObserver.onChanged()
    }


    fun onChangeState() {
        if (adapter?.itemCount == 0) {
            emptyStateView?.visibility = View.VISIBLE
            loadingStateView?.visibility = View.GONE
            this@RecyclerViewEmptyLoadingSupport.visibility = View.GONE
        } else {
            emptyStateView?.visibility = View.GONE
            loadingStateView?.visibility = View.GONE
            this@RecyclerViewEmptyLoadingSupport.visibility = View.VISIBLE
        }
    }

    private fun setState() {

        when (this.stateView) {
            RecyclerViewEnum.LOADING -> {
                loadingStateView?.visibility = View.VISIBLE
                this@RecyclerViewEmptyLoadingSupport.visibility = View.GONE
                emptyStateView?.visibility = View.GONE
            }

            RecyclerViewEnum.NORMAL -> {
                loadingStateView?.visibility = View.GONE
                this@RecyclerViewEmptyLoadingSupport.visibility = View.VISIBLE
                emptyStateView?.visibility = View.GONE
            }
            RecyclerViewEnum.EMPTY_STATE -> {
                loadingStateView?.visibility = View.GONE
                this@RecyclerViewEmptyLoadingSupport.visibility = View.GONE
                emptyStateView?.visibility = View.VISIBLE
            }
        }
    }
}

layout.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:orientation="vertical">

    <LinearLayout
        android:id="@+id/emptyView"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:background="@color/white"
        android:gravity="center"
        android:orientation="vertical">

        <TextView
            android:id="@+id/emptyLabelTv"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="empty" />
    </LinearLayout>

    <LinearLayout
        android:id="@+id/loadingView"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:background="@color/white"
        android:gravity="center"
        android:orientation="vertical">

        <ProgressBar
            android:id="@+id/progressBar"
            android:layout_width="45dp"
            android:layout_height="45dp"
            android:layout_gravity="center"
            android:indeterminate="true"
            android:theme="@style/progressBarBlue" />
    </LinearLayout>

    <com.peeyade.components.recyclerView.RecyclerViewEmptyLoadingSupport
        android:id="@+id/recyclerView"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />
</LinearLayout>

in attività utilizzare in questo modo:

recyclerView?.apply {
        layoutManager = GridLayoutManager(context, 2)
        emptyStateView = emptyView
        loadingStateView = loadingView
        adapter = adapterGrid
    }

    // you can set LoadingView or emptyView manual
    recyclerView.stateView = RecyclerViewEnum.EMPTY_STATE
    recyclerView.stateView = RecyclerViewEnum.LOADING

1
Se si utilizza questa soluzione, prestare attenzione al fatto che l'utilizzo di enum non è sufficiente a causa della maggiore dimensione di allocazione della memoria. Usa Integer o String a seconda del contesto con appropriate StringDefo IntDefannotazioni
Andrii Artamonov

2

Ho aggiunto RecyclerViewe un'alternativa ImageViewa RelativeLayout:

<RelativeLayout
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <ImageView
        android:id="@+id/no_active_jobs"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:src="@mipmap/ic_active_jobs" />

    <android.support.v7.widget.RecyclerView xmlns:android="http://schemas.android.com/apk/res/android"
        android:id="@+id/recyclerView"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />

</RelativeLayout>

e poi in Adapter:

@Override
public int getItemCount() {
    if (mOrders.size() == 0) {
        mRecyclerView.setVisibility(View.INVISIBLE);
    } else {
        mRecyclerView.setVisibility(View.VISIBLE);
    }
    return mOrders.size();
}

7
come raggiungere mRecyclerViewall'internoAdapter
Basheer AL-MOMANI

2
Non è un buon modello di progettazione per collegare l'adattatore ad attività specifica. È meglio farlo tramite interfacce
ruX

1
Anche questo sta causando un sovraccarico del layout, che non è raccomandato e potrebbe causare alcuni problemi di prestazioni. Vedi youtube.com/watch?v=T52v50r-JfE per maggiori dettagli
Felipe Conde

1

Un altro modo è quello di utilizzare addOnChildAttachStateChangeListener maniglie che appaiono / scompaiono nelle viste figlio RecyclerView.

recyclerView.addOnChildAttachStateChangeListener(new RecyclerView.OnChildAttachStateChangeListener() {
            @Override
            public void onChildViewAttachedToWindow(@NonNull View view) {
                forEmptyTextView.setVisibility(View.INVISIBLE);
            }

            @Override
            public void onChildViewDetachedFromWindow(@NonNull View view) {
                forEmptyTextView.setVisibility(View.VISIBLE);
            }
        });

0

Nel caso in cui tu stia lavorando con FirebaseRecyclerAdapter questo post funziona come un incantesimo https://stackoverflow.com/a/39058636/6507009


7
Sebbene questo collegamento possa rispondere alla domanda, è meglio includere qui le parti essenziali della risposta e fornire il collegamento come riferimento. Le risposte di solo collegamento possono diventare non valide se la pagina collegata cambia.
Anh Pham,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.