I have created a database which is displayed in a ListView using an ArrayAdapter. I want a selected ListView item to be deleted when a ContextMenu pops up with a delete option as depicted below:
I have a class for handling all the database functions like delete. When I use a normal onCLicklistener with a button, the delete function is performed correctly, i.e it deletes the correct database entry and reaches the if (cursor.moveToFirst()) line. When I make use of the delete menu item, it does not reach the if (cursor.moveToFirst()) line in the attached delete handler function and therefore does not delete the entry (attached after the ListView code snippet below is the delete handler).
Any help/guidance/examples will be greatly appreciated.
My ListView is populated as follows:
public class Listview extends AppCompatActivity
{
private ListView users;
FloatingActionButton fab;
MyDBHandler dbHandler;
ArrayAdapter<String> arrayAdapter;
String lists;
#Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
StrictMode.ThreadPolicy policy = new
StrictMode.ThreadPolicy.Builder().permitAll().build();
StrictMode.setThreadPolicy(policy);
setContentView(R.layout.activity_listview);
// Create back button in action bar
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
getSupportActionBar().setHomeButtonEnabled(true);
users = (ListView) findViewById(R.id.clientlst);
// Floating Action bar for adding new data entries
fab = (FloatingActionButton) findViewById(R.id.fab1);
MyDBHandler dbHandler = new MyDBHandler(getApplicationContext());
lists = dbHandler.loadHandler();
//Create a list of the saved database String array items and split into
Strings
ArrayList<String> list = new ArrayList<>
(Arrays.asList(lists.split("\n")));
// Create the List view adapter
arrayAdapter = new ArrayAdapter<String>(Listview.this,
android.R.layout.simple_list_item_1, android.R.id.text1, list)
{
#Override // Edit the Text colour of the Listview items
public View getView(int position, View convertView, ViewGroup parent)
{
String Items = arrayAdapter.getItem(position);
String[] separated = Items.split(":");
String Name123 = separated[1]; // This will contain "Name"
TextView textView = (TextView) super.getView(position,
convertView, parent);
textView.setTextColor(Color.BLUE);
textView.setText(Name123);
return textView;
}
};
users.setAdapter(arrayAdapter);
registerForContextMenu(users);
// Create an action to be performed by each click of an item in the
users.setOnItemClickListener
(
new AdapterView.OnItemClickListener()
{
#Override
public void onItemClick(AdapterView<?> parent, View
view, int position, long id) {
String Items = arrayAdapter.getItem(position);
String[] separated = Items.split(":");
String ip = separated[5]; // This will contain "PORT address"
String port = separated[3]; // This will contain "IP number"
Toast.makeText(Listview.this, port + ip,
Toast.LENGTH_LONG).show();
} // onItemClick
} // OnItemClickListener View
); // OnItemClickListener
fab.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view)
{
Toast.makeText(Listview.this, "Fab
Clicked", Toast.LENGTH_LONG).show();
}
}
);
}
#Override
public void onCreateContextMenu(ContextMenu menu, View v,
ContextMenu.ContextMenuInfo menuInfo)
{
super.onCreateContextMenu(menu, v, menuInfo);
menu.setHeaderTitle("Choose an option");
MenuInflater inflator = getMenuInflater();
inflator.inflate(R.menu.example_menu, menu);
}
#Override
public boolean onContextItemSelected(MenuItem item)
{
AdapterView.AdapterContextMenuInfo info =
(AdapterView.AdapterContextMenuInfo) item.getMenuInfo();
switch (item.getItemId())
{
case R.id.option_1:
arrayAdapter.getItem(info.position);
MyDBHandler dbHandler = new MyDBHandler(getApplicationContext());
String Items= arrayAdapter.getItem(info.position);
String[] separated = Items.split(":");
String ip = separated[3]; // This will
contain "IP addr"
String names = separated[1]; // This will
contain "Name"
Log.d("LATE",names + ip);
dbHandler.deleteHandler(names,ip);
arrayAdapter.notifyDataSetChanged(); // Refresh the
listview
Toast.makeText(this, "Deleted", Toast.LENGTH_SHORT).show();
Intent listviews1 = new Intent(Listview.this, Listview.class);
startActivity(listviews1);
return true;
case R.id.option_2:
Intent listviews2 = new Intent(Listview.this, Listview.class);
startActivity(listviews2);
Toast.makeText(this, "Updated", Toast.LENGTH_SHORT).show();
return true;
default:
return super.onContextItemSelected(item);
}
}
}
The delete handler function of the database is as follows:
public void deleteHandler(String username, String IP)
{
//boolean result = false;
String query = "Select*FROM " + TABLE_USER + " WHERE " + COLUMN_NAME + "
= '" + String.valueOf(username) + "'" + " and " + COLUMN_ID + " = '" +
String.valueOf(IP) + "'";
SQLiteDatabase db = this.getWritableDatabase();
Cursor cursor = db.rawQuery(query, null);
Log.d ("MEH", String.valueOf(cursor));
User user = new User();
if (cursor.moveToFirst())
{
user.setUserName(cursor.getString(2));
user.setID(cursor.getString(3));
db.delete(TABLE_USER, COLUMN_NAME + "=? and " + COLUMN_ID + "=?",
new String[]
{
String.valueOf(user.getUserName()),
String.valueOf(user.getID())
});
cursor.close();
//result = true;
}
db.close();
//return result;
}
You aren't calling any method to delete the item from the database from your users.setOnItemClickListener
As you added in your comment, all you are doing is trying to delete the item from your ActionBar's onItemClicked method.
Do the same inside your OnItemClickListener
Update2: Change in requirement
users.setLongClickable(true);
users.setOnItemLongClickListener(new OnItemLongClickListener() {
public boolean onItemLongClick(AdapterView<?> parent, View v, int position, long id) {
//Do your tasks here
AlertDialog.Builder alert = new AlertDialog.Builder(
YourActivity.this);
alert.setTitle("Alert!!");
alert.setMessage("Choose an option");
alert.setPositiveButton("Edit", new OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
//do your work here
dialog.dismiss();
}
});
alert.setNegativeButton("Delete", new OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
//perform your delete callback here
dialog.dismiss();
}
});
alert.show();
return true;
}
});
Update1: Explanation to Amiya's answer,
The reason why
cursor.moveToFirst() isn't a good option is because this statement
is unnecessary. The compiler knows exact spot to hit when it will
enter inside your DB. One usually perform cursor.moveToFirst()
when you need to iterate through all or some data elements from your
database.
"Make sure, COLUMN_ID is PRIMARY Key." Reason behind this is to avoid duplicity in case you ever add a functionality of adding items on the run time.
REMOVE this if (cursor.moveToFirst()) .
Make sure, COLUMN_ID is PRIMARY Key.
Check deleteHandler() method is invoking or not.
You should try with
public void deleteHandler(String username, String IP)
{
SQLiteDatabase db = this.getWritableDatabase();
db.delete(TABLE_USER,
COLUMN_NAME + " = ? AND " + COLUMN_ID + " = ?",
new String[] {username, IP});
db.close();
}
Related
I am using an sqllite database to store two columns which are phonename and phonenumber. I am using an arrayList to iterate through the data and display the phonename in a listview which is working, but I also need to iterate through the phonenumber column under the same listview as well. I only need the phonename to be showing in the listview.
This is for when the user has selected the item in the listview, it shows the selected phonename and phonenumber, which at the moment it is only currently showing the phonename and showing blank for phonenumber for obvious reasons.
DataDBAdapter
public long insert(String phonename, String phonenumber)
{
ContentValues cv = new ContentValues();
cv.put(COl_MYTABLE_PHONENAME,phonename);
cv.put(COL_MYTABLE_PHONENUMBER,phonenumber);
return mDB.insert(TBL_MYTABLE,null,cv);
}
//---------------------------------------------------------------------------
// Iterating through the database
//---------------------------------------------------------------------------
public ArrayList<String> getAllRowsAsList()
{
Cursor csr = mDB.query(TBL_MYTABLE,null,null,null,null,null,null);
ArrayList<String> rv = new ArrayList<>();
while (csr.moveToNext())
{
rv.add(csr.getString(csr.getColumnIndex(COl_MYTABLE_PHONENAME)));
}
return rv;
}
SelectModemFragment
private void manageListView(Context context)
{
thelist = dbHelper.getAllRowsAsList(); // Extract the list, just the phone names
// Only setup the adapter and the ListView if the adapter hasn't been setup
if(arrayAdapter == null)
{
// Instantiate the adapter
arrayAdapter = new ArrayAdapter<>(context,android.R.layout.simple_list_item_1,thelist); //<<<<<<<<<< list included
display_contacts1.setAdapter(arrayAdapter); //<<<<<<<<<< Tie the adpater to the ListView
// Set the ListViews OnItemClick Listener
display_contacts1.setOnItemClickListener(new AdapterView.OnItemClickListener()
{
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id)
{
String namedisplay = arrayAdapter.getItem(position); //<<<<<<<<<< this gets the phone name
namedisplay = arrayAdapter.getItem(position);
Toast.makeText(view.getContext(), namedisplay + " Selected for Communication", Toast.LENGTH_SHORT).show();
Toast.makeText(view.getContext(), phoneNo, Toast.LENGTH_SHORT).show();
}
});
}
Issue
using ArrayAdapter only allows a a single item to be passed, thus unless you resort to complicated/messy/inefficient methods ArrayAdapter is only really suitable for a single value.
Fix
You could use an ArrayList where your_object has members for all the required values. i.e phonenumber and phonename. Noting that unless you use a Custom Adapter that you should override the the toString method to extract the data that you want to be displayed, as that is what a standard ArrayAdapter uses.
Alternative (use a CursorAdapter)
An alternative would be to use a Cursor Adapter (e.g. SimpleCursorAdapter), you can then return the Cursor and use it directly. However, a CursorAdapter REQUIRES a column specifically name _id (BaseColumns._ID can be used).
One of the clear advantages of a Cursor adapter is the the 4th paremmter passed to the onItemClick/onItemLongClick is the id of the row (if used correctly) allowing a single value to then get/update/delete/pass the respective selected row.
As such I'd recommend a Cursor Adapter for a ListView and hence the more comprehensive answer.
You may think I don;t have such a column. However, you can use the normally hidden rowid column and dynamically create a column named _id.
You could have a method, in the database helper (DataDBAdapter) such as :-
public Cursor getAllRowsAsCursor()
{
String[] columns = new String[]{"rowid AS " + BaseColumns._ID,"*"}
return = mDB.query(TBL_MYTABLE,null,null,null,null,null,null)
}
The ManageList method could then be :-
private void manageListView(Context context) {
myCursor = dbhelper.getAllRowsAsCursor();
// Only setup the adapter and the ListView if the adapter hasn't been setup
if(arrayAdapter == null)
{
// Instantiate the adapter
arrayAdapter = new SimpleCursorAdapter(context,android.R.layout.simple_list_item_1,myCursor,new String[]{DataAdapter.COl_MYTABLE_PHONENAME},newint[]{android.R.id.text1},0);
display_contacts1.setAdapter(arrayAdapter); //<<<<<<<<<< Tie the adpater to the ListView
// Set the ListViews OnItemClick Listener
display_contacts1.setOnItemClickListener(new AdapterView.OnItemClickListener()
{
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id)
{
String namedisplay = arrayAdapter.getItem(position); //<<<<<<<<<< this gets the phone name
String phonenumber = myCursor,getString(myCursor.getColumnIndex(DataAdapter.COL_MYTABLE_PHONENUMBER);
Toast.makeText(view.getContext(), namedisplay + " Selected for Communication", Toast.LENGTH_SHORT).show();
Toast.makeText(view.getContext(), phonenumber, Toast.LENGTH_SHORT).show();
}
});
} else {
arrayAdapter.swapCursor(myCursor);
}
Notes
MyCursor would be declared as a class variable e.g. Cursor MyCursor;
Instaed of
ArrayAdapter<String> arrayAdapter; you would have
SimpleCursorAdapter arrayAdapter;
The above is in-principle code and has not been tested, so there may be errors and/or omissions.
Working Example
The following is the code based upon the code from the previous question asked (which this appears to follow on from). It has two ListViews the old and a new one that uses a SimpleCursorAdapter. Clicking an item display phone number and also id. Lon Clicking an Item deletes that item (refreshing both ListViews).
DataDBAdapter.java has two new methods (so add these) :-
//<<<<<<<<<< ADDED
public Cursor getAllRowsAsCursor() {
return mDB.query(TBL_MYTABLE,null,null,null,null,null,null);
}
public int delete(long id) {
String whereclause = COL_MYTABLE_ID + "=?";
String[] whereargs = new String[]{String.valueOf(id)};
return mDB.delete(TBL_MYTABLE,whereclause,whereargs);
}
SelectModemFragment.java is now :-
public class SelectModemFragment extends Fragment {
private SelectModemViewModel mViewModel;
ListView display_contacts1;
ArrayAdapter<String> arrayAdapter;
ArrayList<String> thelist;
DataDBAdapter dbhelper;
//<<<<<<<<<< ADDED
ListView display_contacts2;
SimpleCursorAdapter sca;
Cursor MyCursor;
public static SelectModemFragment newInstance() {
return new SelectModemFragment();
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.select_modem_fragment, container, false);
display_contacts1 = view.findViewById(R.id.lv001); //<<<<<<<<<< top listview ArrayAdapter<String>
display_contacts2 = view.findViewById(R.id.lv002);
dbhelper = new DataDBAdapter(view.getContext());
AddSomeData();
manageListView(view.getContext());
manageListView2();
return view;
}
#Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
mViewModel = ViewModelProviders.of(this).get(SelectModemViewModel.class);
// TODO: Use the ViewModel
}
//Sets up the ListView if not already setup
private void manageListView(Context context) {
thelist = dbhelper.getAllRowsAsList(); //<<<<<<<<<< extract the list (just the phone names) from the database
// Only setup the adapter and the ListView if the adapter hasn't been setup
if (arrayAdapter == null) {
// Instantiate the adapter
arrayAdapter = new ArrayAdapter<>(context,android.R.layout.simple_list_item_1,thelist); //<<<<<<<<<< list included
display_contacts1.setAdapter(arrayAdapter); //<<<<<<<<<< Tie the adpater to the ListView
// Set the ListViews OnItemClick Listener
display_contacts1.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
String name = arrayAdapter.getItem(position); //<<<<<<<<<< this gets the phone name
Toast.makeText(view.getContext(),"You clicked the phone named " + name,Toast.LENGTH_SHORT).show();
}
});
} else {
//<<<<<<<<<< MODIFIED to cope with changes (needs to rebuild the array within the adpater)
arrayAdapter.clear();
for (String s: thelist) {
arrayAdapter.add(s);
}
arrayAdapter.notifyDataSetChanged();
}
}
//<<<<<<<<<< ADDED FOR CursorAdapter
private void manageListView2() {
MyCursor = dbhelper.getAllRowsAsCursor();
if (sca == null) {
sca = new SimpleCursorAdapter(
getContext(),
android.R.layout.simple_list_item_1,
MyCursor,
new String[]{DataDBAdapter.COl_MYTABLE_PHONENAME},
new int[]{android.R.id.text1},
0
);
display_contacts2.setAdapter(sca);
display_contacts2.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
Toast.makeText(view.getContext(),
"You Clicked the phone name " +
MyCursor.getString(MyCursor.getColumnIndex(DataDBAdapter.COl_MYTABLE_PHONENAME)) +
". The phonenumber is " +
MyCursor.getString(MyCursor.getColumnIndex(DataDBAdapter.COL_MYTABLE_PHONENUMBER)) +
". The ID (as passed) is " + String.valueOf(id) +
". The ID (from Cursor) is " + String.valueOf(MyCursor.getLong(MyCursor.getColumnIndex(DataDBAdapter.COL_MYTABLE_ID)))
,
Toast.LENGTH_SHORT).show();
}
});
//<<<<<<<<<< EXTRA delete row on long click
display_contacts2.setOnItemLongClickListener(new AdapterView.OnItemLongClickListener() {
#Override
public boolean onItemLongClick(AdapterView<?> parent, View view, int position, long id) {
dbhelper.delete(id);
manageListView2();
manageListView(getContext());
return true;
}
});
} else {
sca.swapCursor(MyCursor);
}
}
// Add some testing data (only if none already exists)
private void AddSomeData() {
if (DatabaseUtils.queryNumEntries(dbhelper.getWritableDatabase(),DataDBAdapter.TBL_MYTABLE) < 1) {
dbhelper.insert("Phone 1", "0000000000");
dbhelper.insert("Phone 2", "1111111111");
}
}
#Override
public void onResume() {
super.onResume();
manageListView2();
manageListView(getContext());
}
#Override
public void onDetach() {
super.onDetach();
MyCursor.close();
}
}
On deleting the item from the Listview the item gets deleted at that time, but on coming back to the activity the item reappears.
This is my Main2Activity code:
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main2);
position = intent.getIntExtra("position", 0);
adapter = new ArrayAdapter<>(this, android.R.layout.simple_list_item_1, listItem);
listView.setAdapter(adapter);
viewData1();
listView.setOnItemLongClickListener(new AdapterView.OnItemLongClickListener() {
#Override
public boolean onItemLongClick(AdapterView<?> parent, View view, final int pos, long id) {
final int itemToDelete = pos;
new AlertDialog.Builder(Main2Activity.this)
.setIcon(android.R.drawable.ic_dialog_alert)
.setTitle("Are you sure?")
.setMessage("Do you want to delete this location?")
.setPositiveButton("Yes", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialogInterface, int i) {
listItem.remove(itemToDelete);
databaseHelper1.deleteLocation(itemToDelete, position);
adapter.notifyDataSetChanged();
}
}
)
.setNegativeButton("No", null)
.show();
return true;
}
});
}
private void viewData1() {
Cursor cursor = databaseHelper1.viewData1(position);
if (cursor.getCount() == 0) {
Toast.makeText(this, "No data to show", Toast.LENGTH_SHORT).show();
} else {
while (cursor.moveToNext()) {
Log.i("message", "Data got");
listItem.add(cursor.getString(1));
}
adapter.notifyDataSetChanged();
}
}
DatabaseHelper:
public void deleteLocation(int itemToDelete,int position)
{
SQLiteDatabase sqLiteDatabase = this.getWritableDatabase();
String itemDelete = Integer.toString(itemToDelete);
Log.i("itemdel",itemDelete);
if(position ==0)
{
String Id = (ID1);
Log.i("Id",Id);
String query = " Delete from "+DB_TABLE1 + " where "+ Id + " = " + itemDelete;
sqLiteDatabase.execSQL(query);
sqLiteDatabase.delete(DB_TABLE1,ID1 + " = "+ itemDelete, null);
sqLiteDatabase.compileStatement(query);
Log.i("del"," executed")
}
}
public Cursor viewData1(int position)
{
SQLiteDatabase sqLiteDatabase = this.getReadableDatabase();
Cursor cursor = null;
if (position ==0)
{
String query = "Select * from " + DB_TABLE1;
cursor = sqLiteDatabase.rawQuery(query, null);
}
return cursor;
}
What happens is:
Before Deleting:
After Deleting garden:
On restarting activity:
How do I commit the delete to the database? Thanks.
Your issue is that you are assuming that position (3rd parameter passed to the onItemLongClick method) directly relates to the id of the row.
You cannot rely on a correlation between position and id.
The first position in the list will be at position 0. The lowest ID allocated (unless forced) will be 1. However adding 1 is not a solution as even though it may initially work. As soon as you delete anything other than the last item in the list then an id is omitted from the list of id's and you may not delete a row or you may delete a different row.
The most sensible/easiest fix is to utilise a CursorAdapter i.e. SimpleCursorAdapter in which case the 4th parameter to onItemClick and onItemLongClick (long l) will be the actual id. However, to utilise a CursorAdapter you MUST have the id column named as _id (hence why there is the constant BaseColumns._ID).
You could always rename the column when extracting it using AS e.g. SELECT rowid AS _id, * FROM the_table; (which will select all existing columns AND the id column).
Here's a link to a more comprehensive answer with options for other adapter Deleting item from ListView and Database with OnItemClickListener
I read some posts and found that reQuery() is deprecated and some suggested using SwapCursor() or ChangeCursor().
I have a Favorite button on whose click I update DB and change color of the Button. When I scroll and come back to particular view(and Button) color is reset.
I know it is because view is recycled. I have a condition based on a DB column value to set the color of the Button.
I want view to get updated values from DB after I press the Button. For which I have to refresh/requery Cursor/DB.
How do I do that with CursorAdapter keeping in mind that my min. API is 19?
UPDATE
CursorAdapter code:
public class ToDoCursorAdapter extends CursorAdapter {
SparseBooleanArray selectionArrayAr = new SparseBooleanArray();
SparseBooleanArray selectionArrayRef = new SparseBooleanArray();
SparseBooleanArray selectionArrayFav = new SparseBooleanArray();
//Boolean isSet = false;
private MainButtons_Interface mAdapterCallback;
public ToDoCursorAdapter(Context context, Cursor cursor) {
super(context, cursor, 0);
}
#Override
public View newView(Context context, Cursor cursor, ViewGroup parent) {
ViewHolderItem viewHolder = new ViewHolderItem();
View rowView = LayoutInflater.from(context).inflate(R.layout.listview, parent, false);
viewHolder.engTextV = (TextView) rowView.findViewById(R.id.engText);
viewHolder.arTextV = (TextView) rowView.findViewById(R.id.arabText);
viewHolder.buttonIAV = (Button) rowView.findViewById(R.id.buttonIA); //For Arabic Text
viewHolder.refTextV = (TextView) rowView.findViewById(R.id.refText);
viewHolder.buttonIRV = (Button) rowView.findViewById(R.id.buttonIR); //For Ref Text
viewHolder.buttonIFV = (ImageButton) rowView.findViewById(R.id.buttonF);
rowView.setTag(viewHolder);
return rowView;
}
#Override
public void bindView(final View view, final Context context, final Cursor cursor) {
final ViewHolderItem viewHolder = (ViewHolderItem) view.getTag();
String arabic = cursor.getString(cursor.getColumnIndexOrThrow("PlainArab_Text")).trim().replaceAll("[\n]{2,}", "TWOFEEDS").replaceAll("\n", " ").replaceAll(" +", " ").replaceAll("<br/>", "\n").replaceAll("TWOFEEDS", "\n") + "\n";
String english = cursor.getString(cursor.getColumnIndexOrThrow("PlainEng_Text")).trim().replaceAll("[\n]{2,}", "TWOFEEDS").replaceAll("\n", " ").replaceAll(" +", " ").replaceAll("<br/>", "\n").replaceAll("TWOFEEDS", "\n") + "\n";
String ref = cursor.getString(cursor.getColumnIndexOrThrow("REF")).trim().replaceAll("<br/> <br/>", " ").replaceAll("<br/>", "\n");
final Integer HadithID = cursor.getInt(cursor.getColumnIndexOrThrow("ID"));
final Integer IsFav = cursor.getInt(cursor.getColumnIndexOrThrow("IsFavorite"));
viewHolder.arTextV.setText(arabic);
viewHolder.engTextV.setText(english);
viewHolder.refTextV.setText(ref);
final int position = cursor.getPosition();
boolean isSelectedA = selectionArrayAr.get(position);
boolean isSelectedR = selectionArrayRef.get(position);
boolean isSelectedF = selectionArrayFav.get(position);
if (isSelectedA) {
viewHolder.arTextV.setVisibility(view.GONE);
viewHolder.buttonIAV.setText("Show Arabic Version");
} else if (!isSelectedA){
viewHolder.arTextV.setVisibility(view.VISIBLE);
viewHolder.buttonIAV.setText("Hide Arabic Version");
}
if (isSelectedR) {
viewHolder.refTextV.setVisibility(view.GONE);
viewHolder.buttonIRV.setText("Show Refrence");
} else if (!isSelectedR){
viewHolder.refTextV.setVisibility(view.VISIBLE);
viewHolder.buttonIRV.setText("Hide Refrence");
}
//boolean isSelectedF = selectionArrayFav.get(position);
if(isSelectedF) {
viewHolder.buttonIFV.setImageResource(R.drawable.favoritebutton_afterclick);
} else if (!isSelectedF){
viewHolder.buttonIFV.setImageResource(R.drawable.favoritebutton);
}
//Arabic Button
viewHolder.buttonIAV.setOnClickListener(
new View.OnClickListener()
{ #Override
public void onClick(View v) {
boolean isSelectedAc = selectionArrayAr.get(position);
if(!isSelectedAc) {
viewHolder.arTextV.setVisibility(v.GONE);
viewHolder.buttonIAV.setText("Show Arabic Version");
setSelectedAr(position, true);
} else if (isSelectedAc){
viewHolder.arTextV.setVisibility(v.VISIBLE);
setSelectedAr(position, false);
viewHolder.buttonIAV.setText("Hide Arabic version");
}
}
}
);
//Ref Button
viewHolder.buttonIRV.setOnClickListener(
new View.OnClickListener()
{ #Override
public void onClick(View v) {
boolean isSelectedRc = selectionArrayRef.get(position);
if(!isSelectedRc) {
viewHolder.refTextV.setVisibility(v.GONE);
viewHolder.buttonIRV.setText("Show Reference");
setSelectedRef(position, true);
} else if (isSelectedRc){
viewHolder.refTextV.setVisibility(v.VISIBLE);
setSelectedRef(position, false);
viewHolder.buttonIRV.setText("Hide Reference");
}
}
}
);
//Fav Button
viewHolder.buttonIFV.setOnClickListener(
new View.OnClickListener()
{ #Override
public void onClick(View v) {
boolean isSelectedF = selectionArrayFav.get(position);
boolean IsSet = ((ListViewActivity) context).addRemFav(HadithID);
String mess ="";
if(IsSet){
mess = "Hadith add to Favorite list";
} else if(!IsSet){
mess = "Hadith removed from Favorite list";
}
if(!isSelectedF) {
viewHolder.buttonIFV.setImageResource(R.drawable.favoritebutton_afterclick);
setSelectedF(position, true);
} else if (isSelectedF){
viewHolder.buttonIFV.setImageResource(R.drawable.favoritebutton);
setSelectedF(position, false);
}
Toast.makeText(v.getContext(), mess, Toast.LENGTH_SHORT).show();
}
}
);
}
// our ViewHolder.
static class ViewHolderItem {
TextView engTextV;
TextView arTextV;
TextView refTextV;
Button buttonIAV;
Button buttonIRV;
ImageButton buttonIFV;
}
// Method to mark items in selection
public void setSelectedAr(int position, boolean isSelected) {
selectionArrayAr.put(position, isSelected);
}
public void setSelectedRef(int position, boolean isSelected) {
selectionArrayRef.put(position, isSelected);
}
public void setSelectedF(int position, boolean isSelected) {
selectionArrayFav.put(position, isSelected);
}
UPDATE
I added this logic to my function which was called on clicking the Button.
Cursor todoCursor1 = hadDB.rawQuery("SELECT ID as _id, * FROM HAD_TABLE WHERE ID < 7001 ", null);
todoAdapter.changeCursor(todoCursor1);
Basically, you just need to requery DB so that you get updated records/Data and then change your current cursor with new one, todoCursor1 is my case above.
Also, changeCursor() will close your current cursor, in case you would want to go back to old cursor you should use swapCursor() instead as it will return you old cursor.
Now my only thing I want to know is, if this will work for APIs 19 and up.
I added this logic to my function which was called on clicking the Button.
Cursor todoCursor1 = hadDB.rawQuery("SELECT ID as _id, * FROM HAD_TABLE WHERE ID < 7001 ", null);
todoAdapter.changeCursor(todoCursor1);
Basically, you just need to requery DB so that you get updated records/Data and then change your current cursor with new one, todoCursor1 is my case above.
Also, changeCursor() will close your current cursor, in case you would want to go back to old cursor you should use swapCursor() instead as it will return you old cursor.
I have a problem. I try to delete the record from the database. I have no idea, but how to do it. I tried something like this, but not quite work.
The basic gist is that I trying to delete from the database based on list item position, not database row ID. How delete base database row ID?
ListView listawszystkich;
public int pozycja;
DatabaseDEO db = new DatabaseDEO(this);
final String[] skad = new String[]{Database.tables.Transakcje.Kolumny.kwota, Database.tables.Transakcje.Kolumny.data, Kategorie.KOLUMNY.nazwa_kategorii, Database.tables.Transakcje.Kolumny.komentarz};
final int[] dokad = new int[]{R.id.kwotaglowna,R.id.dataglowna,R.id.kategoriaglowna,R.id.komentarzglowny};
private SimpleCursorAdapter adapterspinner;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_transakcje2);
listawszystkich = (ListView) findViewById(R.id.listawszystkich);
listawszystkich.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
pozycja = position+1;
}
});
Cursor kursorwszystkie = db.wszystkietransakcje();
adapterspinner = new SimpleCursorAdapter(getApplicationContext(), R.layout.activity_transakcje,kursorwszystkie,skad, dokad,0);
adapterspinner.notifyDataSetChanged();
listawszystkich.setAdapter(adapterspinner);
registerForContextMenu(listawszystkich);
}
#Override
public void onCreateContextMenu(ContextMenu menu, View v, ContextMenu.ContextMenuInfo menuInfo) {
super.onCreateContextMenu(menu, v, menuInfo);
if (v.getId()==R.id.listawszystkich) {
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.menu_list,menu);
}
}
#Override
public boolean onContextItemSelected(MenuItem item) {
AdapterView.AdapterContextMenuInfo info = (AdapterView.AdapterContextMenuInfo) item.getMenuInfo();
switch (item.getItemId()) {
case R.id.delete:
db.usuwanietransakcji(pozycja);
Transakcje.this.recreate();
Toast.makeText(getApplicationContext(), "Delete", Toast.LENGTH_SHORT).show();
default:
return super.onContextItemSelected(item);
}
Method to delete row (in DatabaseDEO):
public void usuwanietransakcji(int id_transakcji){
SQLiteDatabase db = DbHelper.getWritableDatabase();
db.execSQL("DELETE FROM " + Transakcje.NAZWA_TABELI+ " WHERE "+Transakcje.Kolumny.id_transakcji+"='"+id_transakcji+"'");
db.close();
}
Looks like you're trying to delete from the database based on list position rather than row ID:
db.usuwanietransakcji(pozycja);
I'm guessing id_transakcji is a unique value similar to a row ID? First you'll need to declare Cursor kursorwszystkie as a member variable outside of the onCreate method, but still populate it on the same line.
In onContextItemSelected() you'll need to query your cursor again:
case R.id.delete: {
// Move to the selected row
kursorwszystkie.moveToPosition(info.position);
// Get the column ID of id_transakcji
final int col_id = kursorwszystkie.getColumnIndex(Database.tables.Transakcje.Kolumny.id_transakcji);
// Get id_transakcji
final int id_transakcji = kursorwszystkie.getInt(col_id);
// Query the database
db.usuwanietransakcji(id_transakcji);
Transakcje.this.recreate();
Toast.makeText(getApplicationContext(), "Delete", Toast.LENGTH_SHORT).show();
break;
}
Note the addition of {} as I'm declaring a variable inside a switch case. Also add a break; at the end of the case so the code doesn't fall through into the default block. Let me know if that works.
I've created a ListView from an SQLite database but am stuck on how to add a listener to each ListView item so that when an item is clicked I can display another page with more information on that item. The database is just a sample. Any help would be appreciated.
public class Database extends ListActivity {
private final String SAMPLE_DB_NAME = "myFriendsDb";
//private final String SAMPLE_TABLE_NAME = "friends";
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
ArrayList<String> results = new ArrayList<String>();
SQLiteDatabase db = null;
try {
db = this.openOrCreateDatabase(SAMPLE_DB_NAME, MODE_PRIVATE, null);
db.execSQL("CREATE TABLE IF NOT EXISTS people" +
" (LastName VARCHAR, FirstName VARCHAR," +
" Country VARCHAR, Age INT(3));");
db.execSQL("INSERT INTO people" +
" Values ('Jones','Bob','UK',30);");
db.execSQL("INSERT INTO people" +
" Values ('Smith','John','UK',40);");
db.execSQL("INSERT INTO people" +
" Values ('Thompson','James','UK',50);");
Cursor c = db.rawQuery("SELECT FirstName, LastName FROM people", null);
if (c != null ) {
if (c.moveToFirst()) {
do {
String firstName = c.getString(c.getColumnIndex("FirstName"));
String lastName = c.getString(c.getColumnIndex("LastName"));
results.add("" + firstName + " " + lastName);
}while (c.moveToNext());
}
}
this.setListAdapter(new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1,results));
} catch (SQLiteException se ) {
Log.e(getClass().getSimpleName(), "Could not create or Open the database");
} finally {
if (db != null)
db.execSQL("DELETE FROM people");
db.close();
}
}
}
there are many ways to solve your problem. One possible solution is this: you simply need to implement protected method onListItemClick(ListView l, View v, int position, long id) in your ListActivity.
public class Database extends ListActivity {
//YOUR CODE ABOVE HERE...
public static final String SHOWITEMINTENT_EXTRA_FETCHROWID = "fetchRow";
public static final int ACTIVITY_SHOWITEM = 0; /*Intent request user index*/
#Override
protected void onListItemClick(ListView l, View v, int position, long id){
/*
position variable holds the position of item you clicked...
do your stuff here. If you want to send to another page, say another activity
that shows your stuff, you can always use an intent
example:
*/
Intent tmpIntent = new Intent(this, YourActivityForShowingItem.class);
tmpIntent.putExtra(SHOWITEMINTENT_EXTRA_FETCHROWID, position);
startActivityForResult(tmpIntent, ACTIVITY_SHOWITEM);
}
}
Alternately, you can access the ListView of your listActivity using getListView(), and call the setters for listeners or context menu as you would have done with a regular ListView object. For instance, this function that sets a listener using this approach:
private void setMyListListener(){
getListView().setOnItemClickListener(new OnItemClickListener(){
#Override
public void onItemClick(AdapterView<?> a, View v, int position, long id){
/*same fake code as above for calling another activity using an intent:*/
Intent tmpIntent = new Intent(this, YourActivityForShowingItem.class);
tmpIntent.putExtra(SHOWITEMINTENT_EXTRA_FETCHROWID, position);
startActivityForResult(tmpIntent, ACTIVITY_SHOWITEM);
}
});
}
This function can be called by your onCreate(...) function afterwards if you want your click listener to be configured the same way for the whole duration of your activity.