在RecyclerView中等效ListView.setEmptyView

Man*_*ani 86 android recycler-adapter android-recyclerview

RecyclerView,我想设置一个空视图,以便在适配器为空时显示.有相同的ListView.setEmptyView()吗?

Mar*_*say 113

这是一个类似@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();
    }
}
Run Code Online (Sandbox Code Playgroud)

  • Google示例中的类似实现:https://github.com/googlesamples/android-XYZTouristAttractions/blob/master/Application/src/main/java/com/example/android/xyztouristattractions/ui/AttractionsRecyclerView.java (5认同)
  • 很酷的解决方案,但类名很奇怪 =) (2认同)

And*_*ann 68

使用新的数据绑定功能,您还可以直接在布局中实现此功能:

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

在这种情况下,您只需要在XML的数据部分添加变量和导入:

<data>
<import type="android.view.View"/>
<variable
    name="dataset"
    type="java.util.List&lt;java.lang.String&gt;"
    />
</data>
Run Code Online (Sandbox Code Playgroud)

  • 简化上述示例以强调数据绑定方法.数据绑定非常灵活.您当然可以导入`Adapter`而不是数据集并使用它的`getItemCount()`或将所有内容包装在`ViewModel`中并将`android:visibility`设置为`viewModel.getEmptyViewVisibility()`. (5认同)
  • 这应该更高,这是数据绑定功能的一个很好的例子 (4认同)
  • 即使适配器动态增长或缩小到零,这是否会更新?我不信. (2认同)
  • @a11n当列表缩小到0或获取数据时,它不会更新布局,每次对列表进行任何更改时,我们都必须将值设置为类中的绑定,有什么方法可以自行更新布局吗? (2认同)

Sud*_*sri 26

此链接中提供的解决方案似乎很完美 它使用viewType来标识何时显示emptyView.无需创建自定义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;
}

}
Run Code Online (Sandbox Code Playgroud)

  • 我认为扩展RecyclerView比这个更加适用于解决方案,因为通常我有很多回收适配器,我想避免将这种逻辑添加到它们中的每一个. (6认同)
  • 即使您只有一个适配器和一个回收器视图,也不是适配器的责任.适配器用于显示物品,而不是物品. (2认同)
  • @Deveti Putnik:适配器已经表明没有数据:项目计数等于零。当您使用此解决方案时,您实际上无法提供此信息,因为当适配器为空时,您仍然指示它包含一个元素。这在语义上是错误的。视图类型应该取决于特定元素。元素的缺失不是元素。使用适配器来处理这种情况意味着您还使用适配器来处理错误情况。适配器与网络丢失有何关系?没有什么。 (2认同)

Lal*_*ani 9

我只是喜欢一个简单的解决方案,比如

将您的RecyclerView放在FrameLayout或RelativeLayout中,使用TextView或其他视图显示空数据消息,默认情况下可见GONE,然后在适配器类中应用逻辑

在这里,我有一个TextView,消息没有数据

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