can anybody tell me how to change the visibility of a menuitem from another activity?
I have two activities "activity A and B". in one activity A when I press a menu item it saves some strings to the list of activity B and In activity A menuitem visibility set to false. now I want that when I delete that item from activity B which I saved from activity A, with this delete the menuitem visibility in activity A changes to true and it become visible again? so how can I do this. I using database to populate listview.
Activity A
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.atherosclerosis, menu);
return true;
}
// for starting activity from the option or menu//
#Override
public boolean onOptionsItemSelected(MenuItem item) {
SharedPreferences myPrefs = PreferenceManager.getDefaultSharedPreferences(this);
final SharedPreferences.Editor editor = myPrefs.edit();
favClicked = myPrefs.getBoolean("menu_item", false);
switch (item.getItemId()) {
case R.id.id_favorit:
// Add it to the DB and re-draw the ListView
myDb.insertRow("Atherosclerosis", 0, "");
Toast.makeText(getApplicationContext(), "Item Added to favorite list!", Toast.LENGTH_SHORT).show();
favClicked=true;
editor.putBoolean("menu_item", favClicked);
editor.commit();
invalidateOptionsMenu();
return true;
case R.id.id_favorit2:
myDb.deleteRow("Atherosclerosis");
Toast.makeText(getApplicationContext(), "Item deleted from favorite list!", Toast.LENGTH_SHORT).show();
favClicked=false;
editor.putBoolean("menu_item", favClicked);
editor.commit();
invalidateOptionsMenu();
return super.onOptionsItemSelected(item);
}
return true;
}
#Override
public boolean onPrepareOptionsMenu(Menu menu) {
if(favClicked==true){
menu.findItem(R.id.id_favorit).setVisible(false);
menu.findItem(R.id.id_favorit2).setVisible(true);
}else{
menu.findItem(R.id.id_favorit).setVisible(true);
menu.findItem(R.id.id_favorit2).setVisible(false);
}
Activity B
private void populateListViewFromDB() {
Cursor cursor = myDb.getAllRows();
// Allow activity to manage lifetime of the cursor.
// DEPRECATED! Runs on the UI thread, OK for small/short queries.
startManagingCursor(cursor);
// Setup mapping from cursor to view fields:
String[] fromFieldNames = new String[]
{DBAdapter.KEY_NAME, DBAdapter.KEY_STUDENTNUM};
int[] toViewIDs = new int[]
{R.id.item_name};
// Create adapter to may columns of the DB onto elemesnt in the UI.
SimpleCursorAdapter myCursorAdapter =
new SimpleCursorAdapter(
this, // Context
R.layout.item_layout, // Row layout template
cursor, // cursor (set of DB records to map)
fromFieldNames, // DB Column names
toViewIDs // View IDs to put information in
);
// Set the adapter for the list view
ListView myList = (ListView) findViewById(R.id.favlistView1);
myList.setAdapter(myCursorAdapter);
}
private void registerListClickCallback() {
ListView myList = (ListView) findViewById(R.id.favlistView1);
//This code is for to delete the single item from the listview of favorite list
myList.setOnItemLongClickListener(new AdapterView.OnItemLongClickListener() {
#Override
public boolean onItemLongClick(AdapterView<?> arg0, View arg1,
int arg2, final long arg3) {
Cursor cursor = myDb.getRow(arg3);
if (cursor.moveToFirst()) {
new AlertDialog.Builder(FavoriteDiseases.this)
.setTitle("Delete Item")
.setMessage("Do you want to delete this disease?")
.setPositiveButton(android.R.string.yes, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
// continue with delete
myDb.deleteItem(arg3);
populateListViewFromDB();
}
})
.setNegativeButton(android.R.string.no, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
// do nothing
}
})
.show();
}
return true;
}
});
Need a little more context for a good answer how are the activities related is one calling the other?
But in general if activity a is calling activity b. Then you could just call startActivityForResult when starting activity b. When b is finished return a status that informs activity a that the item has been deleted.
To update the menu assuming you are creating your menu by overriding onCreateOptionsMenu, then just have that method check a flag to set a state of the menu item. Then in your onActivityResult method set the flag based on the result of activity b and call invalidateOptionsMenu() which will redraw your options menu.
Related
I feel like this shouldn't be a complicated problem, but I've tried reworking it and cannot think of a solution as to why it isn't working.
I have a listView that adds a ArrayList notes to it. For this listView, when you longpress on an item, it creates a pop up that deletes the item clicked. my set notesSet takes data from sharedPreferences and adds it to notes and gets updated when notes changes. This deletion is controlled by a Yes/No box. For some reason, I cannot remove the item from notes and have the listView show the updated form.
Here is the code for the long click:
myPref.edit().putStringSet("NN", notesSet).apply();
listView.setOnItemLongClickListener(new AdapterView.OnItemLongClickListener() {
#Override
public boolean onItemLongClick(AdapterView<?> adapterView, View view, int i, long l) {
new AlertDialog.Builder(Schedule.this)
.setIcon(android.R.drawable.ic_dialog_alert)
.setTitle("Pop Up!")
.setMessage("Ready to delete this task?")
.setPositiveButton("Yes", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialogInterface, int i) {
SharedPreferences myPref = Schedule.this.getSharedPreferences("com.example.jackson.collegeplanner", Context.MODE_PRIVATE);
Set<String> notesSet = new HashSet<String>(myPref.getStringSet("NN", null));
ArrayAdapter arrayAdapter = new ArrayAdapter(Schedule.this, android.R.layout.simple_list_item_1, notes);
ListView listView = (ListView) findViewById(R.id.listView);
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
notesSet.remove(i);
notes.clear();
notes.addAll(notesSet);
myPref.edit().putStringSet("NN", notesSet).apply();
listView.setAdapter(arrayAdapter);
/*
notes.remove(i);
notesSet.addAll(notes);
notes.clear();
*/
}
})
.setNegativeButton("No", null).show();
return false;
}
});
I've actually pinpointed the problem, I think, to these three lines of code. Problem is, I can't figure out what it is I'm doing
notesSet.remove(i);
notes.clear();
notes.addAll(notesSet);
Actually it is a simple mistake, instead of passing String value to notesSet.remov(), you are passing integer value to it.
So make change like this
notesSet.remove(i)
to
notesSet.remove(notes(i))
Currently, in anotherclass, I need to delete 1 item when I upload success a file call deleteCallWhenUploadSuccess.
In this class, I using fileName to determined item need to delete.
But it doesn't delete item in ListView from Layout activity_call_history.xml
In DAO class I delete with code:
public void deleteCallWhenUploadSuccess(String fileNameWhis)
{
db = callDatabaseHelper.getWritableDatabase();
String where = CallDatabaseHelper.FILE_NAME + "='" + fileNameWhis + "'";
db.delete(CallDatabaseHelper.TABLE_NAME, where, null);
}
And in other class I using it:
DAO.deleteCallWhenUploadSuccess(filename);
I write code to remove an item on ListView in event onActionItemClicked.
On the DAO class I start to delete an item with rowId:
public void deleteCallV2(int rowId) {
db = callDatabaseHelper.getReadableDatabase();
Cursor cursor = db.rawQuery("select * from "+CallDatabaseHelper.TABLE_NAME+" where rowId = "+String.valueOf(rowId),null);
while(cursor.moveToNext()){
this.rowId = CallDatabaseHelper.ROW_ID +"="+cursor.getString(cursor.getColumnIndex(CallDatabaseHelper.ROW_ID));
}
db.delete(CallDatabaseHelper.TABLE_NAME, this.rowId, null);
}
Code I used to delete item in ListView of Layout historyAdapter write code in HistoryFragment.java, I was comment in code to easy read:
#Override
public boolean onActionItemClicked(ActionMode mode, MenuItem item) {
switch (item.getItemId()) {
case R.id.deleteAction:
// Calls getSelectedIds method from ListViewAdapter Class
selected = historyAdapter
.getSelectedIds();
// Captures all selected ids with a loop
for (int i = (selected.size() - 1); i >= 0; i--) {
if (selected.valueAt(i)) {
Call selecteditem = historyAdapter
.getItem(selected.keyAt(i));
// Remove selected items following the ids
historyAdapter.remove(selecteditem);
}
}
getFragmentManager().beginTransaction().replace(R.id.container,new HistoryFragment()).commit();
// Close CAB
mode.finish();
return true;
case R.id.allAction:
historyAdapter.toggleAll(listView);
Toast.makeText(getActivity(), "Đã chọn tất cả", Toast.LENGTH_SHORT).show();
return true;
default:
return false;
}
}
But it only work when I select item with long press and select item or select all to delete. It using ID to delete item.
Since I didn't got much but according to the heading of the question which says to remove an item in list I can suggest you to use notifyDataSetChanged() whenever you are removing a view so that your listview could update itself whenever its changed
A little code which demonstrate this task is
adapter = new MyListAdapter(this);
lv = (ListView) findViewById(android.R.id.list);
lv.setAdapter(adapter);
lv.setOnItemClickListener(new OnItemClickListener() {
public void onItemClick(AdapterView<?> a, View v, int position, long id) {
AlertDialog.Builder adb=new AlertDialog.Builder(MyActivity.this);
adb.setTitle("Delete?");
adb.setMessage("Are you sure you want to delete " + position);
final int positionToRemove = position;
adb.setNegativeButton("Cancel", null);
adb.setPositiveButton("Ok", new AlertDialog.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
MyDataObject.remove(positionToRemove);
adapter.notifyDataSetChanged();
}});
adb.show();
}
});
I am updating and saving an array of values in SharedPreferences from within a Settings activity. Specifically, from an AlertDialog in an onCLickListener for a ListView. The changes seem to be saved fine - i.e. they are still intact after I close and re-open the MainActivity, but as soon as my app is released from memory and restarted the SharedPreferences revert to their previous state.
I read somewhere that calling editor.clear() before editor.commit() can prevent this happening, but this also has the effect of deleting all of the other values in my SharedPreferences (i.e. the ones that I am not editing in this code).
Can anyone explain why I am losing my SharedPreference updates, and how I can fix this?
The code is below:
final ListView lv = (ListView) findViewById(R.id.list_folders);
lv.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view,
int position, long id) {
// ListView Clicked item index
int itemPosition = position;
// ListView Clicked item value
final String itemValue = (String) lv.getItemAtPosition(position);
// Ask the user to confirm deletion of the item using an AlertDialog
AlertDialog.Builder builder = new AlertDialog.Builder(SourceFolders.this);
builder.setTitle("Confirm");
builder.setMessage("Remove " + itemValue + "?");
builder.setPositiveButton("YES", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
// Yes - remove the current item from SharedPreferences
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(SourceFolders.this);
Set<String> set = prefs.getStringSet("source_folders", null);
if (set == null) {
dialog.dismiss(); // List of folders in Preferences is empty - shouldn't happen
}
// Remove the selected item from the list
set.remove(itemValue);
// Update Shared Preferences
SharedPreferences.Editor edit = prefs.edit();
edit.putStringSet("source_folders", set);
edit.commit();
folderlist = new ArrayList<String>(set);
refreshListViewFromPrefs();
dialog.dismiss();
}
});
builder.setNegativeButton("NO", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
// Do nothing
dialog.dismiss();
}
});
AlertDialog alert = builder.create();
alert.show();
}
});
This is a question that has been floating around on StackOverflow for a little while, and before you mark this question as a duplicate I am aware of this link. However, this question is vague, has no code, and doesn't seem to have been fully answered.
So on to my question:
I have a ListFragment (MainListFragment) that, onLongItemClick, opens up a Contextual Action Bar. One of the menu items within this Contextual Action Bar enables the deletion of the ListView item that was long-clicked.
Within the class that implements ActionMode.Callback, I am able to delete the long-clicked item, but I need the ListView to refresh itself after this deletion so users don't have to switch Fragments to see the effects of the deletion.
Here you can see my onLongItemClickListener within MainListFragment:
this.getListView().setOnItemLongClickListener(new OnItemLongClickListener(){
#Override
public boolean onItemLongClick(AdapterView<?> adapter, View view,
int pos, long id) {
// TODO Auto-generated method stub
Log.d("My Debug Bitches", "made it to the listener");
MainListContextualMenu menu = new MainListContextualMenu();
//view.startActionMode(menu);
ActionMode mode = getActivity().startActionMode(menu);
Object[] tags = new Object[2];
tags[0] = view.getRootView().getContext();
tags[1] = pos;
mode.setTag(tags);
//view.setSelected(true);
return true;
}
});
And here is my ActionMode.Callback-implementing class:
public class MainListContextualMenu implements ActionMode.Callback{
#Override
public boolean onActionItemClicked(ActionMode mode, MenuItem item) {
// TODO Auto-generated method stub
switch(item.getItemId()){
case R.id.main_list_contextual_menu_delete:
//MainActivity activity = (MainActivity) mode.getCustomView().getContext();
//activity.getLists().remove(mode.getTag());
Object[] tags = (Object[]) mode.getTag();
MainActivity activity = (MainActivity) tags[0];
int index = (Integer) tags[1];
//Log.d("My Debug Bitches","" +index);
//Log.d("My Debug Bitches", "size before " + activity.getLists().size());
activity.getLists().remove(index);
//Log.d("My Debug Bitches", "size after " + activity.getLists().size());
break;
case R.id.main_list_contextual_menu_edit:
break;
}
return false;
}
#Override
public boolean onCreateActionMode(ActionMode mode, Menu menu) {
// TODO Auto-generated method stub
MenuInflater inflater = mode.getMenuInflater();
inflater.inflate(R.menu.main_list_contextual_menu, menu);
Log.d("My Debug Bitches", "menu inflated");
return true;
}
#Override
public void onDestroyActionMode(ActionMode mode) {
// TODO Auto-generated method stub
Object[] tags = (Object[]) mode.getTag();
MainActivity activity = (MainActivity) tags[0];
ListView view = (ListView) activity.getCurrentFocus();
}
#Override
public boolean onPrepareActionMode(ActionMode mode, Menu menu) {
// TODO Auto-generated method stub
return false;
}
}
I have tried using invalidateViews() within my onDestroyActionMode() method to no avail, and I have seen others recommend notifyDataSetChange().
However, I am not sure how to use these solutions within an ActionMode.Callback. If you look at my onLongClick() method, I use mode.setTag() to pass both the MainActivity and the position of the ListView item that was clicked. Is this good form?
I just want to be able to refresh the ListView from MainListFragment within the ActionMode.Callback.onDestroyActionMode() method.
Has anyone gotten this to work before, and if so, does he/she have any suggestions?
I am suggesting this answer according to your implementation,there may be a better way, first create a method getAdapter() which will return your adapter which you are using for your listview.
ArrayAdapter adapter;
public ArrayAdapter getAdapter()
{
// TODO Auto-generated method stub
return adapter;
}
Now change your code like this this, add this activity.getAdapter().notifyDataSetChanged();
case R.id.main_list_contextual_menu_delete:
//MainActivity activity = (MainActivity) mode.getCustomView().getContext();
//activity.getLists().remove(mode.getTag());
Object[] tags = (Object[]) mode.getTag();
MainActivity activity = (MainActivity) tags[0];
int index = (Integer) tags[1];
//Log.d("My Debug Bitches","" +index);
//Log.d("My Debug Bitches", "size before " + activity.getLists().size());
activity.getLists().remove(index);
activity.getAdapter().notifyDataSetChanged();
//Log.d("My Debug Bitches", "size after " + activity.getLists().size());
break;
Hope it will help.
I've been working at this all day, and I'm really close but just can't get this to work. I have a button that pulls up an AlertDialog populated with saved entries that include Name and Price. Right now, I can click an item in the Dialog and have it automatically fill in the Name and Price fields in my activity. I want to also be able to long press an item and receive an option to delete it. This is my first try at an Android app, and a lot of this is repurposed from the Notepad Tutorial. Two things I can't figure out:
1) Is my registerForContextMenu sufficient/correct?
2) What am I doing wrong with my onCreateContextMenu?
Thanks.
savedItems.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
cDbHelper.open();
mNotesCursor = cDbHelper.fetchAllSaved();
startManagingCursor(mNotesCursor);
// Create an array of names and corresponding prices from db
String[] from = new String[]{SavedItemsDbAdapter.KEY_NAME, SavedItemsDbAdapter.KEY_PRICE};
// and an array of the fields we want to bind those fields to
int[] to = new int[]{R.id.text1, R.id.text2};
// Now create a simple cursor adapter and set it to display
SimpleCursorAdapter saved =
new SimpleCursorAdapter(NewEntry.this, R.layout.saved_row, mNotesCursor, from, to);
// Build an AlertDialog to hold this list
AlertDialog.Builder builder = new AlertDialog.Builder(NewEntry.this);
builder.setTitle("Choose from list");
// IS THIS SUFFICIENT TO REGISTER FOR CONTEXT MENU?
registerForContextMenu(v);
builder.setAdapter(saved, new DialogInterface.OnClickListener() {
// When an item from the list is clicked, it automatically populates the name and price fields in activity
#Override
public void onClick(DialogInterface dialog, int item) {
Cursor c = mNotesCursor;
c.moveToPosition(item);
Intent i = new Intent(NewEntry.this, NewEntry.class);
i.putExtra("name", c.getString(
c.getColumnIndexOrThrow(SavedItemsDbAdapter.KEY_NAME)));
i.putExtra("price", c.getString(
c.getColumnIndexOrThrow(SavedItemsDbAdapter.KEY_PRICE)));
startActivityForResult(i, ACTIVITY_AUTO);
finish();
}
// TRYING AND FAILING TO SET UP A CONTEXT MENU - the goal is to be able to long press,
// have a "Delete?" option pop up, which will delete the entry when clicked
#Override
public void onCreateContextMenu(ContextMenu menu, View v,
ContextMenuInfo menuInfo) {
super.onCreateContextMenu(menu, v, menuInfo);
menu.add(0, DELETE_ID, 0, R.string.menu_delete);
}
public boolean onContextItemSelected(MenuItem item) {
switch(item.getItemId()) {
case DELETE_ID:
AdapterContextMenuInfo info = (AdapterContextMenuInfo) item.getMenuInfo();
mDbHelper.deleteItem(info.id);
return true;
}
return false;
}
});
AlertDialog alert = builder.create();
alert.show();
}
});
}
I just found
#Override
public boolean onMenuItemSelected(int featureId, MenuItem item) {
to be called, but not
#Override
public boolean onContextItemSelected(MenuItem item) {
in my subclassed AlertDialog:
public class MyAlertDialog extends AlertDialog implements
OnCreateContextMenuListener {
Perhaps this is useful to someone else as I'm pretty sure you have meanwhile solved your problem at hand.
You only need implement the following function. It will work.
#Override
public void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo)
{
Log.e(LOGTAG, "Tao menu");
if(v == expList)
{
super.onCreateContextMenu(menu, v, menuInfo);
//AdapterContextMenuInfo aInfo = (AdapterContextMenuInfo) menuInfo;
// We know that each row in the adapter is a Map
//HashMap map = (HashMap) simpleAdpt.getItem(aInfo.position);
menu.setHeaderTitle("Options");
menu.add(1, 1, 1, "Reprint");
menu.add(1, 2, 1, "Void");
menu.getItem(0).setOnMenuItemClickListener(new OnMenuItemClickListener()
{
public boolean onMenuItemClick(MenuItem clickedItem)
{
return true;
}
});
menu.getItem(1).setOnMenuItemClickListener(new OnMenuItemClickListener()
{
public boolean onMenuItemClick(MenuItem clickedItem)
{
return true;
}
});
}
}
Is my registerForContextMenu sufficient/correct?
You are registering a context menu for whatever savedItems is. If that is what you want the context menu on, then you are OK.
If your goal is to have a context menu on the items in the list in the dialog, your approach is wrong. You will not be able to use AlertDialog.Builder. You will need to create a custom subclass of AlertDialog, so you can override onCreateContextMenu() there.