-2

我有一个recyclerview它的项目包含textViewswitchCompat。在同一个活动中,我还有一个textView包含数值的。任务是当switchCompat打开上面recyclerview包含数值的文本视图时,应该增加recyclerview项目中的值textview。我已经这样做了,但是当在后面滚动recyclerviewswitchCompat默认状态并且数字的值返回textview到它的旧值时,

有什么帮助吗?

我很抱歉现在无法发布部分代码,我会尽快发布,我现在才发布它,以防有人之前通过类似的事情

谢谢

4

2 回答 2

0

Android 中回收器视图或任何适配器视图的关键是让适配器使您的模型适应视图。在您的情况下,您的视图是 a TextViewplus a Switch,因此您的适配器必须使某些模型适应该视图。在这种情况下,我会选择一个像这样的简单模型:

class ItemModel {
  String text;
  boolean on;
}

为简单起见,我省略了 getter 和 setter

该模型包含一个text反映文本视图中文本的字符串和一个on反映开关状态的布尔值。当为真时,开关被选中,当它为假时,它被取消选中。

有很多方法可以表示这个模型。我选择了这个,你可以选择其他的。关键是,您需要将状态保存在某处,这就是我所说的模型 - 视图模型。

现在让我们构建一个适配器,它可以做两件事——当点击开关时更新模型并告诉活动开关改变了状态。这是执行此操作的一种方法:

public class ItemsAdapter extends 
  RecyclerView.Adapter<ItemsAdapter.ViewHolder> {
    @NonNull
    private final List<ItemModel> itemModels;
    @Nullable
    private OnItemCheckedChangeListener onItemCheckedChangeListener;

    ItemsAdapter(@NonNull List<ItemModel> itemModels) {
        this.itemModels = itemModels;
    }

    @NonNull
    @Override
    public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
        return new ViewHolder(LayoutInflater.from(parent.getContext())
                .inflate(R.layout.item, parent, false));
    }

    @Override
    public void onBindViewHolder(@NonNull final ViewHolder holder, int position) {
        ItemModel item = itemModels.get(position);
        holder.text.setText(item.text);
        holder.switchCompat.setChecked(item.on);

        // Make sure we update the model if the user taps the switch
        holder.switchCompat.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
            @Override
            public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
                int adapterPosition = holder.getAdapterPosition();

                ItemModel tapped = itemModels.get(adapterPosition);
                itemModels.set(adapterPosition, new ItemModel(tapped.text, isChecked));

                if (onItemCheckedChangeListener != null) {
                    onItemCheckedChangeListener.onItemCheckedChanged(adapterPosition, isChecked);
                }
            }
        });
    }

    @Override
    public void onViewRecycled(@NonNull ViewHolder holder) {
        super.onViewRecycled(holder);

        holder.switchCompat.setOnCheckedChangeListener(null);
    }

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

    public void setOnItemCheckedChangeListener(@Nullable OnItemCheckedChangeListener onItemCheckedChangeListener) {
        this.onItemCheckedChangeListener = onItemCheckedChangeListener;
    }

    interface OnItemCheckedChangeListener {
        /**
         * Fired when the item check state is changed
         */
        void onItemCheckedChanged(int position, boolean isChecked);
    }

    class ViewHolder extends RecyclerView.ViewHolder {
        TextView text;
        SwitchCompat switchCompat;

        ViewHolder(View itemView) {
            super(itemView);
            text = itemView.findViewById(R.id.item_text);
            switchCompat = itemView.findViewById(R.id.item_switch);
        }
    }
}

有很多东西要消化,但让我们专注于重要的部分 - 方法onBindViewHolder。前 3 行是视图的经典循环。我们在正确的位置抓取模型并在视图中设置与模型属性相对应的元素。

然后它变得更有趣。我们设置 aOnCheckedChangeListener以在每次开关更改状态时更新模型和活动。前 3 行更改适配器中的模型,其余使用自定义接口OnItemCheckedChangeListener通知侦听器有关开关更改。重要的是要注意在方法内部OnCheckedChangeListener你不应该再使用position,而是使用holder.getAdapterPosition. 这将为您提供适配器数据列表中的正确位置。

由于现在适配器在数据列表中始终具有正确的模型,因此每次onBindViewHolder调用该方法时,适配器都知道如何设置视图。这意味着在滚动和回收视图时,它将保留data列表内模型中每个项目的状态。

OnCheckedChangeListener当视图被回收时删除 - 很重要onViewRecycled。这样可以避免在适配器switchCompat设置onBindViewHolder.

以下是活动的示例:

public class MainActivity extends AppCompatActivity {
    private int count = 0;

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

        List<ItemModel> data = new ArrayList<>();

        for (int i = 1; i <= 100; i++)
            data.add(new ItemModel("Item " + i, false));

        ItemsAdapter adapter = new ItemsAdapter(data);

        ((RecyclerView) findViewById(R.id.recyclerview)).setAdapter(adapter);

        final TextView countTextView = findViewById(R.id.count);

        drawCount(countTextView);

        adapter.setOnItemCheckedChangeListener(new ItemsAdapter.OnItemCheckedChangeListener() {
            @Override
            public void onItemCheckedChanged(int position, boolean isChecked) {
                if (isChecked)
                    count++;
                else
                    count--;

                drawCount(countTextView);
            }
        });
    }

    private void drawCount(TextView countTextView) {
        countTextView.setText(String.valueOf(count));
    }
}

这段代码是为了演示这个想法,而不是遵循 :) 无论如何,我们设置所有初始状态,然后设置自定义侦听OnItemCheckedChangeListener器以更新 Activity 中的文本视图。

布局文件在这里不应该相关,但是您可以想象活动有一个带有 id 的文本视图count和一个带有 id 的回收器视图recyclerview

希望这可以帮助

于 2018-05-06T21:50:36.843 回答
0

将以下方法添加到适配器后,它为我解决了:

@Override
public int getItemViewType(int position) {

    return position;
}
于 2019-08-16T20:52:40.007 回答