RecyclerView के साथ एक खाली दृश्य कैसे दिखाएं?


271

मुझे लेआउट फ़ाइल के अंदर एक विशेष दृश्य डालने के लिए उपयोग किया जाता है जैसा कि ListActivityकोई डेटा नहीं होने पर प्रलेखन में वर्णित किया जाता है । इस दृश्य में आईडी है "android:id/empty"

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

मुझे आश्चर्य है कि यह नए के साथ कैसे किया जा सकता है RecyclerView?


2
आप github.com/rockerhieu/rv-adapter-states का उपयोग कर सकते हैं , यह न केवल खाली दृश्य का समर्थन करता है, बल्कि लोडिंग दृश्य और त्रुटि दृश्य का भी समर्थन करता है। और आप मौजूदा एडॉप्टर के तर्क को बदलने के बिना इसका उपयोग कर सकते हैं।
हियर रॉकर

20
यह कुछ भी नहीं है कि आकर्षक है, लेकिन एक के setEmptyView()खिलाफ एक सरल तरीका नहीं लगता RecyclerView...
Subby

यहाँ मेरा जवाब है, कृपया इस लिंक को देखें stackoverflow.com/a/58411351/5449220
राकेश वर्मा

@Subby, सहमत हैं, लेकिन setEmptyView()नुकसान भी था। डेटा लोड करते समय, हम खाली दृश्य दिखाना नहीं चाहते थे ListView, लेकिन यह किया। इसलिए, हमें कुछ तर्क लागू करने थे। वर्तमान में मैं stackoverflow.com/a/48049142/2914140 का उपयोग करता हूं ।
CoolMind

जवाबों:


305

उसी लेआउट पर, जहां परिभाषित किया RecyclerViewगया है 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" />

पर onCreateया उचित कॉलबैक आप जाँच लें कि डाटासेट कि फ़ीड आपके RecyclerViewखाली है। यदि डेटासेट खाली है, तो RecyclerViewखाली भी है। उस स्थिति में, संदेश स्क्रीन पर दिखाई देता है। यदि नहीं, तो इसकी दृश्यता बदलें:

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
यह मेरे लिए काम नहीं करता है क्योंकि पुनर्नवीनीकरण दृश्य लेआउट टुकड़े में फुलाया जाता है जबकि निर्णय यह है कि क्या सामान्य आइटम लेआउट दिखाना है या एडॉप्टर में कोई आइटम नहीं लेआउट बनाया गया है।
JJD

1
@JJD जब एक फ्रैगमेंट का उपयोग करता है, तो यही बात लागू होती है। जब आप अपने खंडन दृश्य को फुलाते हैं तो आपके पास रिसाइकलव्यू और फिर एक और लेआउट होता है जो आपके खाली दृश्य के लिए उपयोग किया जाएगा। आमतौर पर मेरे अंशों में मुझे वहाँ के विचार देखने को मिलेंगे: 1) रिसाइकलव्यू, 2) खाली दृश्य, और 3) प्रगतिबार दृश्य। मैं आमतौर पर जो भी सूची होती है, उसे एडॉप्टर पास करता हूं, लेकिन सूची के आकार के आधार पर या तो मैं पुनर्नवीनीकरण को छिपाऊंगा और खाली या इसके विपरीत दिखाऊंगा। यदि एक रिसाइकलव्यू की एक खाली सूची है, तो यह इसके साथ कुछ भी नहीं करता है। तुम सिर्फ एक खाली दृश्य देखते हो।
रे हंटर

1
@stackex सत्यापन फ्रैगमेंट के onCreateView कॉलबैक या गतिविधि के onResume पर होना चाहिए। इस तरह, उपयोगकर्ता को स्क्रीन प्रदर्शित होने से ठीक पहले सत्यापन किया जाएगा और डेटासेट में पंक्तियों की मात्रा को बढ़ाने या घटाने दोनों के लिए काम करेगा।
स्लीलिस

2
@Zapnologica आप इसे दूसरी तरह से कर सकते हैं: एक Eventbus का उपयोग करें (जैसे कि ग्रीनबोट्स Eventbus या ओटो), फिर डेटाबाइब बदलने पर Eventbus पर एडॉप्टर पोस्ट करें। आपके द्वारा किए जाने वाले टुकड़े में, एक विधि बनाई जाती है, जिसके पैरामीटर उस स्थिति के अनुरूप होते हैं, जो Adapter Eventbus.post विधि से गुजर रहा होता है और फिर उसी के अनुसार लेआउट को बदलता है। एडेप्टर में कॉलबैक इंटरफ़ेस बनाने के लिए एक और अधिक सरल लेकिन अधिक युग्मित दृष्टिकोण है, और एडेप्टर बनाने पर इसके टुकड़े को लागू करना है।
AgentKnopf

2
लेआउट में मुझे कई रूट टैग मिलते हैं। आपकी पूरी लेआउट फ़ाइल कैसी दिखती है?
पाउडर 366

192

अपनी परियोजनाओं के लिए मैंने इसका समाधान किया ( विधि के RecyclerViewसाथ setEmptyView):

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

और आपको RecyclerViewकक्षा के बजाय इसका उपयोग करना चाहिए :

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

तथा

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

2
क्या आपने इस उत्तर से या यहाँ से यह कोड लिया है ?
सूफियान

@ सूफियान नहीं, मैंने वह जवाब नहीं देखा, बस उसी तरह पाया। लेकिन यह कोड निश्चित रूप से मेरा से अधिक सुंदर लगता है :)
maff91

2
मैंने इसे FirebaseRecyclerAdapter के साथ संयोजित करने की कोशिश की, यह काम नहीं किया। ऐसा इसलिए है क्योंकि FirebaseRecyclerAdapter onChange (AdapterDataObserver) को कॉल नहीं करता है, इसके बजाय यह onItem * -methods कहता है। इसे जोड़ने का कार्य करने के लिए: `ओवरराइड सार्वजनिक शून्य onItemRangeRemoved (int positionStart, int itemCount) {// check} ओवरराइड सार्वजनिक शून्य onItemRangeMoved (int से प्रस्ताव, int से प्रस्ताव, int आइटम से) {// check} // आदि।
फ्रेंकीएनएल

1
यदि आप पर्यवेक्षक में अशक्त हैं, तो आप इसकी जांच क्यों करते हैं? यदि एडाप्टर अशक्त है, तो पर्यवेक्षक को कभी नहीं बुलाया जाना चाहिए।
स्टिम्सोनी

16
उह, मुझे कहना होगा कि यह सिर्फ क्लासिक Google बीएस है। मुझे खाली दृश्य जोड़ने के लिए इसे लागू करना होगा? यह उनके cr @ psh1t SDK में शामिल होना चाहिए! भगवान के लिए!
नियॉन वेज

62

यहां खाली स्थिति के लिए एक अलग दृश्य प्रकार के साथ केवल एक कस्टम एडाप्टर का उपयोग करके एक समाधान है।

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 यह त्रुटि क्यों है? यह वह तरीका है जिसे आप recyclerview
MSpeed

@billynomates, क्योंकि getItemCount()एक oneliner होना चाहिए लेकिन यहां हमारे पास ifकुछ छिपे हुए तर्क के साथ एक गैर-तुच्छ है। यह तर्क भी अजीब रूप से प्रकट होता है getItemViewTypeऔर भगवान जानता है कि और कहाँ है
एलेक्सी एंड्रोनोव

3
यह एक पंक्ति होने की जरूरत नहीं है। यदि आपको कई प्रकार के दृश्य मिले हैं, तो यह ऐसा करने का तरीका है।
MSpeed

@ sfk92fksdf छिपे हुए तर्क से आपका क्या तात्पर्य है? कोड वहीं है
u

1
मेरी राय में यह उत्तर स्वीकृत उत्तर होना चाहिए। यह वास्तव में उत्परिवर्ती दृश्य प्रकारों को संभालने का तरीका है
इवो ​​बेकर्स

45

मैं 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>

कोड में आप कर्सर / डेटासेट और स्विच दृश्य की जांच करेंगे।

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

यदि आप कोड की कुछ पंक्तियों के साथ चाहें तो एनिमेशन भी सेट कर सकते हैं

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

यह वास्तव में उपन्यास है
झांग जियांग


30

चूंकि केविन का जवाब पूरा नहीं है।
यह और अधिक सही जवाब है, तो आप का उपयोग है RecyclerAdapter'एस notifyItemInsertedऔरnotifyItemRemoved अद्यतन डाटासेट करने के लिए। कोटलिन संस्करण देखें एक और उपयोगकर्ता नीचे जोड़ा गया है।

जावा:

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
यह एक बेहतरीन उपाय है। मैं इसे संपादित करने का प्रस्ताव दे रहा हूं जिसमें कोटलिन संस्करण शामिल होगा।
जंगलेदेव

यह अच्छा लगता है, लेकिन यदि आप एक से अधिक बार swapAdapter () या यहां तक ​​कि setAdapter () कहते हैं तो काम नहीं कर सकता।
ग्लूकोस

मुझे लगता है कि सबसे सुंदर समाधान है!
Android उत्साही

अच्छा कार्य। लेबल दिखाते समय RecyclerView को छुपाना न भूलें
MrG

18

RVEmptyObserver

इसके बजाय एक कस्टम का उपयोग कर RecyclerView , एक AdapterDataObserverका विस्तार करना एक सरल उपाय है जो उस कस्टम को सेट करने की अनुमति देता Viewहै जो सूची में कोई आइटम नहीं होने पर प्रदर्शित होता है:

उदाहरण उपयोग:

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

वर्ग:

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

मुझे विश्वास है कि यह तेजी से अगर आप कॉल नहीं करते चलेंगे checkIfEmpty()में onChanged()औरonItemRangeInserted()
Geekarist

मैं सहमत हूं (और यही मैंने व्यक्तिगत रूप से किया था) लेकिन यह सिर्फ इस मुद्दे का सामना कर रहे लोगों के लिए एक शुरुआती बिंदु था।
शेहर

9

अपने एडॉप्टर पर getItemViewType जाँच करें कि क्या अडैप्टर में ० तत्व हैं और यदि ऐसा है तो एक अलग दृश्य टाइप करें।

फिर आपके onCreateViewHolderचेक पर अगर व्यू टाइप वह है जिसे आपने पहले लौटाया था और एक अलग दृश्य को फुलाया था। इस मामले में उस TextView के साथ एक लेआउट फ़ाइल

संपादित करें

यदि यह अभी भी काम नहीं कर रहा है, तो आप इस तरह से दृश्य का आकार निर्धारित करना चाहते हैं:

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

और फिर जब आप अपना दृश्य कॉल बढ़ाते हैं:

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

बढ़िया है। हालांकि मैं में नहीं मिलता है onCreateViewHolderजब मेरे डाटासेट है nullया खाली बाद से मैं वापस जाने के लिए है 0में getItemCount
JJD

फिर 1 लौटें यदि यह शून्य है :)
पेड्रो ओलिवेरा

कुछ हद तक काम करता है। धन्यवाद। - मामूली विस्तार यह है कि मैं खाली सूची आइटम को पुनर्नवीनीकरण दृश्य में लंबवत केंद्रित नहीं कर सकता । पाठ दृश्य स्क्रीन के शीर्ष पर रहता है फिर भी मैं सेट करता हूं android:layout_gravity="center"और android:layout_height="match_parent"पैरेंट रिसाइक्लर दृश्य के लिए।
12

यह उस पंक्ति के लेआउट पर निर्भर करता है जिसका आप उपयोग कर रहे हैं। यह ऊंचाई पर match_parent होना चाहिए। यदि आप अभी भी इसे काम नहीं कर सकते हैं, तो एक वैश्विक लेआउट श्रोता जोड़ें और यह निर्धारित करें कि स्क्रीन के समान ऊँचाई और चौड़ाई का लेआउट पैरामीटर है।
पेड्रो ओलिवेरा

सभी कंटेनर (गतिविधि, टुकड़ा, रैखिक लेआउट, पुनर्नवीनीकरण दृश्य, पाठ दृश्य) के लिए सेट हैं android:layout_height="match_parent"। हालांकि पंक्ति स्क्रीन की ऊँचाई तक विस्तारित नहीं होती है।
JJD

8

यहाँ खाली दृश्य दिखाने के लिए मेरी कक्षा है, पुनः प्रयास देखें (जब लोड एपीआई विफल रहा है) और लोडिंग प्रगति के लिए 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>

यहां छवि विवरण दर्ज करें

स्रोत यहाँ है https://github.com/PhanVanLinh/AndroidRecyclerViewWithLoadingEmptyAndRetry


7

कस्टम RecyclerView में AdapterDataObserver का उपयोग करें

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>

गतिविधि में इस तरह से उपयोग करें:

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
यदि आप उस समाधान के साथ जाते हैं, तो ध्यान दें कि एनम का उपयोग इसके बढ़ते स्मृति आवंटन आकार के कारण अपर्याप्त है। उपयुक्त StringDefया IntDefएनोटेशन के साथ अपने संदर्भ के आधार पर इंटेगर या स्ट्रिंग का उपयोग करें
एंड्री आर्टामोनोव

2

मैं जोड़ा RecyclerViewऔर वैकल्पिक ImageViewकरने के लिए 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>

और फिर इसमें Adapter:

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

7
कैसे mRecyclerViewअंदर पहुँचेंAdapter
बशीर अल-मोमानी

2
एडेप्टर को विशिष्ट गतिविधि से बांधने के लिए यह अच्छा डिज़ाइन पैटर्न नहीं है। यह बेहतर है कि इंटरफेस के माध्यम से
बर्बाद करें

1
इसके अलावा यह एक लेआउट अतिवृद्धि का कारण बन रहा है, जिसे अनुशंसित नहीं किया गया है और यह कुछ प्रदर्शन मुद्दों का कारण बन सकता है। अधिक जानकारी के लिए youtube.com/watch?v=T52v50r-JfE देखें
फेलिप कॉनडे

1

एक और तरीका यह है कि addOnChildAttachStateChangeListenerबच्चे के विचारों को दिखने / गायब करने वाले हैंडल का उपयोग करें 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

बस incase आप एक FirebaseRecyclerAdapter के साथ काम कर रहे हैं यह पोस्ट एक आकर्षण https://stackoverflow.com/a/39058636/6507009 के रूप में काम करता है


7
हालांकि यह लिंक प्रश्न का उत्तर दे सकता है, लेकिन उत्तर के आवश्यक भागों को शामिल करना और संदर्भ के लिए लिंक प्रदान करना बेहतर है। लिंक-केवल उत्तर अमान्य हो सकते हैं यदि लिंक किए गए पृष्ठ बदल जाते हैं।
फाम
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.