Android 与RecyclerView中的ListView.setEmptyView等效
在Android 与RecyclerView中的ListView.setEmptyView等效,android,android-recyclerview,Android,Android Recyclerview,在RecyclerView中,我想设置一个空视图,以便在适配器为空时显示。是否有一个等价物 类似的内容可能会有所帮助这里有一个类似于@dragon born的类,但更完整。基于 我的版本,基于 我更愿意在Recycler.Adapter中实现此功能 在重写的getItemCount方法上,在此处插入空检查代码: @Override public int getItemCount() { if(data.size() == 0) listIsEmtpy(); return data
RecyclerView
中,我想设置一个空视图,以便在适配器为空时显示。是否有一个等价物
类似的内容可能会有所帮助这里有一个类似于@dragon born的类,但更完整。基于 我的版本,基于
我更愿意在Recycler.Adapter中实现此功能 在重写的getItemCount方法上,在此处插入空检查代码:
@Override
public int getItemCount() {
if(data.size() == 0) listIsEmtpy();
return data.size();
}
中提供的解决方案似乎是完美的。它使用viewType标识何时显示emptyView。无需创建自定义回收视图
从上述链接添加代码:
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;
}
}
package com.example.androidsampleproject;
导入java.util.ArrayList;
导入java.util.List;
导入android.app.Activity;
导入android.os.Bundle;
导入android.support.v7.widget.LinearLayoutManager;
导入android.support.v7.widget.RecyclerView;
导入android.view.LayoutInflater;
导入android.view.view;
导入android.view.ViewGroup;
导入android.widget.TextView;
公共类RecycleServiceActivity扩展活动{
回收视图回收视图;
@凌驾
创建时受保护的void(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
setContentView(R.layout.activity\u recycler\u视图);
recyclerView=(recyclerView)findViewById(R.id.myList);
recyclerView.setLayoutManager(新的LinearLayoutManager(本));
setAdapter(新的MyAdapter());
}
私有类MyAdapter扩展了RecyclerView.Adapter{
private List dataList=new ArrayList();
公共类EmptyViewHolder扩展了RecyclerView.ViewHolder{
公共空视图文件夹(视图项视图){
超级(项目视图);
}
}
公共类ViewHolder扩展了RecyclerView.ViewHolder{
文本视图数据;
公共视图持有者(视图v){
超级(五);
数据=(TextView)v.findViewById(R.id.data\u视图);
}
}
@凌驾
public int getItemCount(){
返回dataList.size()>0?dataList.size():1;
}
@凌驾
public int getItemViewType(int位置){
如果(dataList.size()==0){
返回空视图;
}
返回super.getItemViewType(位置);
}
@凌驾
BindViewHolder上的公共无效(RecyclerView.ViewHolder vho,最终int pos){
if(视窗支架的vho实例){
视窗持有人vh=(视窗持有人)vho;
字符串pi=dataList.get(pos);
}
}
@凌驾
public RecyclerView.ViewHolder onCreateViewHolder(视图组父级,int-viewType){
观点五;
如果(视图类型==空视图){
v=LayoutInflater.from(parent.getContext()).flate(R.layout.empty_视图,parent,false);
EmptyViewHolder evh=新的EmptyViewHolder(v);
返回evh;
}
v=LayoutInflater.from(parent.getContext()).flate(R.layout.data_行,parent,false);
视窗支架vh=新视窗支架(v);
返回vh;
}
私有静态最终整型空视图=10;
}
}
我认为使用ErrorView和EmptyView这两种功能更为完整使用新功能,您还可以直接在布局中实现这一点:
<TextView
android:text="No data to display."
android:visibility="@{dataset.size() > 0 ? View.GONE : View.VISIBLE}" />
在这种情况下,您只需要向XML的数据部分添加一个变量和一个导入:
<data>
<import type="android.view.View"/>
<variable
name="dataset"
type="java.util.List<java.lang.String>"
/>
</data>
如果您想支持更多状态,如加载状态、错误状态,则可以签出。否则,可以使用()中的
recycleServiceAdapterWrapper
from()轻松实现对空视图的支持。这种方法的主要优点是,您可以轻松地支持空视图,而无需更改现有适配器的逻辑:
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);
我更喜欢一个简单的解决方案,比如 让您的RecyclerView位于FrameLayout或RelativeLayout中,其中包含文本视图或其他视图,默认情况下显示不可见的空数据消息,然后在适配器类中应用逻辑 在这里,我有一个没有数据的文本视图
@Override
public int getItemCount() {
textViewNoData.setVisibility(data.size() > 0 ? View.GONE : View.VISIBLE);
return data.size();
}
当
RecyclerView
为空时,您只需在其上绘制文本即可。以下自定义子类支持空
、失败
、加载
和脱机
模式。要成功编译,请在资源中添加recyclerView\u stateText
color
/**
* {@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;
}
}
从我的观点来看,创建空视图的最简单方法是创建新的空RecyclerView,并将您想要膨胀的布局作为背景。 检查数据集大小时会设置此空适配器。我已修复此问题:
已使用\u emptytext.xml文件创建布局\u recyclerview\u。
已创建EmptyViewRecyclerView.java
-----------
EmptyViewRecyclerView emptyRecyclerView=(EmptyViewRecyclerView)findViewById(R.id.emptyRecyclerViewLayout)
addAdapter(mprayerCollectionRecycleServiceAdapter,“没有为所选类别祈祷”) 使用\u emptytext.xml文件布局\u recyclerview\u
<?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);
}
}
公共类EmptyViewRecyclerView扩展了ViewSwitcher{
私人回收视图mRecyclerView;
私有CustomFontTextView MRECyclServiceExptyTextView;
公共EmptyViewRecyclerView(上下文){
超级(上下文);
initView(上下文);
}
public emptyViewRecycleView(上下文上下文、属性集属性){
超级(上下文,attrs);
initView(上下文);
}
私有void initView(上下文){
LayoutFlater.from(context).充气(R.layout.layout_recyclerview_,带有_emptytext,this,true);
mrecycleServiceExptyTextView=(CustomFontTextView)findViewById(R.id.RecycleServiceEmptyTextView);
mRecyclerView=(RecyclerView)findViewById(R.id.RecyclerView);
mRecyclerView.setLayoutManager(新的LinearLayoutManager(上下文));
}
public void addAdapter(final RecyclerView.Adapter适配器){
mRecyclerView.setAdapter(适配器);
registerAdapterDataObserver(新的RecyclerView.AdapterDataObserver(){
@凌驾
公共空间
/**
* {@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;
}
}
<?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>
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);
}
}
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(); }
}
class RecyclerViewEmpty extends RecyclerView {
....
@Override
public void onDraw(Canvas canvas) {
Adapter a = this.getAdapter();
if(a==null || a.getItemCount()<1) {
int x= (this.getWidth()-strWidth)>>1;
int y = this.getHeight()>>1 ;
canvas.drawText(this.emptyLabel, x, y, labelPaint);
}
else {
super.onDraw(canvas);
}
}
....
}