Android 中回收器视图或任何适配器视图的关键是让适配器使您的模型适应视图。在您的情况下,您的视图是TextView 加上Switch,因此您的适配器必须使某些模型适应此视图。在这种情况下,我会选择这样一个简单的模型:
class ItemModel {
String text;
boolean on;
}
为了简单起见,我省略了 getter 和 setter
此模型包含一个字符串text,它反映了您的文本视图中的文本,以及一个布尔值on,它反映了开关的状态。当为真时,开关被选中,当它为假时,它被取消选中。
有很多方法可以表示这个模型。我选择了这个,你可以选择其他的。关键是,您需要将状态保存在某处,这就是我所说的模型 - 视图模型。
现在让我们构建一个适配器,它可以做两件事 - 当点击开关时更新模型并告诉 Activity 开关改变了状态。这是执行此操作的一种方法:
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 行是视图的经典循环。我们在正确的位置抓取模型,并在视图中设置与模型属性对应的元素。
然后它变得更有趣。我们设置一个OnCheckedChangeListener 来在每次开关改变状态时更新模型和活动。前 3 行更改适配器中的模型,其余使用自定义接口 OnItemCheckedChangeListener 通知监听器有关开关更改。需要注意的是,在方法@987654330@ 中,您不应再使用position,而应使用holder.getAdapterPosition。这将为您提供适配器数据列表中的正确位置。
由于现在适配器在数据列表中始终拥有正确的模型,因此每次调用方法onBindViewHolder 时适配器都知道如何设置视图。这意味着在滚动和回收视图时,它将保留data 列表中模型中每个项目的状态。
当视图被回收时删除OnCheckedChangeListener 很重要 - onViewRecycled。这样可以避免适配器在onBindViewHolder 中设置switchCompat 的值时弄乱计数。
以下是活动的示例:
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 以更新活动中的文本视图。
布局文件在这里不应该相关,但您可以想象,活动有一个 ID 为 count 的文本视图和一个 ID 为 recyclerview 的回收器视图。
希望对你有帮助