I create a listview in Android. My listview data is from sqlite database. When user click the item on the list. Alert dialog to delete confirmation will appear.
this is my code to delete from list:
list.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view,int position, long id) {
AlertDialog.Builder alertDialog = new AlertDialog.Builder(todaycode.this);
alertDialog.setTitle("Delete from list");
alertDialog.setMessage("Are you sure to delete?");
final int del_position=position;
alertDialog.setPositiveButton("Yes", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog,int which) {
//delete from database
mDb.deleteContact(list_food.get(+ del_position).getId());
//reload
final ArrayList<food_object> list_food = mDb.getAllfood();
final ListView list;
final String[] food_name = new String[list_food.size()];
for(int i=0;i<list_food.size();i++){
food_name[i]=list_food.get(i).getName();}
Integer[] imageId = {
R.drawable.image1,};
final customlist adapter = new customlist(todaycode.this, food_name, imageId);
list=(ListView)findViewById(R.id.listToday);
list.setAdapter(adapter);
adapter.notifyDataSetChanged();
}
});
and this is my code to delete from my database in DBAdapter:
public boolean deleteContact(int id)
{
return db.delete(TABLE_NAME, COL_ID + "=" + id, null) > 0;
}
this code is work. but sometimes user can't delete an item from the list until they reload this activity (move to other activity and back). The Alert dialog is appear, but after user click "Yes" there's nothing happen.
this only happen sometime. And only occure in one item on the list, so if user choose other item on the list to delete, it's still working. does anybody knows why this is happen?
EDITED
after many try, I conclude that the error (the item can't deleted) always started after user delete the second item (user deleting consecutively), and I'm still no idea why this is happen
this is my DBAdapter code, I simplified it See the Code
this is my customlist code See the Code
The problem is that you probably use autoincrement id in your table. When you get the id from the setOnItemClick it's actually the index of the item and not the id. So when you delete one at index 3 that id will be deleted and next time you want to delete at same index there won't be an item whit that id.
put this listener it will work then bro..!
alertDialog.setPositiveButton("Yes", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog,int which) {
//delete from database
mDb.deleteContact(list_food.get(+ del_position).getId());
//reload
final ArrayList<food_object> list_food = mDb.getAllfood();
final ListView list;
final String[] food_name = new String[list_food.size()];
for(int i=0;i<list_food.size();i++){
food_name[i]=list_food.get(i).getName();}
Integer[] imageId = {
R.drawable.image1,};
final customlist adapter = new customlist(todaycode.this, food_name, imageId);
list=(ListView)findViewById(R.id.listToday);
list.setAdapter(null);
list.setAdapter(adapter);
}
});
Related
I used custom adapter for viewing listview. I tried to define my variables in adapter class but it didnt work. I find a temporary solution using invisible textview for this but i need to solve this problem. How can I overcome this?
Edit 1>
I have a column named date and this column contains datas like 20180723182036 and i grab this data to a list. I want to place this to listview as a variable and i will use this variable later.
My temporary solution is:
I have a code like that in database:
public ArrayList<SimpleNoteItem> getAllData() {
openDatabase();
ArrayList<SimpleNoteItem> newList = new ArrayList<>();
String[] columns = {KEY_ROWTITLE, KEY_ROWCONTENT, KEY_ROWDATE, KEY_ROWSTRDATE};
Cursor cs = db.query(DB_TABLE_NORMAL, columns, null, null, null, null, null);
while(cs.moveToNext()){
SimpleNoteItem allData = new SimpleNoteItem(cs.getString(0), cs.getString(1), cs.getLong(2), cs.getString(3));
newList.add(allData);
}
Collections.reverse(newList);
Log.d(LOGDB, "GETALLDATA STRUCTURE WORKS WELL!");
return newList;
}
Listview longclick constructor is this:
simpleNotesDisplay.setOnItemLongClickListener(new AdapterView.OnItemLongClickListener() {
#Override
public boolean onItemLongClick(AdapterView<?> parent, View view, int position, final long id) {
Log.d(TAG, "LONG CLICKED " + position + " ITEM!");
//THIS AREA WILL BE EDITED FOR MORE ANDROID VERSION SUPPORT
AlertDialog.Builder builder;
final TextView getInvisibleDate = (TextView) view.findViewById(R.id.tv_date_invisible);
builder = new AlertDialog.Builder(NotesActivity.this, android.R.style.Theme_Material_Dialog_Alert);
builder.setTitle("Delete?")
.setMessage("Do you want to send this note to hell?")
.setPositiveButton("Yes", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
db.deleteSimpleNote(getInvisibleDate.getText().toString());
Log.d(TAG, "DELETING SUCCESSFUL ON ID = " + id + "!!!");
NotesActivity.this.recreate();
}
})
.setNegativeButton("No", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
//empty
}
})
.show();
return true;
}
});
}
And at least my invisible date:
<TextView
android:id="#+id/tv_date_invisible"
android:layout_width="0dp"
android:layout_height="0dp"
android:text="TextView"
android:visibility="invisible"
tools:layout_editor_absoluteX="351dp"
tools:layout_editor_absoluteY="65dp" />
i hope it can help!
you should better to explain more about what you want but:
1)if you want to show some data in listview you most have a list of objects that each one has its data.
2)if you want to show different data in each row of listview then you most fill different data in each object of your list
3) if you want to show different view of each listviews row you most at first define different xml layouts and in your adapter where you define infelater you can use if else statment to decide which layout shows to witch row. below links will help you
Android ListView with different layouts for each row
https://www.javacodegeeks.com/2014/08/android-listview-with-multiple-row-layout.html
I found a different solution for that>>
I grab all data from database with this code:
public ArrayList<SimpleNoteItem> getAllData() {
openDatabase();
ArrayList<SimpleNoteItem> newList = new ArrayList<>();
String[] columns = {KEY_ROWTITLE, KEY_ROWCONTENT, KEY_ROWDATE, KEY_ROWSTRDATE};
Cursor cs = db.query(DB_TABLE_NORMAL, columns, null, null, null, null, null);
while(cs.moveToNext()){
SimpleNoteItem allData = new SimpleNoteItem(cs.getString(0), cs.getString(1), cs.getLong(2), cs.getString(3));
newList.add(allData);
}
Collections.reverse(newList);
Log.d(LOGDB, "GETALLDATA STRUCTURE WORKS WELL!");
return newList;
}
And in another activity i grab this list with this and then initialized it:
private ArrayList<SimpleNoteItem> getList = new ArrayList<>();
getList = db.getAllData();
initialize should be in onCreate method.
And then i used that data:
simpleNotesDisplay.setOnItemLongClickListener(new AdapterView.OnItemLongClickListener() {
#Override
public boolean onItemLongClick(AdapterView<?> parent, View view, final int position, final long id) {
Log.d(TAG, "LONG CLICKED " + position + " ITEM!");
//THIS AREA WILL BE EDITED FOR MORE ANDROID VERSION SUPPORT
AlertDialog.Builder builder;
builder = new AlertDialog.Builder(NotesActivity.this, android.R.style.Theme_Material_Dialog_Alert);
builder.setTitle("Delete?")
.setMessage("Do you want to send this note to hell?")
.setPositiveButton("Yes", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
db.deleteSimpleNote(String.valueOf(getList.get(position).getSimpleNoteDate()));
Log.d(TAG, "DELETING SUCCESSFUL ON ID = " + id + "!!!");
NotesActivity.this.recreate();
}
})
.setNegativeButton("No", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
//empty
}
})
.show();
return true;
}
});
I have a ListView with some items and in each item there is a ImageButton for deleting this item.
The method for deleting the item is inside an ArrayAdapter which uses a view holder.
//ALERT DIALOG FOR DELETE
AlertDialog.Builder builder = new AlertDialog.Builder(getContext());
builder.setTitle("Delete All?");
builder.setNegativeButton("No",
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog,int which)
{
dialog.dismiss();
}
});
builder.setPositiveButton("Yes",
new DialogInterface.OnClickListener()
{
public void onClick(DialogInterface dialog, int which)
{
mHelper.deleteAll(gmid,true); //DELETE ITEM
remove(getItem(position)); //REMOVE ITEM FROM LIST
notifyDataSetChanged();
TextView txtGameCount = (TextView) ((Activity)getContext()).findViewById(R.id.txtGamesCount);
int GamesCount = mHelper.getGamesCount(tmid); //GET COUNT OF ITEMS
txtGameCount.setText(String.valueOf(GamesCount)); //SET TEXT WITH NEW NUMBER OF ITEMS
dialog.dismiss(); //CLOSE DIALOG
}
});
builder.show();
My problem is that the TextView for displaying the number of items is displaying "0" and not the actual count of items.
The count method is working while I am adding an item and it is the following:
public int getGamesCount(int id)
{
String countQuery = "SELECT * FROM " + TABLEG +" WHERE t_id="+ id +"";
SQLiteDatabase db = this.getReadableDatabase();
Cursor cursor = db.rawQuery(countQuery, null);
return cursor.getCount();
}
What I am doing wrong here?
thank you
You are using deleteAll() which will delete all records.
To delete a particular record use this function.
public void deleteRecords(String table, String whereClause,
String[] whereArgs) {
db.delete(table, whereClause, whereArgs);
}
Then there is no need to call
remove(getItem(position))
because
notifydatasetchange()
will reset the list again.
You have called deleteAll() and the n you are finding count so that will return 0 only because all records are deleted.
I have a ListView, with three TextViews in each row, that is populated from a Database. The first TextView contains the _id. When I click on an item, an AlertDialog pops up asking if I want to delete the item. How do I extract the information from a specific TextView, in order to update the Database accordingly?
Here is the code snippet I have so far:
listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, final int position, long id) {
AlertDialog.Builder builder = new AlertDialog.Builder(MainActivity.this);
builder.setMessage("Delete this reminder?");
builder.setPositiveButton("Yes", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
//I need the _id to remove the selected item.
db.deleteContact();
}
});
AlertDialog dialog = builder.create();
dialog.show();
}
});
Thanks!
Easiest would be if you got the information from the database that is driving the adapter. You already have the position of the clicked item and the data from your database.
Another possibility is in the onClick method to do
TextView tv = (TextView) view.findViewById(R.id.yourFirstTextView);
String id = tv.getText().toString();
I have a list view where my SQL query will be displayed.
Now I have added an OnItemClickListener to delete entrys on click:
lv.setOnItemClickListener(new OnItemClickListener()
{
public void onItemClick(AdapterView<?> arg0,View arg1,int arg2, long arg3){
ListView lv = (ListView) findViewById(R.id.listView1);
final String Name = lv.getAdapter().getItem(arg2).toString();
final String ID = String.valueOf(arg3);
CharSequence dbeintrag = getString(R.string.dbeintrag);
CharSequence yes = getString(R.string.yes);
CharSequence no = getString(R.string.no);
Builder alertDialog = new AlertDialog.Builder(EP.this);
alertDialog.setTitle(Name);
alertDialog.setMessage(dbeintrag);
alertDialog.setCancelable(true);
alertDialog.setPositiveButton(yes, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
deleteentry(Name,ID);
fillSQLData(); // refresh
} });
alertDialog.setNegativeButton(no, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
} });
alertDialog.show();
}
});
}
public void deleteentry(String Name,long ID) // Lösche Eintrag
{
DataBaseHelper myDbHelper = new DataBaseHelper(null);
myDbHelper = new DataBaseHelper(this);
ID = ID+1; // Anpassen zur DB
SQLiteDatabase database = myDbHelper.getWritableDatabase();
database.execSQL("DELETE FROM Heute WHERE Name='"+Name+"' and _id='"+ID+"'");
mPLAdapter.notifyDataSetChanged();
}
Now I have the problem that my ID in the Database is not the ID I get from the onItemClick function.
For example, I'll add 3 entries, delete all, add 3 new ones. For the function the first entry is 0, in the SQL database its 4...
What is the best solution to fix this?
Than you very much!
Override this method to your adapter class so you can retrieve the id in onItemClick.
#Override
public long getItemId(int position) {
return yourList.get(position);
}
In onItemClick
final String ID = String.valueOf(lv.getAdapter().getItemId(arg2));
//long id = ((YourAdapter)parent.getAdapter()).getItemId(arg2);
Please see Android OnItemClickListener long id parameter is not giving field id and view.getId() returning wrong id in OnItemClickListener
Edit: so here's Oli's changes:
final long id = ((EPListAdapter)arg0.getAdapter()).getItemId(arg2);
"Its important to use .notifyDataSetChanged(); on the Adapter. Else it wont work."
I am building an application in which I'm populating data from the database into the listview of my activity. Now, on longItemClick Listener I want to delete that value from the database and update my listview in the app.
Here my code for longClickListener on the listview:
private ListView showing_history;
private ListAdapter mHistoryListAdapter;
private ArrayList<SearchHistoryDetails> searchArrayList;
private ArrayList<SearchHistoryDetails> HistoryObjArrayList;
mHistoryListAdapter = new ArrayAdapter<String>(this,
R.layout.mylistlayout, populateList());
showing_history.setAdapter(mHistoryListAdapter);
HistoryObjArrayList = new ArrayList<SearchHistoryDetails>();
/**
* Long tap on listview to delete the selected item from the history
* list.
* */
showing_history
.setOnItemLongClickListener(new OnItemLongClickListener() {
#Override
public boolean onItemLongClick(AdapterView<?> arg0,
View arg1, int arg2, long arg3) {
final AlertDialog.Builder b = new AlertDialog.Builder(
MainActivity.this);
b.setIcon(android.R.drawable.ic_dialog_alert);
b.setMessage("Delete this from history?");
b.setPositiveButton("Yes",
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog,
int whichButton) {
Toast.makeText(getApplicationContext(),
"Yes", Toast.LENGTH_LONG)
.show();
}
});
b.setNegativeButton("No",
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog,
int whichButton) {
dialog.cancel();
}
});
b.show();
return true;
}
});
By this code I'm inserting data into the database:
/**
* Inserting the string when user searches for anything into the database.
* */
public void insertHistory(SearchHistoryDetails paraHistoryDetailsPojoObj) {
AndroidOpenDbHelper androidOpenDbHelperObj = new AndroidOpenDbHelper(
this);
SQLiteDatabase sqliteDatabase = androidOpenDbHelperObj
.getWritableDatabase();
ContentValues contentValues = new ContentValues();
contentValues.put(AndroidOpenDbHelper.COLUMN_NAME_HISTORY_STRING,
paraHistoryDetailsPojoObj.getHistoryName());
#SuppressWarnings("unused")
long affectedColumnId = sqliteDatabase.insert(
AndroidOpenDbHelper.TABLE_NAME_HISTORY, null, contentValues);
sqliteDatabase.close();
}
Here is the code from which I'm retrieving data from the database and repopulating it into the list view:
public List<String> populateList() {
List<String> HistoryNamesList = new ArrayList<String>();
AndroidOpenDbHelper openHelperClass = new AndroidOpenDbHelper(this);
SQLiteDatabase sqliteDatabase = openHelperClass.getReadableDatabase();
Cursor cursor = sqliteDatabase
.query(AndroidOpenDbHelper.TABLE_NAME_HISTORY,
new String[] { AndroidOpenDbHelper.COLUMN_NAME_HISTORY_STRING },
null, null, null, null, AndroidOpenDbHelper.ID
+ " DESC");
startManagingCursor(cursor);
while (cursor.moveToNext()) {
String ugName = cursor
.getString(cursor
.getColumnIndex(AndroidOpenDbHelper.COLUMN_NAME_HISTORY_STRING));
SearchHistoryDetails histPojoClass = new SearchHistoryDetails();
histPojoClass.setHistoryName(ugName);
searchArrayList.add(histPojoClass);
HistoryNamesList.add(ugName);
}
sqliteDatabase.close();
int history_db = cursor.getCount();
if (history_db == 0) {
history_layout.setVisibility(LinearLayout.GONE);
} else {
history_layout.setVisibility(LinearLayout.VISIBLE);
}
return HistoryNamesList;
}
Retrieving and inserting data all things are perfectly, but deleting of a particular row is not working for me. Right now I have done some action using toast and it is working, what should I do so that, the database data updates after deletion of the row from the listview. Please give me any idea to overcome this problem.
Try this..,.
b.setPositiveButton("Yes", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int whichButton) {
DatabaseHandler db=new DatabaseHandler(getApplicationContext());
db.delete(arg3+"");
list.remove(position);
YourActivity.this.adapter.notifyDataSetChanged();
}
});
and in DatabaseHandler class
public void delete(String id)
{
SQLiteDatabase db = this.getReadableDatabase();
db.delete(TABLE_NAME, KEY_ID + "=?", new String[]{id});
db.close();
}
most proper solution is to use Loaders.. especially CursorLoader along with Content Provider.
If Content Provider is an overkill for what you are doing try CursorLoader from commonsware. The update after deletion happens automatically and not in the ui thread which is good.
https://github.com/commonsguy/cwac-loaderex.. its pretty easy once you get your head around this.
However if you still want to delete the row as per your code. Just delete it in your longpress listener. But after that refresh the adapter.
How to refresh Android listview?
To update list.. Firstly call the method where you specified the delete query from builder positive button.
After that delete the item from HistoryNamesList array list
Now the data removed from both database and arraylist but listview still show previous data so you have to notify listview adapter as show below
adapter.notifyDataSetChanged();
adapter.notifyDataSetInvalidated();
Solved!
Changes made on onCLick():
public void onClick(DialogInterface dialog,
int whichButton) {
HistoryNamesList.remove(pos);
((BaseAdapter) mHistoryListAdapter)
.notifyDataSetChanged();
}