I'm faced with strange problem. I've made a ListView, populated it with adapter and everything works fine until I want to delete any item. After I press confirmation button view really deletes, but text inside of it doesn't changes on the text from next view.
For example I've got such items in ListView:
Item 1
Item 2
Item 3
When I press delete Item 2, Item 3 disappears but text in view on position 2 doesn't changes. I know that Item 2 was deleted as I use database for storing data and after app restart everything show as expected. I suppose that problem is in reuse of views by View Holder but I can't figure out how to change text in second view.
Here is code that doesn't work (at least I think that problem is here)
confirmDeleteButton.setOnClickListener(new View.OnClickListener() {//this button is in dialog
#Override
public void onClick(View v) {
DBController.init(context).delete("main", "id=" + item.get(position).getId(), null);//deleting item from database
remove(getItem(position)); //removing view from adapter
notifyDataSetChanged(); //notifying adapter
dialog.dismiss(); //closing dialog
}
});
SOLUTION
Just use RecyclerView instead of ListView.
First you have to remove the data from adapter like adapter.remove(adapter.getItem(position));
and then call notifyDataSetChanged()
don't use the get position to delete the datas, first setid() to confirm buttons like, confirmDeleteButton.setid(position) used in getview adapter class.
then remove the id based on getid() like:
DBController.init(context).delete("main", "id=" + item.get(v.getid()).getId(), null);//deleting item from database
remove(v.getid()); //removing view from adapter
Is better if you use:
adapter.notifyItemRangeRemoved(int positionStart, int itemCount)
adapter.notifyItemRemoved(int position)
More info: https://developer.android.com/reference/android/support/v7/widget/RecyclerView.Adapter.html
Related
I have a RecyclerView, it will show close icon in the last item view,
but when I add new data in the Adapter,
the old item does not refresh their view, it just adds new item view in the RecyclerView.
How could I update the old last item view?
I tried to use notifyItemChanged(int) but it didn't work.
for(int i = lastPosition(); i < mAdapter.getItemCount() - 1; i++) {
mAdapter.notifyItemChanged(i);
}
Add below code after adding item in listview...
mAdapter.notifyDataSetChanged();
you can call this whenever you want to update the item of recyclerview list
mAdapter.notifyItemChanged(ITEM_INDEX);
//ITEM_INDEX IS THE POSITION
Thanks for your help, I have find the problem
the problem is not in adapter, it in my viewholder
my xml layout show the icon in default,
when it is the last item ,I set the icon Gone
public static void hideBottomLine(BaseViewHolder h) {
h.line.setVisibility(View.GONE);
}
when i notifyItemChanged it ,I thought it will show default, but not! So when I add method
public static void showLine(BaseViewHolder h) {
h.line.setVisibility(View.VISIBLE);
}
now it work...
I have a Listview and a custom adapter, I am trying to change swap two arraylist items inside the apdapter in onclick of button as listview item.
My code is
viewHolder.btnUp.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
Integer pos = (Integer) v.getTag();
if (!pojos.get(pos).equals(pojos.get(0))) {
Collections.swap(pojos, pos, pos - 1);
notifyDataSetChanged();
}
}
});
But I can not see the changes in listview, though arraylist has modified, but UI changes has not reflected.
Thats because your adapter has already finished its work. The adapter will turn the data into views and pass those views to the list view. Notice that changing the order in the original collection wont change the views inside the list view. What you could do is remove the views and add them at the correct positions. Get access to the list view by doing viewHolder.getParent()
If pojos is a local final variable, make sure the one the adaptor uses still points to the same collection otherwise the anonymous class will swap 2 elements in an collection that's not being used.
I would recommend to pass the arrayList to the adapter again and setting adapter to the list view, all this before the notifyDataSetChanged(); method.
I am working with a ListView trying to add/delete items. The addition bit was fairly easy, the removing though is proving to be trickier.
I was thinking to use a multiple choice list, but to start with something simpler I chose a single choice mode just to test it out.
I have an array of strings containing the items, an array adapter to notify when Data has changed.
expenseAdapter=new ArrayAdapter<String>(this,
android.R.layout.simple_list_item_single_choice,
android.R.id.text1,
expenseList);
myListView.setAdapter(expenseAdapter);
myListView.setOnItemClickListener(new OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View item, int position,
long index) {
((ListView)parent).setItemChecked(position, true);
item.setSelected(true);
}
});
I have also added a listener for the item onClick Event. Visually the item gets selected/deselected the issue is when I click the button which triggers the deletion of the item the selected index in the list is always -1 although the item appears to be selected.
Delete button with onClick event
public boolean doDelete(View view)
{
ListView myListView= (ListView)findViewById(R.id.list);
String s=(String)myListView.getSelectedItem();
expenseList.remove(s);
expenseAdapter.notifyDataSetChanged();
return true;
}
Any ideas what is happening or what I'm doing wrong?
use this
xmlfile : https://www.dropbox.com/s/eky9zb275mgt4py/activity_list__addand_delete.xml
javaFile : https://www.dropbox.com/s/idqyyosbutgqqbs/List_AddandDelete.java
your selection ( focus ) is removed when ever you will shift your focus to button .
I have seen your code and understand that problem, you are getting -1 index when you are removing item from List because that item is not existing in that list so change your code please try this.
I changed getSelectedItem() to getSelectedItemId() here it will return selected item id instead of Item so you can remove that item from List based on item id which will be the Index of item in List.
public boolean doDelete(View view)
{
ListView myListView= (ListView)findViewById(R.id.list);
long id = myListView.getSelectedItemId();
expenseList.remove(id);
expenseAdapter.notifyDataSetChanged();
return true;
}
Hope it will help you.
I'm developing an android application using eclipse. I have a listview and each row of this contains an EditText. When I click on an EditText I want two things to do.
1: Reload all the EditText with texts from my data array.
2: Set the text of the clicked EditText to a constant string(say "0").
For this I used the below onclicklisetner for EditText.
myEdittext.setOnClickListener(new View.OnClickListener()
{
#Override
public void onClick(View v)
{
adapter.notifyDataSetChanged();//adapter is my arrayadapter of the listview
EditText clickedText = (EditText)v;
clickedText.setText("0");
}
});
As you can see I'm using 'notifyDataSetChanged' method to reload the EditTexts in the listview and 'setText' method to set the clicked EditText's text to "0".
But the 'setText' method is not working. If I comment the line 'adapter.notifyDataSetChanged()' the 'setText' method is working.
I also tried to do this by calling the setText method after a delay(to check if the notifyDataSetChanged is starting a new thread) but failed.
How can I make both the methods to work in my onClick method.
Thanks in Advance.
You can do it using another approach.
You might be setting the ListView adapter using an ArrayList say mList.
Now in the onItemClick listener of the list view you get the position of the item clicked in the ListView. In the onClick() set the value 0 at that position of the arrayList eg mList.set(position, 0). and then call notifyDataChanged()
try :
So the reason for such behavior is that when you call adapter.notifyDataSetChanged(), there is a good chance that your View V is recycled hence it no longer refers to the one that is clicked. What you really want to do is to change the list so that when notifyDataSetChanged is called then all the values will be loaded accordingly.
Please share your adapter code.
myEdittext.setOnClickListener(new View.OnClickListener()
{
#Override
public void onClick(View v)
{
//adapter is my arrayadapter of the listview
//EditText clickedText = (EditText)v;
//clickedText.setText("0");
//Do some thing to change the adapter data list.
adapter.notifyDataSetChanged();
}
});
So I have a spinner (spinner2 here) which is populated via an ArrayAdapter from an SQLite table. On selecting an item I want it
deleted from the DB
deleted from the spinner
The code below actually works. Except when the spinner has only one item. When that happens
it seems onItemSelected is not called at all.
I get the following LogCat
10-01 22:30:55.895: WARN/InputManagerService(1143): Window already focused, ignoring focus gain of: com.android.internal.view.IInputMethodClient$Stub$Proxy#45a06028
Oh and when two items are populating the spinner, spinner.getcount() shows two items, so it's not some strange case of the system thinking the spinner is empty or something like that.
This is the code:
public class SpinnerItemSelectListener implements OnItemSelectedListener {
public void onItemSelected(AdapterView<?> parent, View view, int pos, long id) {
if(parent == spinner2){
if(autoselected){
autoselected=false;
}
else{
//uniqvalarray is the arraymade from pulling data from SQLite and populaitng array adapter
Integer i = uniquevalarray.get(pos);
deleteRow(i);//deletes the row from the database and repopulates the above array.
autoselected=true;//just a boolean to stop autoslecting in onCreate()
//makeAlert(i);initially wanted to make alert box.
loadSpinner2();//reloads the spinner with new data
}
}
}
public void onNothingSelected(AdapterView parent) {
//TODO
}
}
The spinner runs this way : Only fire when you change the selected item . If you dont change that element , cause its the only one that exist , it can't change .
The solution i think you must use is using a button next to the spinner to throw the delete funcions.
You must think that Spinner is not made to be with an unique element , cause only changes usually when you change the selected one . then the natural solution can be that .