Как показать пустой вид с помощью RecyclerView?
Я привык помещать специальный вид внутри файла макета как описано в 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?
11 ответов:
на том же макете, где определяется
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); }
для моих проектов я принял это решение (
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));
вот решение, использующее только пользовательский адаптер с другим типом представления для пустой ситуации.
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); } } }
Я использую 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);
на проверьте, имеет ли адаптер 0 элементов и верните другой тип представления, если это так.
на
onCreateViewHolderпроверьте, является ли viewType тем, который вы вернули ранее, и раздуйте другой вид. В этом случае файл макета с этим TextViewEDIT
если это все еще не работает, то вы можете установить размер представления программно следующим образом:
Point size = new Point(); ((WindowManager)itemView.getContext().getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay().getSize(size);и после этого когда вы надуваете ваше просмотр вызова:
inflatedView.getLayoutParams().height = size.y; inflatedView.getLayoutParams().width = size.x;
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(); } }
так как ответ Кевина не является полным.
Это более правильный ответ, если вы используетеRecyclerAdapter' snotifyItemInsertedи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); } });
вот мой класс для показа пустого представления, повторите просмотр (когда загрузка api не удалась) и прогресс загрузки для
RecyclerViewpublic 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
добавил
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(); }
просто упакуйте вы работаете с FirebaseRecyclerAdapter этот пост работает как шарм https://stackoverflow.com/a/39058636/6507009
попробуй
listView,addFooterViewпосле добавления адаптера кlistviewlistview.setAdapter(adapter); listview.addFooterView(emptyView);

Comments