Reputation: 720
To summarize my app fragment, I have a RecyclerView
who's size is dynamic, and relative to a ViewModel
variable (when this variable changes, RecyclerView's list of items grows or shrinks respectively).
Each row has a couple buttons. Each of those buttons has a OnClickListener
on it. (When clicked, the button disappears).
Problem: When a button is clicked, not only that button disappears, but every additional multiple of 7 (index-wise) disappears as well.
For example: You press a button in row 1, and the exact same thing happens in row 8, 15, and 22, even though you only clicked row 1.
I am currently passing a listener through my fragment's onViewCreated
method to a private listener variable in the adapter (listener's set in the constructor).
I'll show the relavent bits of my Fragment and Adapter:
Fragment:
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);
}
}
Adapter:
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;
}
}
Upvotes: 1
Views: 2078
Reputation: 1448
You are passing to your onClick listener the viewHolder
while doing that
myButton.setTag(this); // this = viewHolder
The viewHolder is a recyclable view. So, you cannot treat this view as a unique item view. Remember that a viewHolder is created to be reused by other items. That's why you see your action reflected in other items.
The solution:
Set to your tag, not the viewHolder
, but the item position.
Then, in your Data
structure, you should add variables to remember which buttons should be displayed or not.
class Data {
...
String text;
boolean btnVisible;
}
In View.OnClickListener
you should set these variables values.
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
}
}
Then, in your onBindViewHolder
you should set the button text and the button visibility state depending on variables in Data
structure.
@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);
}
Upvotes: 2
Reputation: 997
please use below snip for get exact position, setTag(); to the View and then on Click time get that tag value using getTag(); for perfect position.
myViewHolder.ivVoiceThumb.setTag(pos);
myViewHolder.ivVoiceThumb.setOnClickListener(view -> {
int getPos = (int)view.getTag();
});
Upvotes: 2