Bagaimana cara menunjukkan tampilan kosong dengan RecyclerView?

271

Saya terbiasa meletakkan tampilan khusus di dalam file layout seperti yang dijelaskan dalam ListActivitydokumentasi yang akan ditampilkan ketika tidak ada data . Tampilan ini memiliki 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" />

Saya bertanya-tanya bagaimana ini bisa dilakukan dengan yang baru RecyclerView?

JJD
sumber
2
Anda dapat menggunakan github.com/rockerhieu/rv-adapter-states , mendukung tidak hanya tampilan kosong tetapi juga memuat tampilan dan tampilan kesalahan. Dan Anda bisa menggunakannya tanpa mengubah logika adaptor yang ada.
Hieu Rocker
20
Tidak ada yang menarik selain tampaknya tidak ada setEmptyView()metode sederhana melawan RecyclerView...
Subby
Inilah jawaban saya, silakan periksa tautan ini stackoverflow.com/a/58411351/5449220
Rakesh Verma
@Subby, setuju, tetapi setEmptyView()juga memiliki kelemahan. Saat memuat data, kami tidak ingin menampilkan tampilan kosong ListView, tetapi ternyata benar. Jadi, kami harus menerapkan beberapa logika. Saat ini saya menggunakan stackoverflow.com/a/48049142/2914140 .
CoolMind

Jawaban:

306

Pada tata letak yang sama di mana didefinisikan RecyclerView, tambahkan 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" />

Di onCreateatau pada panggilan balik yang sesuai Anda memeriksa apakah dataset yang memberi makan Anda RecyclerViewkosong. Jika dataset kosong, maka RecyclerViewkosong juga. Dalam hal itu, pesan muncul di layar. Jika tidak, ubah visibilitasnya:

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);
}
slellis
sumber
11
Itu tidak berhasil bagi saya karena tata letak tampilan pendaur ulang meningkat dalam fragmen sedangkan keputusan apakah akan menampilkan tata letak item normal atau tata letak tidak-item dibuat dalam adaptor.
JJD
1
@JJD saat menggunakan Fragmen, hal yang sama berlaku. Saat Anda mengembang tampilan fragmen Anda, Anda memiliki recyclerview dan kemudian tata letak lain yang akan digunakan untuk tampilan kosong Anda. Biasanya dalam fragmen saya, saya akan memiliki pandangan ikuti di sana: 1) recyclerview, 2) tampilan kosong, dan 3) tampilan progressbar. Saya biasanya melewati adaptor apa pun daftar itu, tetapi berdasarkan pada ukuran daftar saya akan menyembunyikan recyclerview dan menunjukkan yang kosong atau sebaliknya. Jika recyclerview memiliki daftar kosong, maka itu tidak melakukan apa-apa dengannya. Anda hanya melihat tampilan kosong.
Ray Hunter
1
@stackex Verifikasi harus dalam callback onCreateView dari Fragment atau onResume of Activity. Dengan cara ini, verifikasi akan dilakukan segera sebelum layar ditampilkan kepada pengguna dan akan bekerja untuk keduanya, menambah atau mengurangi jumlah baris dalam dataset.
slellis
2
@Zapnologica Anda dapat melakukannya dengan cara sebaliknya: Gunakan Eventbus (seperti greenrobots Eventbus atau Otto), lalu pasang posting Adaptor pada eventbus saat dataset berubah. Dalam fragmen yang Anda lakukan adalah membuat metode yang parameternya sesuai dengan apa yang diteruskan Adaptor ke dalam metode Eventbus.post dan kemudian ubah tata letaknya. Pendekatan yang lebih sederhana tetapi juga lebih digabungkan adalah untuk membuat antarmuka panggilan balik di adaptor, dan setelah membuat adaptor memiliki fragmen mengimplementasikannya.
AgentKnopf
2
Dalam tata letak saya mendapatkan beberapa tag root. Seperti apa file layout lengkap Anda?
bubuk366
192

Untuk proyek saya, saya membuat solusi ini ( RecyclerViewdengan setEmptyViewmetode):

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

Dan Anda harus menggunakannya sebagai ganti RecyclerViewkelas:

<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"
    />

dan

RecyclerViewEmptySupport list = 
    (RecyclerViewEmptySupport)rootView.findViewById(R.id.list1);
list.setLayoutManager(new LinearLayoutManager(context));
list.setEmptyView(rootView.findViewById(R.id.list_empty));
maff91
sumber
2
Apakah Anda mengambil kode ini dari jawaban ini atau dari sini ?
Sufian
@ Sufian Tidak, saya tidak melihat jawaban itu, hanya menemukan cara yang sama. Tapi kode itu jelas terlihat lebih cantik dari milikku :)
maff91
2
Saya mencoba untuk menggabungkan ini dengan FirebaseRecyclerAdapter, itu tidak berhasil. Ini karena FirebaseRecyclerAdapter tidak memanggil onChange (dari AdapterDataObserver), melainkan memanggil metode onItem * -methods. Untuk membuatnya berfungsi, tambahkan: `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
Mengapa Anda memeriksa apakah adaptor nol di pengamat? jika adaptornya nol, pengamat tidak boleh dipanggil.
Stimsoni
16
huh, saya harus mengatakan ini hanya Google BS klasik. Saya harus menerapkan ini hanya untuk menambahkan tampilan kosong? Itu harus dimasukkan dalam SDK cr @ psh1t mereka! Demi Tuhan!
Neon Warge
62

Berikut adalah solusi yang hanya menggunakan adaptor khusus dengan jenis tampilan berbeda untuk situasi kosong.

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

}
radu122
sumber
3
@ sfk92fksdf Mengapa ini rawan kesalahan? Ini adalah cara Anda seharusnya menangani beberapa jenis tampilan dalam recyclerview
MSpeed
@ billynomates, karena getItemCount()harus oneliner tetapi di sini kita memiliki non-sepele ifdengan beberapa logika tersembunyi. Logika ini juga muncul dengan canggung getItemViewTypedan Tuhan tahu di mana lagi
Alexey Andronov
3
Tidak perlu satu baris. Jika Anda memiliki beberapa jenis tampilan, ini adalah cara untuk melakukannya.
MSpeed
@ sfk92fksdf Apa yang Anda maksud dengan logika tersembunyi?
Kodenya
1
menurut pendapat saya jawaban ini harus menjadi jawaban yang diterima. Ini benar-benar cara untuk menangani tipe tampilan mutliple
Ivo Beckers
45

Saya menggunakan 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>

dalam kode Anda akan memeriksa kursor / dataset dan beralih tampilan.

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

Anda juga dapat mengatur animasi jika Anda ingin dengan beberapa baris kode

mListSwitcher.setInAnimation(slide_in_left);
mListSwitcher.setOutAnimation(slide_out_right);
wnc_21
sumber
Ini benar-benar novel
Zhang Xiang
Solusi bersih.
Ojonugwa Jude Ochalifu
30

Karena jawaban Kevin tidak lengkap.
Ini adalah jawaban yang lebih benar jika Anda menggunakan RecyclerAdapter's notifyItemInserteddan notifyItemRemovedupdate dataset. Lihat versi Kotlin yang ditambahkan pengguna lain di bawah.

Jawa:

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)
    }
})
wonsuc
sumber
2
Ini solusi hebat. Saya mengusulkan edit yang akan menyertakan versi kotlin.
jungledev
Ini tampaknya baik tetapi mungkin tidak berfungsi jika Anda memanggil swapAdapter () atau bahkan setAdapter () lebih dari sekali.
Glaucus
Saya pikir ini solusi paling elegan!
Penggemar android
Kerja bagus. jangan lupa untuk menyembunyikan RecyclerView saat menunjukkan label
MrG
18

RVEmptyObserver

Alih-alih menggunakan kustom RecyclerView, memperluas AdapterDataObserveradalah solusi sederhana yang memungkinkan pengaturan kustom Viewyang ditampilkan ketika tidak ada item dalam daftar:

Contoh penggunaan:

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

Kelas:

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
sumber
Saya percaya bahwa itu akan berjalan lebih cepat jika Anda tidak menelepon checkIfEmpty()di onChanged()danonItemRangeInserted()
Geekarist
Saya setuju (dan itulah yang saya lakukan secara pribadi) tetapi ini hanya dimaksudkan sebagai titik awal bagi orang yang menghadapi masalah ini.
Sheharyar
9

Pada adaptor Anda getItemViewTypeperiksa apakah adaptor memiliki 0 elemen dan mengembalikan tipe tampilan yang berbeda jika demikian.

Kemudian pada onCreateViewHolderpemeriksaan Anda apakah viewType yang Anda kembali sebelumnya dan mengembang tampilan yang berbeda. Dalam hal ini file tata letak dengan TextView itu

EDIT

Jika ini masih tidak berfungsi maka Anda mungkin ingin mengatur ukuran tampilan secara terprogram seperti ini:

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

Dan kemudian ketika Anda mengembang panggilan panggilan Anda:

inflatedView.getLayoutParams().height = size.y;
inflatedView.getLayoutParams().width = size.x;
Pedro Oliveira
sumber
Kedengarannya bagus. Namun saya tidak masuk ke dalam onCreateViewHolderketika dataset saya nullatau mengosongkan karena saya harus kembali 0di getItemCount.
JJD
Lalu kembalikan 1 jika itu nol :)
Pedro Oliveira
Bekerja agak. Terima kasih. - Detail kecil adalah bahwa saya tidak bisa mendapatkan item daftar kosong dipusatkan secara vertikal dalam tampilan pendaur ulang. Tampilan teks tetap di bagian atas layar namun saya atur android:layout_gravity="center"dan android:layout_height="match_parent"untuk tampilan pendaur ulang induk.
JJD
Itu tergantung pada tata letak baris yang Anda gunakan. Seharusnya match_parent pada ketinggian itu. Jika Anda masih tidak dapat membuatnya berfungsi, tambahkan pendengar tata letak global dan tetapkan parameter tata letak agar memiliki tinggi dan lebar yang sama dengan layar.
Pedro Oliveira
Semua wadah (aktivitas, fragmen, tata letak linier, tampilan pendaur ulang, tampilan teks) diatur ke android:layout_height="match_parent". Padahal deretan layar tidak memanjang setinggi.
JJD
8

Ini adalah kelas saya untuk tampilan kosong, coba lagi tampilan (ketika memuat api gagal) dan memuat kemajuan untuk 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>

masukkan deskripsi gambar di sini

Sumbernya ada di sini https://github.com/PhanVanLinh/AndroidRecyclerViewWithLoadingEmptyAndRetry

Phan Van Linh
sumber
7

Gunakan AdapterDataObserver di RecyclerView kustom

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>

dalam aktivitas gunakan cara ini:

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
Rasoul Miri
sumber
1
Jika Anda menggunakan solusi tersebut perhatikan bahwa menggunakan enum tidak cukup karena ukuran alokasi memorinya meningkat. Gunakan Integer atau String tergantung pada konteks Anda dengan yang sesuai StringDefatau IntDefanotasi
Andrii Artamonov
2

Saya menambahkan RecyclerViewdan alternatif ImageViewuntuk 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>

dan kemudian di Adapter:

@Override
public int getItemCount() {
    if (mOrders.size() == 0) {
        mRecyclerView.setVisibility(View.INVISIBLE);
    } else {
        mRecyclerView.setVisibility(View.VISIBLE);
    }
    return mOrders.size();
}
YTerle
sumber
7
bagaimana mencapai mRecyclerViewdi dalamAdapter
Basheer AL-MOMANI
2
Itu bukan pola desain yang baik untuk mengikat Adaptor dengan Kegiatan spesifik. Lebih baik melakukannya melalui antarmuka
ruX
1
Ini juga menyebabkan tata letak overdraw, yang tidak direkomendasikan dan dapat menyebabkan beberapa masalah kinerja. Lihat youtube.com/watch?v=T52v50r-JfE untuk rincian lebih lanjut
Felipe Conde
1

Satu cara lagi adalah menggunakan addOnChildAttachStateChangeListeneryang menangani tampilan anak yang muncul / menghilang 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);
            }
        });
hidd
sumber
0

Jika Anda bekerja dengan FirebaseRecyclerAdapter posting ini berfungsi sebagai pesona https://stackoverflow.com/a/39058636/6507009

knightcube
sumber
7
Meskipun tautan ini dapat menjawab pertanyaan, lebih baik untuk memasukkan bagian-bagian penting dari jawaban di sini dan memberikan tautan untuk referensi. Jawaban hanya tautan dapat menjadi tidak valid jika halaman tertaut berubah.
Anh Pham