RecyclerView项目上的事件一次影响多行,而不是某一行

时间:2019-04-30 04:36:40

标签: android android-recyclerview event-listener

总结一下我的应用程序片段,我有一个RecyclerView,它的大小是动态的,并且相对于ViewModel变量(当此变量更改时,RecyclerView的项目列表分别增大或缩小)。

每行都有几个按钮。每个按钮上都有一个OnClickListener。 (单击后,按钮消失)。

问题: 单击一个按钮时,不仅该按钮消失,而且每增加7的倍数(索引方式)也消失。

例如:即使您只单击了第1行,您在第1行中按了一个按钮,第8、15和22行也发生了完全相同的事情。

我当前正在通过片段的onViewCreated方法将侦听器传递给适配器中的私有侦听器变量(在构造函数中设置侦听器)。

我将展示我的片段和适配器的相关部分:

片段:

public class MyFragment extends Fragment {
    private MyModel model;
    private ArrayList<Data> dataList;
    private int numberOfDataItems;

    private RecyclerView content;
    private RecycleAdapter adapter;

    private View.OnClickListener onItemClickLIstener = new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            RecyclerAdapter.ViewHolder viewHolder = (RecyclerAdapter.ViewHolder) view.getTag();

            // This is the buggy bit
            viewHolder.myButton.setVisibility(View.GONE);

            int position = viewHolder.getAdapterPosition();
            Data data = dataList.get(position);
            // TODO: eventually do some logic here with the data
        }
    }

    @Override
    public void onViewCreated(@NonNull View view, Bundle savedInstanceState) {
        content = view.findViewById(R.id.content);
        model.createDataList(numberOfDataItems);
        dataList = model.getDataList();

        adapter = new RecycleAdapter(dataList);
        content.setAdapter(adapter);
        content.setLayoutManager(new LinearLayoutManager(getContext()));

        adapter.setOnItemClickListener(onItemClickListener);
    }
}

适配器:

public class RecycleAdapter extends RecyclerView.Adapter<RecycleAdapter.ViewHolder> {
    private List<Data> dataList;
    private View.OnClickListener onItemClickListener;

    public class ViewHolder extends RecyclerView.ViewHolder {
        public Button myButton;

        public ViewHolder(View itemView) {
            super(itemView);

            myButton = itemView.findViewById(R.id.myButton);
            myButton.setTag(this);
            myButton.setOnClickListener(onItemClickListener);
        }
    }

    @Override
    public RecycleAdapter.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        Context conext = parent.getContext();
        LayoutInflater inflater = LayoutInflater.from(context);

        View DataView = inflater.inflate(R.layout.data_layout, parent, false);
        return new ViewHolder(dataView);
    }

    @Override
    public void onBindViewHolder(@NonNull RecycleAdapter.ViewHolder viewHolder, int position) {
        Data data = dataList.get(position);
        // Do stuff with data

        myButton.setText(data);
    }

    public void setOnItemClickListener(View.OnClickListener itemClickListener) {
        onItemClickListener = itemClickListener;
    }
}

2 个答案:

答案 0 :(得分:2)

请使用以下代码获取确切位置, setTag();到视图,然后在单击时使用getTag()获得该标签值; 以获得完美的位置。

    myViewHolder.ivVoiceThumb.setTag(pos);
    myViewHolder.ivVoiceThumb.setOnClickListener(view -> {
        int getPos = (int)view.getTag();
    });

答案 1 :(得分:2)

您正在将viewHolder传递给onClick侦听器

   myButton.setTag(this);  // this = viewHolder

viewHolder是可回收的视图。因此,您不能将此视图视为唯一的项目视图。 请记住,已经创建了一个viewHolder以供其他项目重用。这就是为什么您看到自己的行为反映在其他项目上的原因。

解决方案:

设置为标签,而不是viewHolder,而是项目的位置。 然后,在Data结构中,应添加变量以记住应显示或不显示哪些按钮。

class Data {
    ...
    String text;
    boolean btnVisible;
}

View.OnClickListener中,您应该设置这些变量值。

private View.OnClickListener onItemClickLIstener = new View.OnClickListener() {
    @Override
    public void onClick(View view) {
        int position =  (int)view.getTag();
        Data data = dataList.get(position);
        data.btnVisible = false;
        adapter.notifyDataSetChanged();
        // TODO: eventually do some logic here with the data
    }
}

然后,在onBindViewHolder中,应根据Data结构中的变量设置按钮文本和按钮可见性状态。

@Override
public void onBindViewHolder(@NonNull RecycleAdapter.ViewHolder viewHolder, int position) {
    Data data = dataList.get(position);
    // Do stuff with data

    myButton.setText(data.text);
    myButton.setVisibility(?data.btnVisible:VISIBLE:GONE);
}