Làm cách nào để hiển thị chế độ xem trống với RecyclerView?


271

Tôi được sử dụng để đặt một chế độ xem đặc biệt bên trong tệp bố cục như được mô tả trong ListActivitytài liệu sẽ được hiển thị khi không có dữ liệu . Quan điểm này có 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" />

Tôi tự hỏi làm thế nào điều này có thể được thực hiện với cái mới RecyclerView?


2
Bạn có thể sử dụng github.com/rockerhieu/rv-ad CHƯƠNG-state , nó không chỉ hỗ trợ chế độ xem trống mà còn tải chế độ xem và chế độ xem lỗi. Và bạn có thể sử dụng nó mà không thay đổi logic của bộ điều hợp hiện có.
Hiếu Rocker

20
Không có gì ngoài sự thú vị khi dường như không có một setEmptyView()phương pháp đơn giản nào chống lại RecyclerView...
Subby 11/05/2016

Đây là câu trả lời của tôi, vui lòng kiểm tra liên kết này stackoverflow.com/a/58411351/5449220
Rakesh Verma

@Subby, đồng ý, nhưng setEmptyView()cũng có nhược điểm. Khi tải dữ liệu, chúng tôi không muốn hiển thị chế độ xem trống ListView, nhưng nó đã làm. Vì vậy, chúng tôi đã phải thực hiện một số logic. Hiện tại tôi đang sử dụng stackoverflow.com/a/48049142/2914140 .
CoolMind

Câu trả lời:


305

Trên cùng một bố cục nơi được xác định RecyclerView, thêm 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" />

Tại onCreatehoặc cuộc gọi lại thích hợp, bạn kiểm tra xem tập dữ liệu cung cấp cho bạn RecyclerViewcó trống không. Nếu tập dữ liệu trống, thì RecyclerViewcũng trống. Trong trường hợp đó, thông báo xuất hiện trên màn hình. Nếu không, thay đổi tầm nhìn của nó:

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
Điều đó không phù hợp với tôi vì bố cục khung nhìn của trình tái chế bị thổi phồng trong đoạn trong khi quyết định hiển thị bố cục mục bình thường hay bố cục không có mục được thực hiện trong bộ điều hợp.
JJD 6/2/2015

1
@JJD khi sử dụng Fragment, điều tương tự cũng được áp dụng. Khi bạn tăng cường chế độ xem phân đoạn của mình, bạn có recyclerview và sau đó một bố cục khác sẽ được sử dụng cho chế độ xem trống của bạn. Thông thường trong các phân đoạn của tôi, tôi sẽ có các lượt xem sau: 1) recyclerview, 2) chế độ xem trống và 3) chế độ xem thanh tiến trình. Tôi thường vượt qua bộ chuyển đổi bất kể danh sách là gì, nhưng dựa trên kích thước của danh sách, tôi sẽ ẩn recyclerview và hiển thị trống hoặc ngược lại. Nếu một recyclerview có một danh sách trống, thì nó không làm gì với nó. Bạn chỉ thấy một cái nhìn trống rỗng.
Ray Hunter

1
@stackex Việc xác minh phải nằm trong cuộc gọi lại onCreateView của Fragment hoặc onResume of Activity. Bằng cách này, việc xác minh sẽ được thực hiện ngay trước khi màn hình được hiển thị cho người dùng và sẽ hoạt động cho cả hai, tăng hoặc giảm số lượng hàng trong tập dữ liệu.
slellis

2
@Zapnologica Bạn có thể thực hiện theo cách khác: Sử dụng một Eventbus (chẳng hạn như greenrobots Eventbus hoặc Otto), sau đó có bài Adaptor trên eventbus khi tập dữ liệu thay đổi. Trong đoạn, tất cả những gì bạn làm là tạo một phương thức có tham số tương ứng với những gì Bộ điều hợp đang truyền vào phương thức Eventbus.post và sau đó thay đổi bố cục cho phù hợp. Một cách tiếp cận đơn giản hơn nhưng cũng được kết hợp nhiều hơn là tạo giao diện gọi lại trong bộ điều hợp và khi tạo bộ điều hợp có đoạn thực hiện nó.
Đặc vụKnopf

2
Trong cách bố trí tôi nhận được nhiều thẻ gốc. Tập tin bố trí đầy đủ của bạn trông như thế nào?
bột366

192

Đối với các dự án của tôi, tôi đã thực hiện giải pháp này ( RecyclerViewvới setEmptyViewphương pháp):

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

Và bạn nên sử dụng nó thay vì RecyclerViewlớp học:

<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
Bạn đã lấy mã này từ câu trả lời này hoặc từ đây ?
Sufian

@Sufian Không, tôi không thấy câu trả lời đó, chỉ tìm thấy cùng một cách. Nhưng mã đó chắc chắn trông đẹp hơn của tôi :)
maff91

2
Tôi đã thử kết hợp điều này với FirebaseRecyclerAd CHƯƠNG, nó không hoạt động. Điều này là do FirebaseRecyclerAd CHƯƠNG không gọi onChange (của AdaptorDataObserver), thay vào đó, nó gọi là onItem * -methods. Để làm cho nó hoạt động, hãy thêm: `Ghi đè khoảng trống công khai
FrankkieNL

1
Tại sao bạn kiểm tra xem bộ điều hợp có null trong bộ quan sát không? nếu bộ điều hợp là null thì người quan sát không bao giờ được gọi.
Stimsoni

16
ugh, tôi phải nói rằng đây chỉ là Google BS cổ điển. Tôi phải thực hiện điều này chỉ để thêm một chế độ xem trống? Nó nên được bao gồm trong SDK cr @ psh1t của họ! Vì chúa trời!
Chiến tranh neon

62

Đây là một giải pháp chỉ sử dụng bộ điều hợp tùy chỉnh với kiểu xem khác cho tình huống trống.

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 Tại sao nó dễ bị lỗi? Đây là cách bạn phải xử lý nhiều loại chế độ xem trong recyclerview
MSpeed

@billynomates, vì getItemCount()nên là một oneliner nhưng ở đây chúng ta có một thứ không tầm thường ifvới một số logic ẩn. Logic này cũng xuất hiện một cách vụng về getItemViewTypevà chúa biết còn ở đâu nữa
Alexey Andronov

3
Nó không cần phải là một dòng. Nếu bạn có nhiều kiểu xem, đây là cách để làm điều đó.
MSpeed

@ sfk92fksdf Ý của bạn là gì khi ẩn logic? Mã ở ngay trên đó ▲
radu122

1
theo tôi câu trả lời này nên là câu trả lời được chấp nhận Đó thực sự là cách để xử lý các kiểu xem đa dạng
Ivo Beckers

45

Tôi sử dụng 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>

trong mã bạn sẽ kiểm tra con trỏ / tập dữ liệu và chuyển đổi chế độ xem.

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

Ngoài ra, bạn có thể đặt hình động nếu bạn muốn với một vài dòng mã

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

Nó thực sự là tiểu thuyết
Zhang Xiang

Dung dịch sạch.
Ojonugwa Jude Ochalifu

30

Vì câu trả lời của Kevin chưa đầy đủ.
Đây là câu trả lời chính xác hơn nếu bạn sử dụng RecyclerAdapter's notifyItemInsertednotifyItemRemovedđể cập nhật dữ liệu. Xem phiên bản Kotlin một người dùng khác được thêm vào bên dưới.

Java:

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
Đây là một giải pháp tuyệt vời. Tôi đang đề xuất một chỉnh sửa cho nó sẽ bao gồm phiên bản kotlin.
jungledev

Điều này có vẻ tốt nhưng có thể không hoạt động nếu bạn gọi exchangeAd CHƯƠNG () hoặc thậm chí setAd CHƯƠNG () nhiều lần.
Glaucus

Tôi nghĩ là giải pháp thanh lịch nhất!
người đam mê Android

Công việc tuyệt vời đừng quên ẩn RecyclerView khi hiển thị nhãn
MrG

18

Máy chủ RVEmptyObs

Thay vì sử dụng một tùy chỉnh RecyclerView, mở rộng một AdapterDataObserverlà một giải pháp đơn giản hơn cho phép thiết lập một tùy chỉnh Viewđược hiển thị khi không có mục nào trong danh sách:

Cách sử dụng ví dụ:

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

Lớp học:

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

Tôi tin rằng nó sẽ chạy nhanh hơn nếu bạn không gọi checkIfEmpty()trong onChanged()onItemRangeInserted()
Geekarist

Tôi đồng ý (và đó là những gì cá nhân tôi đã làm) nhưng đây chỉ là điểm khởi đầu cho những người phải đối mặt với vấn đề này.
Sheharyar

9

Trên getItemViewTypekiểm tra bộ điều hợp của bạn nếu bộ điều hợp có 0 phần tử và trả về một viewType khác nếu có.

Sau đó, trên onCreateViewHolderkiểm tra của bạn nếu viewType là cái bạn đã trả về trước đó và làm tăng một cái nhìn khác. Trong trường hợp này, một tệp bố cục với TextView đó

BIÊN TẬP

Nếu điều này vẫn không hoạt động thì bạn có thể muốn đặt kích thước của chế độ xem theo chương trình như sau:

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

Và sau đó khi bạn tăng cường xem cuộc gọi của bạn:

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

Âm thanh tốt. Tuy nhiên tôi không nhận được vào onCreateViewHolderkhi dữ liệu của tôi là nullđúng hoặc bỏ trống kể từ khi tôi phải trở về 0trong getItemCount.
JJD 5/2/2015

Sau đó trả về 1 nếu không có giá trị :)
Pedro Oliveira

Hoạt động được phần nào. Cảm ơn bạn. - Chi tiết nhỏ là tôi không thể lấy mục danh sách trống được căn giữa theo chiều dọc trong chế độ xem của trình tái chế. Chế độ xem văn bản vẫn ở trên cùng của màn hình dù sao tôi đã đặt android:layout_gravity="center"android:layout_height="match_parent"cho chế độ xem trình tái chế cha mẹ.
JJD 6/2/2015

Nó phụ thuộc vào cách bố trí hàng bạn đang sử dụng. Nó sẽ khớp với chiều cao của nó. Nếu bạn vẫn không thể làm cho nó hoạt động, hãy thêm một trình nghe bố cục toàn cầu và đặt các tham số bố cục của nó có cùng chiều cao và chiều rộng với màn hình.
Pedro Oliveira

Tất cả các thùng chứa (hoạt động, đoạn, bố cục tuyến tính, chế độ xem tái chế, chế độ xem văn bản) được đặt thành android:layout_height="match_parent". Mặc dù hàng không mở rộng đến chiều cao màn hình.
JJD 6/2/2015

8

Đây là lớp của tôi để hiển thị chế độ xem trống, xem lại thử (khi tải api không thành công) và tiến trình tải cho 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();
    }
}

hoạt động_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>

nhập mô tả hình ảnh ở đây

Nguồn ở đây https://github.com/PhanVanLinh/AndroidRecyclerViewWithLoadingEmptyAndR tem


7

Sử dụng AdapterDataObserver trong RecyclerView tùy chỉnh

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>

trong hoạt động sử dụng cách này:

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
Nếu bạn đi với giải pháp đó, hãy chú ý rằng việc sử dụng enums là không đủ do kích thước phân bổ bộ nhớ tăng lên. Sử dụng Số nguyên hoặc Chuỗi tùy thuộc vào ngữ cảnh của bạn với các chú thích StringDefhoặc IntDefchú thích phù hợp
Andrii Artamonov

2

Tôi đã thêm RecyclerViewvà thay thế ImageViewcho 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>

và sau đó trong Adapter:

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

7
làm thế nào để tiếp cận mRecyclerViewbên trongAdapter
Basheer AL-MOMani

2
Đây không phải là mẫu thiết kế tốt để gắn Adaptor với Hoạt động cụ thể. Tốt hơn là làm điều đó thông qua các giao diện
ruX

1
Ngoài ra, điều này gây ra tình trạng quá tải bố cục, không được khuyến nghị và nó có thể gây ra một số vấn đề về hiệu suất. Xem youtube.com/watch?v=T52v50r-JfE để biết thêm chi tiết
Felipe Conde

1

Một cách nữa là sử dụng các thẻ addOnChildAttachStateChangeListenerđiều khiển xuất hiện / biến mất các khung nhìn con trong 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

Chỉ cần bạn đang làm việc với FirebaseRecyclerAd CHƯƠNG, bài đăng này hoạt động như một cơ duyên https://stackoverflow.com/a/39058636/6507009


7
Mặc dù liên kết này có thể trả lời câu hỏi, tốt hơn là bao gồm các phần thiết yếu của câu trả lời ở đây và cung cấp liên kết để tham khảo. Câu trả lời chỉ liên kết có thể trở nên không hợp lệ nếu trang được liên kết thay đổi.
Anh Phạm
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.