Android RecyclerView : Update all items height after notifyDataSetChanged

标签 android android-recyclerview

在我的适配器类的 onCreateViewHolder 中,我将屏幕的总高度分布在我拥有的项目上,如下所示:

@Override
public ViewHolder onCreateViewHolder(final ViewGroup parent, int viewType) {
    View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.single_card, parent, false);
    // float weight = 1 / (mCards.size() * 1.0f);
    // LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, 0, weight);
    // view.setMinimumHeight(params.height);
    int height = parent.getMeasuredHeight() / mCards.size();
    view.setMinimumHeight(height - 15);
    return new ViewHolder(view, listener);
}

但是当我调用 adapter.notifyDataSetChanged() 时,只有新项目获得新高度。所有其他(已经存在的)项目都保持旧高度。

我应该把高度计算移到哪里才能在数据集更新时检查它?

最佳答案

在 RecyclerView 中,onCreateViewHolder() 在创建新 View 对象并附加到父 View 时被调用,onBindViewHolder() 在 View 离开时被调用滚动屏幕,屏幕上会出现一个新 View 。

回收适配器.java

public class RecyclerAdapter extends RecyclerView.Adapter<RecyclerAdapter.ViewHolder>{

private Context context;
private ArrayList<String> months = new ArrayList<>();

public RecyclerAdapter(Context context, ArrayList<String> months){
    this.context = context;
    this.months = months;
}

@Override
public RecyclerAdapter.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
    View vi = LayoutInflater.from(parent.getContext()).inflate(R.layout.list_item, parent, false);
    Log.d("RECYCLER_CALLBACKS", "onCreateViewHolder() " + parent.getChildCount());
    return new ViewHolder(vi);
}

@Override
public void onBindViewHolder(RecyclerAdapter.ViewHolder holder, int position) {
    holder.month.setText(months.get(position));
    Log.d("RECYCLER_CALLBACKS", "onBindViewHolder() " + months.get(holder.getAdapterPosition()));
}

@Override
public void onViewRecycled(ViewHolder holder) {
    super.onViewRecycled(holder);
    Log.d("RECYCLER_CALLBACKS", "onViewRecycled() " + months.get(holder.getAdapterPosition()));
}

@Override
public int getItemCount() {
    return months.size();
}

public class ViewHolder extends RecyclerView.ViewHolder {

    private CardView cardView;
    private TextView month;
    private TextView date;

    public ViewHolder(View itemView) {
        super(itemView);
        cardView = (CardView) itemView.findViewById(R.id.cardView);
        month = (TextView) itemView.findViewById(R.id.textView2);
        date = (TextView) itemView.findViewById(R.id.textView3);
    }
}

主 Activity .java

public class MainActivity extends AppCompatActivity {

private Button button;
private RecyclerView recyclerView;
private LinearLayoutManager layoutManager;
private RecyclerAdapter adapter;

private static int MONTH_COUNT = 1;
private ArrayList<String> monthsList = new ArrayList<>();

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    monthsList.add("January");
    monthsList.add("February");
    monthsList.add("March");
    monthsList.add("April");
    monthsList.add("May");
    monthsList.add("June");
    monthsList.add("July");
    monthsList.add("August");
    monthsList.add("September");
    monthsList.add("October");
    monthsList.add("November");
    monthsList.add("December");

    recyclerView = (RecyclerView) findViewById(R.id.recyclerView);
    layoutManager = new LinearLayoutManager(this, LinearLayoutManager.VERTICAL, false);
    recyclerView.setLayoutManager(layoutManager);
    adapter = new RecyclerAdapter(this, monthsList);
    recyclerView.setAdapter(adapter);

    button = (Button) findViewById(R.id.button);
    button.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            monthsList.add("New Month " + MONTH_COUNT);
            MONTH_COUNT++;
            adapter.notifyDataSetChanged();
        }
    });
}

enter image description here 目前,屏幕上只有 6 个项目可见。一旦应用程序启动

08-26 21:32:23.547 28518-28518/com.stabstudio.afteranimation D/RECYCLER_CALLBACKS: onCreateViewHolder() 0

08-26 21:32:23.557 28518-28518/com.stabstudio.afteranimation D/RECYCLER_CALLBACKS: onCreateViewHolder() 1

08-26 21:32:23.557 28518-28518/com.stabstudio.afteranimation D/RECYCLER_CALLBACKS: onBindViewHolder() February

08-26 21:32:23.563 28518-28518/com.stabstudio.afteranimation D/RECYCLER_CALLBACKS: onCreateViewHolder() 2

08-26 21:32:23.563 28518-28518/com.stabstudio.afteranimation D/RECYCLER_CALLBACKS: onBindViewHolder() March

08-26 21:32:23.569 28518-28518/com.stabstudio.afteranimation D/RECYCLER_CALLBACKS: onCreateViewHolder() 3

08-26 21:32:23.569 28518-28518/com.stabstudio.afteranimation D/RECYCLER_CALLBACKS: onBindViewHolder() April

08-26 21:32:23.575 28518-28518/com.stabstudio.afteranimation D/RECYCLER_CALLBACKS: onCreateViewHolder() 4

08-26 21:32:23.575 28518-28518/com.stabstudio.afteranimation D/RECYCLER_CALLBACKS: onBindViewHolder() May

08-26 21:32:23.581 28518-28518/com.stabstudio.afteranimation D/RECYCLER_CALLBACKS: onCreateViewHolder() 5

08-26 21:32:23.581 28518-28518/com.stabstudio.afteranimation D/RECYCLER_CALLBACKS: onBindViewHolder() June

最初,在创建 View 时,会为每个 View 调用 onCreateViewHolder() 和 onBindViewHolder()。当我们向下滚动到底部时

08-26 21:37:36.579 28518-28518/com.stabstudio.afteranimation D/RECYCLER_CALLBACKS: onCreateViewHolder() 6

28518-28518/com.stabstudio.afteranimation D/RECYCLER_CALLBACKS: onBindViewHolder() July

28518-28518/com.stabstudio.afteranimation D/RECYCLER_CALLBACKS: onCreateViewHolder() 7

28518-28518/com.stabstudio.afteranimation D/RECYCLER_CALLBACKS: onBindViewHolder() August

28518-28518/com.stabstudio.afteranimation D/RECYCLER_CALLBACKS: onCreateViewHolder() 7

28518-28518/com.stabstudio.afteranimation D/RECYCLER_CALLBACKS: onBindViewHolder() September

28518-28518/com.stabstudio.afteranimation D/RECYCLER_CALLBACKS: onCreateViewHolder() 7

28518-28518/com.stabstudio.afteranimation D/RECYCLER_CALLBACKS: onBindViewHolder() October

28518-28518/com.stabstudio.afteranimation D/RECYCLER_CALLBACKS: onViewRecycled() January

28518-28518/com.stabstudio.afteranimation D/RECYCLER_CALLBACKS: onBindViewHolder() November

28518-28518/com.stabstudio.afteranimation D/RECYCLER_CALLBACKS: onViewRecycled() February

28518-28518/com.stabstudio.afteranimation D/RECYCLER_CALLBACKS: onBindViewHolder() December

28518-28518/com.stabstudio.afteranimation D/RECYCLER_CALLBACKS: onViewRecycled() March

因此,onCreateViewHolder() 在第 8 个 View 后停止调用,而是调用 onViewRecycled()创建一个新 View 。 现在,当我们滚动回顶部时:

08-26 21:54:20.262 28518-28518/com.stabstudio.afteranimation D/RECYCLER_CALLBACKS: onBindViewHolder() March

08-26 21:54:20.784 28518-28518/com.stabstudio.afteranimation D/RECYCLER_CALLBACKS: onViewRecycled() December

08-26 21:54:21.471 28518-28518/com.stabstudio.aftera nimation D/RECYCLER_CALLBACKS: onBindViewHolder() February

08-26 21:54:21.835 28518-28518/com.stabstudio.afteranimation D/RECYCLER_CALLBACKS: onViewRecycled() November

08-26 21:54:22.277 28518-28518/com.stabstudio.afteranimation D/RECYCLER_CALLBACKS: onBindViewHolder() January

08-26 21:54:26.050 28518-28518/com.stabstudio.afteranimation D/RECYCLER_CALLBACKS: onViewRecycled() October

当我们向上滚动时,十二月首先离开屏幕,三月进入屏幕。所以,

  1. 12 月被回收,以通过回调让位于 3 月 onViewRecycled() 十二月onBindViewHolder() 三月。
  2. 同样,11 月被回收,2 月取而代之 回调 onViewRecycled() NovemberonBindViewHolder() 二月
  3. 最后,onViewRecycled() 十月onBindViewHolder() 一月

现在,当我们创建一个新的月份时,我们调用 notifyDataSetChanged() 将更改报告给适配器:

2597-2597/com.stabstudio.afteranimation D/RECYCLER_CALLBACKS: onViewRecycled() 5 2597-2597/com.stabstudio.afteranimation D/RECYCLER_CALLBACKS: onViewRecycled() 4 2597-2597/com.stabstudio.afteranimation D/RECYCLER_CALLBACKS: onViewRecycled() 3 2597-2597/com.stabstudio.afteranimation D/RECYCLER_CALLBACKS: onViewRecycled() -1 2597-2597/com.stabstudio.afteranimation D/RECYCLER_CALLBACKS: onViewRecycled() -1 2597-2597/com.stabstudio.afteranimation D/RECYCLER_CALLBACKS: onViewRecycled() -1 2597-2597/com.stabstudio.afteranimation D/RECYCLER_CALLBACKS: onViewRecycled() -1 2597-2597/com.stabstudio.afteranimation D/RECYCLER_CALLBACKS: onViewRecycled() -1 2597-2597/com.stabstudio.afteranimation D/RECYCLER_CALLBACKS: onViewRecycled() -1 2597-2597/com.stabstudio.afteranimation D/RECYCLER_CALLBACKS: onBindViewHolder() July 2597-2597/com.stabstudio.afteranimation D/RECYCLER_CALLBACKS: onBindViewHolder() August 2597-2597/com.stabstudio.afteranimation D/RECYCLER_CALLBACKS: onBindViewHolder() September 2597-2597/com.stabstudio.afteranimation D/RECYCLER_CALLBACKS: onBindViewHolder() October 2597-2597/com.stabstudio.afteranimation D/RECYCLER_CALLBACKS: onBindViewHolder() November 2597-2597/com.stabstudio.afteranimation D/RECYCLER_CALLBACKS: onCreateViewHolder() 5 2597-2597/com.stabstudio.afteranimation D/RECYCLER_CALLBACKS: onBindViewHolder() December 2597-2597/com.stabstudio.afteranimation D/RECYCLER_CALLBACKS: onCreateViewHolder() 6 2597-2597/com.stabstudio.afteranimation D/RECYCLER_CALLBACKS: onBindViewHolder() New Month 1

一旦 notifyDataSetChanged() 被调用,所有的 View 都会被回收,并且 onCreateViewHolder() 会被再次调用,次数与显示的数量相同在屏幕上 + 2。 1 个在屏幕顶部,1 个在屏幕底部,这是不可见的。在本例中,无论 RecyclerView 中有多少项,它都只有 8 次。

因此,您应该将高度计算移至 onBindViewHolder(),它会在所有 View 中被调用,而不是 onCreateViewHolder(),后者仅被调用与屏幕上可见项目的数量一样多.

关于Android RecyclerView : Update all items height after notifyDataSetChanged,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45884240/

相关文章:

java - 安卓 Ant 构建

android - 我可以像<loan_amount,adv_interest_amount>一样从房间查询中获取数据吗?

java - 集成加载器和回收器 View 不起作用

android - CardView突然变黑

java - 从单选组值中选择一个并向下滚动并在 Recycler View 中自动选择一些项目(初学者)

java - 在 SettingsActivity 中未定义 findPreference

android - ListView 上的聊天气泡对齐

android - AsyncTask 无法执行任务 : the task has already been executed

java - 如何仅在按下按钮时才重新加载 recyclerview?

android - 处理 RecyclerView 上的 TouchEvents