When a button is clicked, I'm trying to delete the row. At the very bottom, I call the delete method that I made. However it gives me an error (in the question). I tried making the delete method static, tried everything that android suggested
public class myAdapter extends RecyclerView.Adapter<myAdapter.ViewHolder> {
private List<numbers> mNumbers;
public myAdapter (List<numbers> numbers) {
mNumbers = numbers;
}
#Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.list_slot, parent, false);
ViewHolder vh = new ViewHolder(v);
return vh;
}
#Override
public void onBindViewHolder(ViewHolder holder, int position) {
holder.bindNumbers(mNumbers.get(position));
}
#Override
public int getItemCount() {
return mNumbers.size();
}
public void delete(int position) {
mNumbers.remove(position);
notifyItemRemoved(position);
}
public static class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener{
TextView numberText;
EditText checklistText;
Button deleteButton;
CheckBox checkDisBox;
public ViewHolder(View itemView) {
super(itemView);
numberText = (TextView) itemView.findViewById(R.id.number);
checklistText = (EditText) itemView.findViewById(R.id.editText);
deleteButton = (Button) itemView.findViewById(R.id.deleteButton);
checkDisBox = (CheckBox) itemView.findViewById(R.id.checkBox);
deleteButton.setOnClickListener(this);
}
public void bindNumbers(numbers numbers) {
numberText.setText(numbers.getInt() + "");
}
#Override
public void onClick(View v) {
delete(getAdapterPosition());
}
}
}
EDITED PROBLEM BELOW
#Override
public void onBindViewHolder(ViewHolder holder, int position) {
holder.bindNumbers(mNumbers.get(position));
holder.deleteButton.setOnClickListener(this);
}
public void delete(int position) {
mNumbers.remove(position);
notifyItemRemoved(position);
}
#Override
public void onClick(View v) {
delete(getAdapterPosition());
}
Edit
I just went and implemented this myself, and this is what worked for me.
Create an interface for deleting items
public interface DeleteItem {
void delete(int position);
}
Make your adapter implement this interface
public class myAdapter
extends RecyclerView.Adapter<myAdapter.ViewHolder>
implements DeleteItem {
#Override
public void delete(int position) {
mNumbers.remove(position);
notifyItemRemoved(position);
}
}
Set your viewholder to take a reference to the interface
DeleteItem mDeleteItem;
public ViewHolder(View itemView, DeleteItem deleteItem) {
super(itemView);
mDeleteItem = deleteItem;
...
}
Modify your view holders on click handler
#Override
public void onClick(View v) {
mDeleteItem.delete(getAdapterPosition());
}
Finally when creating your view holder pass it the reference
ViewHolder vh = new ViewHolder(v, this);
Original Answer
A ViewHolder is to save your application from having to find the views inside of list items. It should only contain the myview = itemView.findViewById() type calls and nothing else.
The bindViewHolder() method should contain all the code that uses those views you found in the view holder.
#Override
public void onBindViewHolder(ViewHolder holder, final int position) {
holder.bindNumbers(mNumbers.get(position));
// add listener here
holder.deleteButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
delete(position);
}
}
}
Code hasnt really changed from my question but removing the static keyword really got rid of a lot of my struggles
public class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener{
TextView numberText;
EditText checklistText;
Button deleteButton;
CheckBox checkDisBox;
public ViewHolder(View itemView) {
super(itemView);
numberText = (TextView) itemView.findViewById(R.id.number);
checklistText = (EditText) itemView.findViewById(R.id.editText);
deleteButton = (Button) itemView.findViewById(R.id.deleteButton);
checkDisBox = (CheckBox) itemView.findViewById(R.id.checkBox);
deleteButton.setOnClickListener(this);
}
public void bindNumbers(numbers numbers) {
numberText.setText(numbers.getInt() + "");
}
#Override
public void onClick(View v) {
delete(getAdapterPosition());
}
}
my delete method
public void delete(int position) {
mNumbers.remove(position);
notifyItemRemoved(position);
}
Related
Everything works well and my onClick in my recyclerView is working in getting the positions of my items, but what my design calls for is to be able to click an item of the recyclerView and open up a new activity (as a popover or pop up). I can achieve this but my problems comes with the information I need to display on the popover. The information comes like this inside the activity (inside a Firebase value call)
attributeList.removeAll(attributeList);
for (DataSnapshot child : dataSnapshot.child("Attribute").getChildren()){
Attribute attribute = child.getValue(Attribute.class);
attribute_list newAttributeList = new attribute_list( attribute.Name + ": " + attribute.Value);
attributeList.add(newAttributeList);
}
attributeAdapter = new attribute_list_adapter(attributeList, getContext());
recyclerAttribute.setAdapter(attributeAdapter);
This works perfectly for displaying the information, but there's more then just a "value" and a "name" associated with the click.
Basically when I select an item, I need to get the position of the item clicked (which I have) and compare it to the position inside attributeList so I can call a Firebase call (or pass the data somehow) to the popover to display values from the "Attribute" class (such as Name, Value, Description, and another list (recyclerView).
My recyclerView:
public class attribute_list_adapter extends RecyclerView.Adapter<attribute_list_adapter.ViewHolder> {
private List<attribute_list> listItems;
private Context context;
public attribute_list_adapter(List<attribute_list> listItems, Context context) {
this.listItems = listItems;
this.context = context;
}
#Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View v = LayoutInflater.from(parent.getContext())
.inflate(R.layout.attribute_list, parent, false);
return new ViewHolder(v);
}
#Override
public void onBindViewHolder(ViewHolder holder, int position) {
attribute_list listItem = listItems.get(position);
holder.txtTitle.setText(listItem.getTxtTitle());
}
#Override
public int getItemCount() {
return listItems.size();
}
public class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
public TextView txtTitle;
public ViewHolder(View itemView) {
super(itemView);
itemView.setOnClickListener(this);
txtTitle = (TextView) itemView.findViewById(R.id.txtTitle);
}
#Override
public void onClick(View v) {
}
}
}
This is example:
public class attribute_list_adapter extends RecyclerView.Adapter<attribute_list_adapter.ViewHolder> {
private List<attribute_list> listItems;
private Context context;
public attribute_list_adapter(List<attribute_list> listItems, Context context) {
this.listItems = listItems;
this.context = context;
}
#Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View v = LayoutInflater.from(parent.getContext())
.inflate(R.layout.attribute_list, parent, false);
return new ViewHolder(v);
}
#Override
public void onBindViewHolder(ViewHolder holder, int position) {
holder.itemView.setOnClickListener(new View.onClickListener() {
#Override
public void onClick(View v) {
onItemClickListener.onItemClick(position);
}
});
}
#Override
public int getItemCount() {
return listItems.size();
}
public class ViewHolder extends RecyclerView.ViewHolder {
TextView txtberita;
ImageView imgberita;
TextView txtnama;
public ViewHolder(View itemView) {
super(itemView);
txtnama = (TextView) itemView.findViewById(R.id.txtnama);
txtberita = (TextView) itemView.findViewById(R.id.txtberita);
imgberita = (ImageView) itemView.findViewById(R.id.imgberita);
}
}
public void setOnItemClickListener(OnItemClickListener onItemClickListener){
this.onItemClickListener = onItemClickListener;
}
OnItemClickListener onItemClickListener;
public interface OnItemClickListener{
void onItemClick(int position);
}
}
your Activity. in Oncreate()
public class TestActivity extends AppCompatActivity implements attribute_list_adapter.OnItemClickListener {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_test);
attribute_list_adapter adapter = new attribute_list_adapter(listItems, this);
adapter.setOnItemClickListener(this);
}
#Override
public void onItemClick(int position) {
// code here
}
}
Create an interface something like
public interface OnSingleItemClickListener{
void onSingleItemClick(int position);
}
Then implement it on your ViewHolder like this
public class ViewHolder extends RecyclerView.ViewHolder implements OnSingleItemClickListener {
public ViewHolder(View itemView) {
super(itemView);
}
#Override
void onSingleItemClick(int position){
if(listItems.get(position) == listItems.get(getAdapterPosition)){
// TODO do something here
}
}
now on your OnBindViewHolder inside your adapter you must do this.
holder.setOnClickListener(new View.OnClickListener(){
#Override
public void onClick(View view) {
holder.onSingleItemClick(position);
}
}):
I have a recycler view and I am implementing OnClicklistener inside it. Basically , I have an adapter class called actressadapter and a viewholder class MyViewHolder.I am implementing OnClickListener inside viewholder class to initiate another activity via intent method. My basic data is inside a class called actress which has three variables name,country(both String) and an Id(UUID). I am providing this data that is of actresses to my adapter.Next activity is just displaying the name of actress like abc ,def etc that it retrieves . The fault is that it shows name of only one actress after clicking. For instance if it shows abc ,then for each click it will show abc.Don't know why is this happening because as per code I am passing actressname as an extra .
public class actressadapter extends RecyclerView.Adapter <actressadapter.MyViewHolder> {
private List<Actress>al;
private Actress actress,mActress;
public static final String str="shivam.panwar.actressdetails.actressadapter.str";
public class MyViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
public TextView naam, desh;
public MyViewHolder(View view) {
super(view);
view.setOnClickListener(this);
naam = (TextView) view.findViewById(R.id.name);
desh= (TextView) view.findViewById(R.id.country);
}
#Override
public void onClick(View v) {
Toast.makeText(v.getContext(),"Clicked",Toast.LENGTH_SHORT).show();
Intent intent=new Intent(v.getContext(),Actressview.class);
intent.putExtra(str,actress.getName());
v.getContext().startActivity(intent);
}
public void bindactress(Actress mActress) {
naam.setText(mActress.getName());
desh.setText(mActress.getCountry());
}
}
public actressadapter(List<Actress> al) {
this.al = al;
}
#Override
public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View itemView = LayoutInflater.from(parent.getContext())
.inflate(R.layout.actress_list_row, parent, false);
return new MyViewHolder(itemView);
}
#Override
public void onBindViewHolder(MyViewHolder holder, int position) {
actress =al.get(position);
holder.bindactress(actress);
}
#Override
public int getItemCount() {
return al.size();
}
}
If required any further assist about code please comment.
try this way hope it works...
#Override
public void onBindViewHolder(MyViewHolder holder, int position) {
actress =al.get(position);
holder.bindactress(actress);
holder.naam.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Toast.makeText(context,holder.naam.getText().toString(), Toast.LENGTH_SHORT).show();
Intent intent = new Intent(context,Actressview.class);
intent.putExtra(str,holder.naam.getText().toString());
context.startActivity(intent);
}
});
}
The best way to use the method getLayoutPosition() of adapter class to get the selected item(position).
You have to update your code for better result. Replace your existing code with that.
public class actressadapter extends RecyclerView.Adapter <actressadapter.MyViewHolder> {
private List<Actress>al;
private Actress actress,mActress;
private int itemPosition; // change
public static final String str="shivam.panwar.actressdetails.actressadapter.str";
public class MyViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
public TextView naam, desh;
public MyViewHolder(View view) {
super(view);
view.setOnClickListener(this);
naam = (TextView) view.findViewById(R.id.name);
desh= (TextView) view.findViewById(R.id.country);
}
#Override
public void onClick(View v) {
itemPosition = getLayoutPosition(); // change
Toast.makeText(v.getContext(),"Clicked",Toast.LENGTH_SHORT).show();
Intent intent=new Intent(v.getContext(),Actressview.class);
intent.putExtra(str,al.get(itemPosition).getName()); // change
v.getContext().startActivity(intent);
}
public void bindactress(Actress mActress) {
naam.setText(mActress.getName());
desh.setText(mActress.getCountry());
}
}
public actressadapter(List<Actress> al) {
this.al = al;
}
#Override
public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View itemView = LayoutInflater.from(parent.getContext())
.inflate(R.layout.actress_list_row, parent, false);
return new MyViewHolder(itemView);
}
#Override
public void onBindViewHolder(MyViewHolder holder, int position) {
actress =al.get(position);
holder.bindactress(actress);
}
#Override
public int getItemCount() {
return al.size();
}
}
Hope it will work..
your issue is that you made actress a variable of the Adapte, and it should be of the Holder.
To fix it:
Delete the line:
private Actress actress,mActress;
Change the onBindViewHolder method to:
holder.bindactress(al.get(position))
And make replace your holder class with that:
// holder HAVE TO be static. It's WRONG not doing it static
public static class MyViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
TextView naam, desh;
Actress actress;
public MyViewHolder(View view) {
super(view);
view.setOnClickListener(this);
naam = (TextView) view.findViewById(R.id.name);
desh= (TextView) view.findViewById(R.id.country);
}
#Override
public void onClick(View v) {
Toast.makeText(v.getContext(),"Clicked",Toast.LENGTH_SHORT).show();
Intent intent=new Intent(v.getContext(),Actressview.class);
intent.putExtra(str,actress.getName());
v.getContext().startActivity(intent);
}
public void bindactress(Actress mActress) {
this.actress = mActress;
naam.setText(mActress.getName());
desh.setText(mActress.getCountry());
}
}
I have gotten up to this far:
I have created a boolean variable in my "numbers" object class with a getter and setter. In my bindNumbers method near the bottom of my adapter, i set the checked state of my checkbox. I know that im supposed to now use a on click listener however i dont know how to accomplish this. Can someone give me a beginner friendly explanation on what to do now? All the other answers on the forums are much more advanced and arent helping me.
public class myAdapter extends RecyclerView.Adapter<myAdapter.ViewHolder> {
private List<numbers> mNumbers = Collections.emptyList();
public myAdapter (List<numbers> numbers) {
mNumbers = numbers;
}
#Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.list_slot, parent, false);
ViewHolder vh = new ViewHolder(v);
return vh;
}
#Override
public void onBindViewHolder(ViewHolder holder, final int position) {
holder.bindNumbers(mNumbers.get(position));
}
#Override
public int getItemCount() {
return mNumbers.size();
}
public class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
TextView numberText;
EditText checklistText;
Button deleteButton;
CheckBox checkDisBox;
public ViewHolder(View itemView) {
super(itemView);
numberText = (TextView) itemView.findViewById(R.id.number);
checklistText = (EditText) itemView.findViewById(R.id.editText);
deleteButton = (Button) itemView.findViewById(R.id.deleteButton);
checkDisBox = (CheckBox) itemView.findViewById(R.id.checkBox);
deleteButton.setOnClickListener(this);
}
public void bindNumbers(numbers numbers) {
numberText.setText(numbers.getInt() + "");
checkDisBox.setChecked(numbers.isChecked());
}
#Override
public void onClick(View v) {
mNumbers.remove(getAdapterPosition());
notifyItemRemoved(getAdapterPosition());
}
}
}
I usually add Listeners in the onBindViewHolder() method, i.e.
#Override
public void onBindViewHolder(ViewHolder holder, final int position) {
holder.bindNumbers(mNumbers.get(position));
holder.checkDisBox.setOnClickListener(new OnClickListener({
...
}));
}
edit:
Short help for implementation: In your adapter, add:
public class myAdapter extends RecyclerView.Adapter<myAdapter.ViewHolder> {
private List<numbers> mNumbers = Collections.emptyList();
private SparseBooleanArray mCheckedItems;
#Override
public void onBindViewHolder(ViewHolder holder, final int position) {
holder.bindNumbers(mNumbers.get(position));
boolean checked = mCheckedItems.get(position), false;
holder.checkDisBox.setChecked(checked);
holder.checkDisBox.setOnClickListener(new OnClickListener({
mCheckedItems.put(position, !checked);
}));
}
I am having trouble removing items from RecyclerView. When I click on delete, the item is removed from RecyclerView, but comes back when I open the app again. I'm hoping it is just a minor issue that someone here can point out or direct me to what area to troubleshoot. The removeItem(String item) in bold is what I think is the issue. You can't see it in this post, but it is "not used".
public class RecyclerViewAdapter extends RecyclerView.Adapter<RecyclerViewAdapter.MyViewHolder> {
private List<Grocery> mListData;
private SQLGroceryHelper helper;
RecyclerViewAdapter adapter;
//Adapter's Constructor//
public RecyclerViewAdapter(List<Grocery> mDataList) {
this.mListData = mDataList;
}
//Provide a reference to the views for each contact item//
public class MyViewHolder extends RecyclerView.ViewHolder {
TextView rowItem;
ImageButton purchasedButton;
ImageButton deleteButton;
LinearLayout linearLayout;
public MyViewHolder(View itemView) {
super(itemView);
linearLayout = (LinearLayout) itemView.findViewById(R.id.recycler_row);
rowItem = (TextView) itemView.findViewById(R.id.item_field1);
purchasedButton = (ImageButton) itemView.findViewById(R.id.item_purchased);
deleteButton = (ImageButton) itemView.findViewById(R.id.delete_item);
}
}
//Inflate the view based on the viewtype provided//
#Override
public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
//Create a new view by inflating the row item xml//
View row = LayoutInflater.from(parent.getContext()).inflate(R.layout.recycler_row, parent, false);
//Set the view to the ViewHolder//
MyViewHolder holder = new MyViewHolder(row);
return holder;
}
//Display data at the specified position//
#Override
public void onBindViewHolder(final MyViewHolder holder, final int position) {
holder.rowItem.setText(mListData.get(position).getTextItem());
holder.purchasedButton.setOnClickListener(new View.OnClickListener() {
//Ignore this click for now//
#Override
public void onClick(View v) {
removeItem(position);
}
});
holder.deleteButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
removeItem(position);
}
});
}
public void **removeItem**(String item) {
int position = mListData.indexOf(item);
if (position != -1) {
mListData.remove(item);
notifyItemRemoved(position);
}
}
public void removeItem(int position) {
mListData.remove(position);
notifyItemRemoved(position);
}
#Override
public int getItemCount() {
if (mListData == null) {
return 0;
}
return mListData.size();
}
}
You are removing the data from local object, mListData I guess the original data object remains intact. Remove the data item from the original data object as well
Declare a interface
public interface AdapterCommunication{
void removeStringItem(int position);
}
then in your adapter
private AdapterCommunication mListener;
public void setOnClickListener(AdapterCommunication listener){
mListener = listener;
}
Then from your activity where you initialize the adapter
RecyclerViewAdapter adapter = new RecyclerViewAdapter(list);
adapter.setOnClickListener(new AdapterCommunication{
public void removeStringItem(int position){
list.remove(position);
adapter.notifyDataSetChanged();
}
});
In your adaper,
holder.deleteButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
mListener.remove(position);
}
});
I've a small problem with my RecyclerView. It's well filled by my adapter with some TextViews, an ImageView and some buttons. When there's an OnClick-Event on one of the buttons it modifies a TextView - so far so good but when I'm scrolling some items further another RecyclerView-item is also modified and has the value of the originally modified one.
I tried already to move the setOnClickListener into my ViewHolder but the result was the same.
May be you can help me.
public class MyAdapter extends RecyclerView.Adapter<MyAdapter.ViewHolder> {
// some vars .... and a constructor
#Override
public ViewHolder onCreateViewHolder(ViewGroup viewGroup, int i) {
View view = LayoutInflater.from(mContext).inflate(R.layout.recyclerview_item, viewGroup, false);
return new ViewHolder(view);
}
#Override
public void onBindViewHolder(final ViewHolder viewHolder, final int i) {
// ...
viewHolder.myTextView.setText("clear");
viewHolder.myButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
viewHolder.myTextView.setText("modified");
}
});
// ...
}
#Override
public int getItemCount() {
return mProducts.size();
}
public class ViewHolder extends RecyclerView.ViewHolder {
private TextView productMultibuy;
private Button productAddToShoppingList;
// ...
public ViewHolder(View itemView) {
super(itemView);
myTextView = (TextView) itemView.findViewById(R.id.my_textview);
myButton = (Button) itemView.findViewById(R.id.my_button);
// ...
itemView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
}
});
itemView.setOnLongClickListener(new View.OnLongClickListener() {
#Override
public boolean onLongClick(View v) {
return false;
}
});
}
}
}
Reading from here.
RecyclerView, just the same as ListView and GridView, reuses views whenever possible. That means while you scroll, views that fall off the top are used for the views on the bottom, etc. This greatly improves the memory efficiency and scroll performance. This means if you don't reset all of the state on a new item, you'll see state left over from the last time this view was used.
always reset all the of the state
thanks, but I solved the problem with setTag() and getTag()
public class MyAdapter extends RecyclerView.Adapter {
// some vars .... and a constructor
#Override
public ViewHolder onCreateViewHolder(ViewGroup viewGroup, int i) {
View view = LayoutInflater.from(mContext).inflate(R.layout.recyclerview_item, viewGroup, false);
return new ViewHolder(view);
}
#Override
public void onBindViewHolder(final ViewHolder viewHolder, final int i) {
// ...
}
#Override
public int getItemCount() {
return mProducts.size();
}
public class ViewHolder extends RecyclerView.ViewHolder {
private TextView productMultibuy;
private Button productAddToShoppingList;
// ...
public ViewHolder(View itemView) {
super(itemView);
myTextView = (TextView) itemView.findViewById(R.id.my_textview);
myTextView.setTag(this);
myButton = (Button) itemView.findViewById(R.id.my_button);
myButton.setTag(this);
// ...
myButton.getTag();
myButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
myTextView.getTag();
myTextView.setText(String.valueOf(amount));
}
}
});
}
}
}