[英]How to make single selection work in a nested RecyclerView
对于我们的应用程序,我必须实现一个嵌套的 RecyclerView。 我从 JSON 获得了一个表列表,每个表都有另一个列表,其中包含每个表中的组。 我可以按要求在屏幕上显示所有内容,问题在于选择。
我在屏幕上有 2 个不同的 RecyclerViews,我似乎无法在这种环境中获得单个选择,尤其是在滚动之后。 每个组和每个表都有一个切换按钮,一次只能激活一个。
到目前为止,我已经尝试将 boolean isSelected 放在 Model 上,但这根本没有成功。 我想出的最接近的解决方案是一个助手 class 搜索屏幕上的每个 CompoundButton 并在选择一个时取消选择它们。 问题是这个助手 class 无法获取屏幕外的按钮。
我如何填充 ParentAdapter(在 MainActivity 中):
public void setAdapter(List<Table> tableList)
{
RecyclerView recycler_view_parent = findViewById(R.id.recyclerparent);
LinearLayoutManager manager=new LinearLayoutManager(MainActivity.this);
manager.setOrientation(LinearLayoutManager.HORIZONTAL);
recycler_view_parent.setLayoutManager(manager);
recycler_view_parent.setHasFixedSize(true);
recycler_view_parent.setItemViewCacheSize(tableList.size());
ParentAdapter parentAdapter=new ParentAdapter(tableList,MainActivity.this);
recycler_view_parent.setAdapter(parentAdapter);
}
我如何填充 ChildAdapter(在 ParentAdapter 的 onBindViewHolder 中):
FlexboxLayoutManager manager = new FlexboxLayoutManager(context);
manager.setFlexDirection(FlexDirection.COLUMN);
manager.setJustifyContent(JustifyContent.FLEX_START);
manager.setFlexWrap(FlexWrap.WRAP);
manager.setAlignItems(AlignItems.BASELINE);
holder.recycler_view_child.setLayoutManager(manager);
holder.recycler_view_child.setHasFixedSize(true);
adapter = new ChildAdapter(tableList, tableList.get(position).getGroups(), context);
holder.recycler_view_child.setAdapter(adapter);
所需的 output 一次只能切换 1 个表或组(总共,不是每个 RecyclerView 中的一个),并且 state 在滚动/设备旋转后应该相同)。
在过去的几天里,我对这个主题进行了很多研究,但我似乎找不到嵌套 RecyclerView 的工作示例,其中单选两个 RV。
那么有人知道如何解决这个问题吗? 我认为最大的问题是告诉家长孩子中的按钮被切换,反之亦然。
我认为对于 ParentAdapter 它应该是这样的:
@Override
public void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, final int position) {
final Table table = tablelist.get(position);
ViewHolder viewHolder = (ViewHolder) holder;
if (table.isTableSelected()) {
viewHolder.toggletable.setChecked(true);
lastToggled = position;
} else {
viewHolder.toggletable.setChecked(false);
}
viewHolder.toggletable.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
@Override
public void onCheckedChanged(CompoundButton compoundButton, boolean b) {
if (b) {
table.setTableSelected(true);
// notify ChildAdapter and group.setGroupSelected(false)
if (lastToggled >= 0) {
tablelist.get(lastToggled).setTableSelected(false);
// notify ChildAdapter and group.setGroupSelected(false)
notifyItemChanged(lastToggled);
}
lastToggled = position;
} else {
table.setTableSelected(false);
}
}
});
}
提前致谢。
更新:自己设法想出了一个解决方案,虽然 100% 肯定,但不是最好的方法。
首先,实现 Greenrobots EventBus:
implementation 'org.greenrobot:eventbus:3.1.1'
现在在您持有两个 RecyclerViews 的 Activity 中注册事件侦听器:
@Override
protected void onStart() {
super.onStart();
EventBus.getDefault().register(this);
}
并订阅 2 种方法。 一种用于家长活动,一种用于儿童活动。 每次选择项目时都会触发此方法!
@Subscribe(threadMode = ThreadMode.MAIN)
public void onParentEventClicked(ParentAdapter.ParentEvent event) {
// to access the inner adapter here you must set it to public in the ParentAdapter(public ChildAdapter adapter;)
adapter.adapter.deSelectChild();
}
@Subscribe(threadMode = ThreadMode.MAIN)
public void onChildEventClicked(ChildAdapter.ChildEvent event) {
// normal ParentAdapter reference(ParentAdapter adapter;)
adapter.deSelectParent();
}
在 ParentAdapter 中创建一个取消选择所有父项的方法和一个 static class 来触发事件:
public void deSelectParent()
{
for (int i=0;i<data.size();i++)
{
data.get(i).setSelected(false);
}
notifyDataSetChanged();
}
public static class ParentEvent {
View view;
int position;
}
在您的 ChildAdapter 中创建一个取消选择所有子项的方法和一个 static class 来触发事件:
public void deSelectChild()
{
for (int i=0;i<data.size();i++)
{
datachild.get(i).setSelected(false);
}
notifyDataSetChanged();
}
public static class ChildEvent {
View view;
int position;
}
现在在 Parent 和 Child onBindViewHolders 中,您的模型需要类似的逻辑:
if (item.isSelected()) {
holder.yourbutton.setChecked(true);
} else {
holder.yourbutton.setChecked(false);
}
holder.yourbutton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
ParentEvent event = new ParentEvent();
event.view = holder.yourbutton;
event.position = position;
EventBus.getDefault().post(event);
if (holder.yourbutton.isChecked()) {
for (int i = 0; i < data.size(); i++) {
data.get(i).setSelected(false);
}
data.get(position).setSelected(true);
} else {
data.get(position).setSelected(false);
}
notifyDataSetChanged();
}
});
差不多就是这样,每次单击 ParentItem 都会触发 ChildAdapter 的取消选择方法,反之亦然。 由于 notifyDataSetChanged() 的使用率很高,我建议使用这一行来摆脱闪烁:
recycler_view_parent.setItemAnimator(null);
有什么问题告诉我!
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.