在创建之前查找有多少RecyclerView项目适合屏幕

时间:2015-11-02 17:49:58

标签: java android android-recyclerview

基本上,我试图以编程方式找出ReclerView中有多少项目(当然是对用户可见),以确定从缓存中获取的项目数量。

我正在使用LinearLayoutManager。

另外,我知道LinearLayoutManager方法findLastVisibleItemPosition,但显然它在这种情况下无用,因为我们在初始化之前的时间而不是之后(因此它返回-1)

尝试阅读文档或思考创造性但有效的想法,但我没有想到任何事情。

有什么想法吗?

1 个答案:

答案 0 :(得分:0)

这听起来非常有趣,但只有在您的高度(垂直滚动)或宽度(水平滚动)固定时才有效,这意味着没有wrap_content。

没有示例代码,也没有在此测试:

  1. 使用getCount的setter创建一个适配器,以便在您的数据源为空/空时返回
  2. 如果您的数据为空/ null,则getCount中的
  3. 至少返回1
  4. 确保onBindViewHolder()可以处理空/不存在的数据
  5. 向您的RecyclerView添加OnChildAttachStateChangeListener,每次调用侦听器时,使用viewview.post(new Runnable() {...increase adapters getCount...adapter.notifyItemInserted()}(必须运行runnable以避免崩溃+刻录)
  6. 再次调用
  7. OnChildAttachStateChangeListener>>>比较getCountfindLastVisibleItemPosition。如果getCount > findLastVisibleItemPosition + 1删除该侦听器。适合ListView的固定大小视图的数量为findLastVisibleItemPosition + 1
  8. 获取您的数据并将其设置为适配器,请致电notifyDataSetChanged
  9. 确保getCount从现在开始返回数据源长度。
  10. 您可以隐藏装订屏幕后面的列表视图,或者您可以在onBindViewHolder

    中将子视图设置为不可见

    编辑:

    1. 创建一个适配器,在没有设置数据时返回一个荒谬的高计数,并确保它在onBindViewHolder
    2. 中正确处理丢失的数据
    3. 如果LinearLayoutManager getChildCount()是您在RecyclerView中可见的视图数量
    4. ,则在超级调用后扩展onLayoutChildren()并覆盖getItemCount() > getChildCount()

      MainActivity.class

          public class MainActivity extends AppCompatActivity {
      
              private PreCountingAdapter mAdapter;
              private RecyclerView mRecyclerView;
              private PreCountLinearLayoutManager mPreCountLayoutManager;
      
              @Override
              protected void onCreate(Bundle savedInstanceState) {
                  super.onCreate(savedInstanceState);
                  setContentView(R.layout.activity_main);
                  mRecyclerView = (RecyclerView) findViewById(R.id.recycler_view);
                  mPreCountLayoutManager = new PreCountLinearLayoutManager(this,
                          LinearLayoutManager.VERTICAL, false);
                  mPreCountLayoutManager.setListener(new PreCountLinearLayoutManager.OnPreCountedListener() {
                      @Override
                      public void onPreCounted(int count) {
                          mPreCountLayoutManager.setListener(null);
                          loadData(count);
                      }
                  });
                  mRecyclerView.setLayoutManager(mPreCountLayoutManager);
                  mAdapter = new PreCountingAdapter();
                  mRecyclerView.setAdapter(mAdapter);
              }
      
              private void loadData(final int visibleItemCount) {
                  // load data here, probably asynchronously,
                  // for simplicity just an String Array with size visibleItemCount
                  final List<String> data = new ArrayList<>();
                  for (int i = 0; i < visibleItemCount; i++) {
                      data.add(String.format("child number #%d", i));
                  }
                  mRecyclerView.post(new Runnable() {
                      @Override
                      public void run() {
                          mAdapter.swapData(data);
                      }
                  });
              }
      
              @Override
              protected void onDestroy() {
                  mPreCountLayoutManager.setListener(null);
                  super.onDestroy();
              }
          }
      

      PreCountLinearLayoutManager.class

          public class PreCountLinearLayoutManager extends LinearLayoutManager {
              private OnPreCountedListener mListener;
      
              public interface OnPreCountedListener {
                  void onPreCounted(int count);
              }
      
              public PreCountLinearLayoutManager(Context context, int orientation, boolean reverseLayout) {
                  super(context, orientation, reverseLayout);
              }
      
              @Override
              public void onLayoutChildren(RecyclerView.Recycler recycler, RecyclerView.State state) {
                  super.onLayoutChildren(recycler, state);
                  if (getItemCount() > getChildCount()) {
                      if (mListener != null) {
                          mListener.onPreCounted(getChildCount());
                      }
                  }
              }
      
              public void setListener(OnPreCountedListener listener) {
                  mListener = listener;
              }
          }
      

      PreCountingAdapter.class

          public class PreCountingAdapter extends RecyclerView.Adapter<PreCountingAdapter.ViewHolder> {
      
              private List<String> mData;
      
              public void swapData(List<String> data) {
                  mData = data;
                  notifyDataSetChanged();
              }
      
              public class ViewHolder extends RecyclerView.ViewHolder {
      
                  View mItemView;
                  TextView mTextView;
      
                  public ViewHolder(View itemView) {
                      super(itemView);
                      mTextView = (TextView) itemView.findViewById(R.id.text_view);
                      mItemView = itemView;
                  }
              }
      
              @Override
              public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
                  LayoutInflater inflater = LayoutInflater.from(parent.getContext());
                  return new ViewHolder(inflater.inflate(R.layout.recycler_child, parent, false));
              }
      
              @Override
              public void onBindViewHolder(ViewHolder holder, int position) {
                  if (mData == null) {
                      // we are in precounting stage
                      holder.mItemView.setVisibility(View.INVISIBLE);
                  } else {
                      String item = mData.get(position);
                      holder.mItemView.setVisibility(View.VISIBLE);
                      holder.mTextView.setText(item);
                  }
              }
      
              @Override
              public int getItemCount() {
                  return mData == null ? Integer.MAX_VALUE : mData.size();
              }
      
          }