RecyclerView中ListView.setEmptyView的等价物
在RecyclerView
,我想设置一个空的视图,当适配器为空时显示。 有没有相当于ListView.setEmptyView()
?
使用新的数据绑定function,您也可以直接在您的布局中实现这一点:
<TextView android:text="No data to display." android:visibility="@{dataset.size() > 0 ? View.GONE : View.VISIBLE}" />
在这种情况下,您只需将一个variables和一个导入添加到XML的数据部分:
<data> <import type="android.view.View"/> <variable name="dataset" type="java.util.List<java.lang.String>" /> </data>
这里有一个类似于@dragon的类,但更完整。 基于这个要点 。
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(); } }
这个链接提供的解决scheme似乎很完美 它使用viewType来确定何时显示emptyView。 无需创build自定义的RecyclerView
从上面的链接添加代码:
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; } }
我只是喜欢简单的解决scheme,
将您的RecyclerView放入FrameLayout或RelativeLayout中,使用TextView或其他视图,默认显示空数据消息GONE,然后在适配器类中应用逻辑
在这里,我有一个TextView消息没有数据
@Override public int getItemCount() { textViewNoData.setVisibility(data.size() > 0 ? View.GONE : View.VISIBLE); return data.size(); }
我的版本,基于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(); } }
我宁愿在Recycler.Adapter中实现这个function
在您重写的getItemCount方法上,在其中注入空的校验码:
@Override public int getItemCount() { if(data.size() == 0) listIsEmtpy(); return data.size(); }
如果你想支持更多的状态,如加载状态,错误状态,那么你可以检出https://github.com/rockerhieu/rv-adapter-states 。 否则,可以使用( https://github.com/rockerhieu/rv-adapter )中的RecyclerViewAdapterWrapper
轻松实现支持空视图。 这种方法的主要优点是您可以轻松支持空视图而无需更改现有适配器的逻辑:
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); } } }
用法:
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);
我已经解决这个问题:
创build了布局layout_recyclerview_with_emptytext.xml文件。
创buildEmptyViewRecyclerView.java
———
EmptyViewRecyclerView emptyRecyclerView =(EmptyViewRecyclerView)findViewById(R.id.emptyRecyclerViewLayout);
emptyRecyclerView.addAdapter(mPrayerCollectionRecyclerViewAdapter,“没有select的类别祈祷”);
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); } }
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(); } }
这样的事情可能会有帮助
我认为这是更完整的ErrorView&EmptyView https://gist.github.com/henrytao-me/2f7f113fb5f2a59987e7
您可以在RecyclerView
空白时直接绘制文本。 以下自定义子类支持empty
, failed
, loading
和offline
模式。 为了成功编译,将recyclerView_stateText
颜色添加到您的资源中。
/** * {@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; } }
从我的angular度来看,如何做一个空的视图最简单的方法是创build一个新的空的RecyclerView与布局,你想膨胀作为背景。 当你检查你的数据集的大小,这个空的适配器被设置。
尝试RVEmptyObserver
:
这是一个AdapterDataObserver
的实现,它允许您简单地将View
设置为RecylerView
的默认空白布局。 通过这种方式,您可以轻松地将其与现有的代码一起使用,而不是使用自定义的RecyclerView
并使您的生活更加艰难:
用法示例:
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(); } }