You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

切换明暗模式时Android ListView出现重复项问题求助

Android笔记应用明暗模式切换后ListView出现重复项的解决方案

问题根源

你的ListView出现重复项的核心原因是自定义Adapter的getView方法中,复用已有的Item View时,没有清空ChipGroup中的旧标签(Chip)。每次切换主题触发视图刷新后,getView会复用之前的View,而旧的Chip仍然保留,新的Chip又被添加进去,导致标签重复。同时,getView中存在一些不必要的重复操作,也会加重问题。

修复步骤及代码修改

1. 优化View复用与Holder逻辑

  • 仅在创建新View时初始化NoteHolder,复用View时直接从Tag中获取;
  • 将CardView等固定View的初始化移到View创建阶段,避免每次findViewById浪费性能;

2. 强制清空ChipGroup再加载新标签

无论当前View是新创建还是复用的,在添加新Chip之前,必须清空ChipGroup的所有子View,确保每个Item只显示当前笔记的标签。

修改后的getView方法代码

public View getView(int position, View convertView, ViewGroup parent) {
    View v = convertView;
    NoteHolder holder;

    Note n = noteList.get(position);
    Set<String> folders = n.getFolders();
    Set<String> foldersForChips = new HashSet<>(folders);
    foldersForChips.remove("Notes");
    foldersForChips.remove("All Notes");

    if (v == null) {
        LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        v = inflater.inflate(R.layout.row_layout, parent, false);

        holder = new NoteHolder();
        // 一次性初始化所有View到Holder中
        holder.foldersChipGroup = v.findViewById(R.id.labels_of_note);
        holder.foldersChipGroup.setChipSpacingHorizontal(2);
        holder.foldersChipGroup.setClickable(false);
        holder.foldersChipGroup.setFocusable(false);
        
        holder.titleView = v.findViewById(R.id.title);
        holder.contentView = v.findViewById(R.id.content);
        holder.cardView = v.findViewById(R.id.cardView);

        v.setTag(holder);
    } else {
        holder = (NoteHolder) v.getTag();
    }

    // 关键操作:清空旧标签,避免复用重复
    holder.foldersChipGroup.removeAllViews();

    // 添加当前笔记的标签
    for (String folder : foldersForChips) {
        Chip folderChip = new Chip(context);
        folderChip.setText(folder);
        folderChip.setTextSize(8);
        folderChip.setEnsureMinTouchTargetSize(false);
        folderChip.setHeight(40);
        folderChip.setChipMinHeight(10);
        folderChip.setBackgroundColor(Color.TRANSPARENT);
        folderChip.setChipBackgroundColor(null);

        ChipDrawable chipFolderDrawable = ChipDrawable.createFromAttributes(context, null, 0, R.style.Widget_App_Chip);
        folderChip.setChipDrawable(chipFolderDrawable);

        holder.foldersChipGroup.addView(folderChip);
    }

    // 重置标题和内容的可见性,避免复用旧状态
    holder.titleView.setVisibility(View.GONE);
    holder.contentView.setVisibility(View.GONE);
    
    // 处理标题和内容的显示逻辑
    if (n.getTitle() == null || n.getTitle().trim().isEmpty()) {
        holder.contentView.setVisibility(View.VISIBLE);
        holder.contentView.setText(n.getContent());
        holder.contentView.setPadding(20, 0, 20, 0);
    } else if (n.getContent() == null || n.getContent().trim().isEmpty()) {
        holder.titleView.setVisibility(View.VISIBLE);
        holder.titleView.setText(n.getTitle());
        holder.titleView.setPadding(20, 0, 20, 0);
    } else {
        holder.titleView.setVisibility(View.VISIBLE);
        holder.titleView.setText(n.getTitle());
        holder.titleView.setPadding(20, 0, 20, 0);
        
        holder.contentView.setVisibility(View.VISIBLE);
        holder.contentView.setText(n.getContent());
        holder.contentView.setPadding(20, 0, 20, 0);
    }

    // 设置卡片背景色
    if (getItem(position).getBackgroundColor() != null) {
        holder.cardView.setCardBackgroundColor(Color.parseColor(getItem(position).getBackgroundColor()));
    }

    return v;
}

3. 简化主题切换代码

调用AppCompatDelegate.setDefaultNightMode后,系统会自动重建当前Activity以应用新主题,因此不需要手动调用视图刷新方法,可简化代码:

FloatingActionButton fabLight = findViewById(R.id.light);
fabLight.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View view) {
        AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_NO);
        themeChange.setVisibility(View.VISIBLE);

        SharedPreferences settingsPreferences = getApplicationContext().getSharedPreferences("com.example.settings", Context.MODE_PRIVATE);
        settingsPreferences.edit().putInt("Mode", AppCompatDelegate.MODE_NIGHT_NO).apply();
    }
});

额外建议

  • 字符串判空时使用trim().isEmpty(),避免空格导致的误判;
  • 初始化View时使用inflater.inflate(R.layout.row_layout, parent, false)而非传入null,确保布局参数正确应用;
  • 建议使用RecyclerView替代ListView,其复用机制更完善,也更适配现代Android开发需求。

内容的提问来源于stack exchange,提问作者Weronika Materkowska

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.12 10:50:37