Tương đương với ListView.setEmptyView trong RecyclerView


Câu trả lời:


69

Với tính năng liên kết dữ liệu mới, bạn cũng có thể đạt được điều này trực tiếp trong bố cục của mình:

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

Trong trường hợp đó, bạn chỉ cần thêm một biến và một nhập vào phần dữ liệu trong XML của mình:

<data>
<import type="android.view.View"/>
<variable
    name="dataset"
    type="java.util.List&lt;java.lang.String&gt;"
    />
</data>

6
Ví dụ trên được đơn giản hóa để nhấn mạnh cách tiếp cận liên kết dữ liệu. Liên kết dữ liệu rất linh hoạt. Tất nhiên, bạn có thể nhập Adaptertập dữ liệu thay vì tập dữ liệu và sử dụng tập dữ liệu đó getItemCount()hoặc bọc mọi thứ trong một ViewModelvà đặt android:visibilitythành viewModel.getEmptyViewVisibility().
André Diermann

4
Điều này sẽ được bình chọn cao hơn, nó là một ví dụ tuyệt vời về khả năng liên kết dữ liệu
Ed George

1
@javmarina Không, đối với tôi, bố cục không tiếp tục cập nhật. Nếu bộ điều hợp của tôi bắt đầu với kích thước 0 và sau đó tập dữ liệu phát triển, bố cục sẽ không cập nhật như mong muốn. Có vẻ như ràng buộc dữ liệu sẽ không hoạt động đối với tôi. :-(
meisteg

3
Điều này sẽ cập nhật ngay cả khi bộ điều hợp đang phát triển động hoặc thu hẹp về 0? Tôi nghi ngờ điều đó.
david

1
@ a11n Nó không cập nhật bố cục khi danh sách thu hẹp về 0 hoặc nhận dữ liệu, chúng tôi phải đặt giá trị cho ràng buộc từ lớp mỗi khi chúng tôi thực hiện bất kỳ thay đổi nào đối với danh sách, có cách nào để tự cập nhật bố cục không?
Om Infowave Developers

114

Đây là một lớp tương tự như của @dragon sinh ra, nhưng hoàn thiện hơn. Dựa trên ý chính này .

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

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

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

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

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

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

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

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

        checkIfEmpty();
    }

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

bạn có thể vui lòng giải thích làm thế nào tôi có thể sử dụng lớp này?
Ololoking

Cũng chính xác như cách bạn làm với RecyclerView, nó chỉ thêm setEmptyViewphương thức mà bạn có thể gọi bất cứ khi nào bạn muốn xác định khung nhìn trống. Xem ListView.setEmptyViewtài liệu nếu nó không rõ ràng, đó là cùng một ý tưởng.
Marc Plano-Lesay

5
Cách triển khai tương tự từ Google Mẫu: github.com/googlesamples/android-XYZTouristAttaries/blob/…
jase 23/02/16

2
Giải pháp hay nhưng tên lớp lạ quá =)
Шах

1
@AJW Tôi đoán chủ yếu là vấn đề bạn muốn đạt được gì. Sự khác biệt giữa hai cách triển khai thực sự rất nhỏ và sẽ không còn gì ngay sau khi bộ điều hợp được thiết lập. Nếu bạn không thay đổi bộ điều hợp (rất có thể là trường hợp này), không có sự khác biệt.
Marc Plano-Lesay

26

Giải pháp được cung cấp trong liên kết này có vẻ hoàn hảo. Nó sử dụng viewType để xác định thời điểm hiển thị blankView. Không cần tạo RecyclerView tùy chỉnh

Thêm mã từ liên kết trên:

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

public class RecyclerViewActivity extends Activity {

RecyclerView recyclerView;

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


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

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

    public class ViewHolder extends RecyclerView.ViewHolder {
        TextView data;

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

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

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


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

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

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

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

    private static final int EMPTY_VIEW = 10;
}

}

6
Tôi nghĩ rằng mở rộng RecyclerView là giải pháp được chấp thuận hơn giải pháp này bởi vì nói chung tôi có rất nhiều bộ điều hợp tái chế và tôi muốn tránh thêm loại logic này vào mỗi một trong số chúng.
Gunhan,

Điều đó có ý nghĩa @Gunhan, khi sử dụng nhiều bộ điều hợp tái chế. Bạn cũng có thể cố gắng mở rộng một BaseAdapter duy nhất được tùy chỉnh cho tất cả những thứ phổ biến
Sudhasri

2
Ngay cả khi bạn chỉ có một bộ chuyển đổi và một bộ tái chế, đó không phải là khả năng đáp ứng của bộ chuyển đổi. Bộ điều hợp ở đây để hiển thị các mặt hàng, không phải là không có mặt hàng.
Marc Plano-Lesay

@Kernald Tùy thuộc vào trường hợp sử dụng của bạn. Cá nhân tôi nghĩ rằng nó sạch sẽ hơn nhiều so với cách Sudhasri đã làm. Đặc biệt nếu bạn muốn thể hiện một cái nhìn khác trong trường hợp không có mặt hàng nào là quà như: "Không có mặt hàng nào ở đây, hãy đi mua sắm!" hoặc những thứ như thế
AgentKnopf

@Zainodis Như bạn đã nói, đó là một quan điểm khác. Đó không phải là khả năng đáp ứng của bộ điều hợp, đó là hiển thị các vật phẩm trong chế độ tái chế, không có gì khác. Tôi đồng ý rằng nói về mặt kỹ thuật, cả hai giải pháp đều hoạt động và khá bình đẳng. Nhưng các mục của bộ điều hợp không được tạo ra để hiển thị các chế độ xem như thế này.
Marc Plano-Lesay

10

Tôi chỉ muốn một giải pháp đơn giản như,

đặt RecyclerView của bạn bên trong FrameLayout hoặc RelativeLayout với TextView hoặc chế độ xem khác có hiển thị thông báo dữ liệu trống với khả năng hiển thị GONE theo mặc định và sau đó trong lớp bộ điều hợp, hãy áp dụng logic

Ở đây, tôi có một TextView với thông báo không có dữ liệu

@Override
public int getItemCount() {
    textViewNoData.setVisibility(data.size() > 0 ? View.GONE : View.VISIBLE);
    return data.size();
}

3

Hãy thử RVEmptyObserver:

Đó là một triển khai của một AdapterDataObservercho phép bạn chỉ cần đặt một Viewlàm bố cục trống mặc định cho của bạn RecylerView. Bằng cách này, thay vì sử dụng một tùy chỉnh RecyclerViewvà khiến cuộc sống của bạn khó khăn hơn, bạn có thể dễ dàng sử dụng nó với mã hiện có của mình:


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

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

Bạn có thể xem mãví dụ sử dụng trong một ứng dụng thực tế tại đây.


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

2

Phiên bản của tôi, dựa trên https://gist.github.com/adelnizamutdinov/31c8f054d1af4588dc5c

public class EmptyRecyclerView extends RecyclerView {
    @Nullable
    private View emptyView;

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

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

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

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

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

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

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

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

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

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

3
Ý tưởng tốt để thực hiện lại setVisibilityquá.
Marc Plano-Lesay

2

Tôi muốn triển khai chức năng này trong Recycler.Adapter

Trên phương thức getItemCount bị ghi đè của bạn, hãy nhập mã kiểm tra trống vào đó:

@Override
public int getItemCount() {
    if(data.size() == 0) listIsEmtpy();
    return data.size();
}

3
Đó không phải là khả năng đáp ứng của bộ điều hợp. Bộ điều hợp ở đây để hiển thị các mặt hàng, không phải là không có mặt hàng.
Marc Plano-Lesay

@Kernald Mã của chúng tôi và theo cách riêng của chúng tôi, cách chúng tôi tùy chỉnh và sử dụng nó.
Lalit Poptani

@LalitPoptani chắc chắn. Nhưng đó là một trang web Hỏi & Đáp, nơi mọi người đang tìm kiếm câu trả lời, hầu hết thời gian mà không cần suy nghĩ nhiều hơn "phím tắt sao chép lại là gì?". Chỉ ra rằng giải pháp là ngữ nghĩa sai (hơn nữa khi bạn cũng có "quyền" giải pháp) là không thực sự vô dụng ...
Marc Plano-Lesay

@Kernald à Tôi nghĩ giải pháp này là đơn giản nhất và nó cũng là một giải pháp tốt, vì mỗi khi bộ điều hợp được thông báo, nó sẽ được gọi và có thể được sử dụng để kiểm tra kích thước của dữ liệu!
Lalit Poptani

1
@ MarcPlano-Lesay là chính xác. Câu trả lời này không đầy đủ vì nó không xử lý trường hợp khi chế độ xem trống cần ẩn khi các mục được lấp đầy. Sau khi thực hiện phần đó, giải pháp này trở nên không hiệu quả vì mỗi khi bộ điều hợp truy vấn số mục, setVisibility()sẽ được gọi. Chắc chắn bạn có thể thêm một số cờ để bù đắp nhưng đó là khi nó trở nên phức tạp hơn.
razzledazzle

2

Nếu bạn muốn hỗ trợ nhiều trạng thái hơn như trạng thái tải, trạng thái lỗi thì bạn có thể kiểm tra https://github.com/rockerhieu/rv-adapter-states . Nếu không, hỗ trợ chế độ xem trống có thể được triển khai dễ dàng bằng cách sử dụng RecyclerViewAdapterWrappertừ ( https://github.com/rockerhieu/rv-adapter ). Ưu điểm chính của cách tiếp cận này là bạn có thể dễ dàng hỗ trợ chế độ xem trống mà không cần thay đổi logic của bộ điều hợp hiện có:

public class StatesRecyclerViewAdapter extends RecyclerViewAdapterWrapper {
    private final View vEmptyView;

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

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

    public static final int TYPE_EMPTY = 1001;

    @State
    private int state = STATE_NORMAL;

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

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

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

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

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

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

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

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

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

Sử dụng:

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

// Change the states of the adapter
statesRecyclerViewAdapter.setState(StatesRecyclerViewAdapter.STATE_EMPTY);
statesRecyclerViewAdapter.setState(StatesRecyclerViewAdapter.STATE_NORMAL);

Tôi đã sử dụng mã của bạn làm cơ sở cho một giải pháp tương tự. Cảm ơn!
Albert Vila Calvo

2

Tôi đã sửa lỗi này:
Đã tạo tệp layout layout_recyclerview_with_emptytext.xml.
Đã tạo EmptyViewRecyclerView.java
---------

EmptyViewRecyclerView blankRecyclerView = (EmptyViewRecyclerView) findViewById (R.id.emptyRecyclerViewLayout);
voidRecyclerView.addAdapter (mPrayerCollectionRecyclerViewAdapter, "Không có lời cầu nguyện nào cho danh mục đã chọn.");

tệp layout_recyclerview_with_emptytext.xml

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

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

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

    </merge>


EmptyViewRecyclerView.java

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

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

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


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

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

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

public RecyclerView getRecyclerView() {
    return mRecyclerView;
}

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

}

1
public class EmptyRecyclerView extends RecyclerView {
  @Nullable View emptyView;

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

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

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

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

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

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

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

một cái gì đó như thế này có thể giúp


2
Điều này là không đầy đủ. Có thể bạn sẽ cần phải ẩn RecyclerViewkhi nào emptyViewhiển thị (và ngược lại). Bạn cũng sẽ cần phải gọi checkIfEmpty()vào onItemRangeInserted()onItemRangeRemoved(). Ồ, và bạn có thể đã trích dẫn nguồn của mình: gist.github.com/adelnizamutdinov/31c8f054d1af4588dc5c
Marc Plano-Lesay


1

Bạn chỉ có thể sơn văn bản trên RecyclerViewkhi nó trống. Các tùy chỉnh sau lớp con hỗ trợ empty, failed, loading, và offlinechế độ. Để biên dịch thành công, hãy thêm recyclerView_stateTextmàu sắc vào tài nguyên của bạn.

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

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

        setUp(context);
    }

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

        setUp(context);
    }

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

        setUp(context);
    }

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

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

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

    private State state;

    public State state()
    {
        return state;
    }

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

    private String loadingText = "Loading...";

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

    private String emptyText = "Empty";

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

    private String failedText = "Failed";

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

    private String offlineText = "Offline";

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

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

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

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

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

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

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

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

        calculateLayout(w, h);
    }

    private String stringForCurrentState()
    {
        if (state == State.EMPTY)
            return emptyText;
        else if (state == State.LOADING)
            return loadingText;
        else if (state == State.FAILED)
            return failedText;
        else if (state == State.OFFLINE)
            return offlineText;
        else
            return null;
    }
}

1

Theo quan điểm của tôi, cách đơn giản nhất để thực hiện một View trống là tạo RecyclerView trống mới với bố cục bạn muốn tăng lên làm nền. Và Bộ điều hợp trống này được đặt khi bạn kiểm tra kích thước tập dữ liệu của mình.

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.