LogCat is telling me that my Application is unable to display a window, since "token null is not for an application". This is the code it's having problems with:
AlertDialog.Builder builder = new AlertDialog.Builder(getApplicationContext());
builder.setMessage("Er du sikker?\n" + taskList.get(position) +"\nvil starte med det samme hvis du trykker 'Ja'");
.setPositiveButton("Ja", dialogClickListener);
.setNegativeButton("Nej", dialogClickListener);
.show();
Ignore the Danish, that's just for our users. It's on .show() it starts acting up and throws FATAL. I looked this same issue up all over StackOverflow and found that it's likely a problem in getApplicationContext(), but I've been unable to figure out how to get the context of use otherwise.
I'll leave some of the code it's supposed to be used on here in case you need it.
lv.setOnItemClickListener(new AdapterView.OnItemClickListener() { //give our listView an onItemClickListener
#Override
public void onItemClick(AdapterView<?> parent, View view, final int position, long id) { //when you click on an item
DialogInterface.OnClickListener dialogClickListener = new DialogInterface.OnClickListener() { //it should open a dialog but doesn't
#Override
public void onClick(DialogInterface dialog, int which) { //if you click
switch (which){ //"ja"
case DialogInterface.BUTTON_POSITIVE:
Intent i = new Intent(getApplicationContext(), PlayScreen.class); //start a new intent to open PlayScreen
i.putExtra("task", taskList.get(position)); //with the task out of the ArrayList that was clicked
startActivity(i);
break;
case DialogInterface.BUTTON_NEGATIVE: //nothing
break;
}
}
};
Basically I think the problem is I don't know how to provide builder with the context it needs. It may have something to do with me being new to Android development.
Replace getApplicationContext() with this, assuming that this is an Activity. Activity inherits from Context, and you need to use an Activity to show a Dialog.
I am an idiot.
Basically I forgot I was using it in the context of a ListView, meaning I was attempting to use it with an activity. I got the context from the listview..
lv.getContext()
Sorry for wasting your time, if only I had spent 5 more minutes figuring out my position in the code...
Related
So right now I have a custom listview adapter that adds another row when the user selects a item. The thing is, each item in the row should have a modification button where they can choose to add whatever modification it is (can choose more than one modification)
This is a food ordering app that when the item is selected, there should be another button in the list labeled "Modify", where a pop-up comes up and allows the user to choose what modification it wants by using checkbox. ("Less salt", "More sauce", etc). Each modification list is the same for each dish. When the user exits the popup and clicks on the same modify button, the checkboxes checked should stay there.
I originally created a Popup class where when the button is selected, there is an intent to jump to that Popup activity, but I couldn't find the relationship between the custom adapter and the Popup activity. I also tried using an AlertDialog to replace the Popup window, but could not find a way to save all the checked items and show which ones were selected before.
Here's my code
modifyBtn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
AlertDialog.Builder builder = new AlertDialog.Builder(context);
builder.setTitle("Modification");
final CharSequence[] modify_items = orderClass.getModifyList()
.toArray(new CharSequence[orderClass.getModifyList().size()]);
builder.setMultiChoiceItems(modify_items, null, new DialogInterface.OnMultiChoiceClickListener() {
#Override
public void onClick(DialogInterface dialog, int indexSelected, boolean isChecked) {
if(isChecked){
selectedList.add(indexSelected);
selectedItems.set(position, selectedList);
}
else if(selectedList.contains(indexSelected)){
selectedList.remove(Integer.valueOf(indexSelected));
selectedItems.set(position, selectedList);
}
}
})
.setPositiveButton("OK", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
}
})
.setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
}
});
AlertDialog dialog = builder.create();
dialog.show();
Log.d("dialog", "Showing dialog");
}
});
return view;
}
You need to put data in a holder structure(its kinda a class that holds variables)
then you can show data by index and theres is a relation between the list view index shown and the data index so when is a list view cell clicked you get the position then find it in the structure and post it to another activity or anything else to modify it remember you have to declare a flag to launch the activity else the app will crash i think its called activtyoutofbound index or something like this
Ok,this is going to get a bit complicated, but hang with me. I have the following scenario that I cannot get to work:
Prompt the user to save (ok or cancel)
In onclick for "ok", do a Async task to get some data. Do this synchronously
Then create a custom dialog to display that data to prompt the user for more info [THIS PART DOES NOT WORK)
The do another Async task where I save the data.
So, is there an inherent problem with creating a custom Dialog inside of a AlertDialog?
The behavior that happens is that all operations run, and at the end the custom Dialog briefly appears and then disappears. It should show up before the last Async task and not let the Async task execute before it has gathered the data needed.
I have simplified the problem code to this:
AlertDialog.Builder submitDialog = new AlertDialog.Builder(this);
submitDialog.setMessage("Are you sure you want to end this Preview of the form? It will no longer be availabe for editing");
}
else {
submitDialog.setTitle("Submit?");
submitDialog.setMessage("Are you sure?");
}
submitDialog.setNegativeButton("Cancel", null);
submitDialog.setPositiveButton("OK", new AlertDialog.OnClickListener() {
public void onClick(DialogInterface dialog, int arg1) {
// =============================
// 1st Async
// =============================
// Make synchronous since need data. Must be a task cause hitting server
Test test = null;
try {
test = new workflowTask().execute().get();
}
catch (Exception ex) {
// nothing
}
// =============================
// Customer Dialog Get more info
// =============================
// Prompt for data here...
String[] listContent = {"test1#test.com", "test2#test.com"};
// custom dialog
Dialog dialog = new Dialog(MyActivity.this);
dialog.setContentView(R.layout.dialog_email_picker);
dialog.setTitle("Select email and enter comments");
ListView emails = (ListView) dialog.findViewById(R.id.emaillist);
ArrayAdapter<String> adapter = new ArrayAdapter<String> (MyActivity.this, android.R.layout.simple_list_item_1, listContent);
emails.setAdapter(adapter);
emails.setOnItemClickListener(new OnItemClickListener(){
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
Toast.makeText(getApplicationContext(), parent.getItemAtPosition(position).toString() + " clicked", Toast.LENGTH_LONG).show();
}
});
Button dialogButton = (Button) dialog.findViewById(R.id.dialogButtonOK);
// if button is clicked, close the custom dialog
dialogButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Toast.makeText(getApplicationContext(), "ok clicked", Toast.LENGTH_LONG).show();
}
}
});
dialog.show();
// =============================
// 2nd Async
// =============================
new submitFormResultTask().execute();
}
}
});
submitDialog.show();
Why you don't use a viewflipper in your "unique" custom dialog? so after first click on OK you can check if first page is visible and then you can show second page and only from this moment if user press on OK you can recall the dismiss() method.
In this way, you can perform a sort of wizard with possibility to return on first view if user needs to change something. Make sense?
Just for future reference the way I solved this was to actually call the AsyncTask in the onClick of the 2nd Dialog. Kind of ugly, but I could not get anything else to work. I would have thought that so long as it was a modal dialog being run that Android would pause till its work was accomplished - it did not, it just ran the next line of code (2nd AsyncTask). So it looks something like:
AlertDialog ->
AsyncTask.get() (so synchronous)
Customer Dialog
onClick->
2nd AsyncTask
I have a little problem with a Dialog.
It's a ListView of Videos with thumbnails that load the videos with an Adapter. The ListView register an OnItemClickListener and inside the OnClickItem method I try to raise the Dialog.
I've tried with various types of Dialog but nothing happened. A simplified piece of code it's here:
public class ListOfVideos extends Activity {
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.list_of_videos);
init_phone_video_grid();
}
private void init_phone_video_grid() {
// Here's some code for the video reading
// The ListView
videolist = (ListView) findViewById(R.id.PhoneVideoList);
videolist.setAdapter(new VideoAdapter(getApplicationContext()));
videolist.setOnItemClickListener(new OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View v, int position, long id) {
// Here's some code for the video reading
/** ============= Here's the problem ================ **/
AlertDialog.Builder builder = new AlertDialog.Builder(v.getContext());
builder.setMessage("Example Message")
.setTitle("This is the title!!")
.setCancelable(false)
.setNeutralButton("Ok",
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
dialog.cancel();
}
});
AlertDialog alert = builder.create();
alert.show();
System.out.println("[debug]" + "Open File " + filename);
}
});
}
The list of videos load perfectly. But when I click on an Item:
The Dialog does not show
I got a error message in the LogCat, that state: "show() Dialog's window is null!"
The println debug message, appears ok in the LogCat
I have searched for that message error, but there's not much information.
I think the problem could be on the Context that receive the Builder, but I'm stuck on this point.
Any advice will be apreciated
That error message is saying that the Context given to the AlertDialog.Builder has no attached window, which Dialogs need as a UI anchor, basically. An Activity is what should be used for such a Context, as it will have the required window.
Without seeing VideoAdapter's code, the root cause is presumably new VideoAdapter(getApplicationContext()), which is handing your VideoAdapter the application Context to build Views with. That likely means that the v passed into onItemClick() is one such View, and v.getContext() is returning that application Context in new AlertDialog.Builder(v.getContext()).
That application Context does not have a window but your Activity does, as mentioned. Furthermore, the Activity is actually what you want to give to VideoAdapter to build Views with anyway, to ensure that they are created with the correct theme and styling. Change that relevant line to:
videolist.setAdapter(new VideoAdapter(ListOfVideos.this));
That alone might solve the issue, depending on what VideoAdapter does internally. However, it's arguably better to specify the Activity again in the AlertDialog.Builder constructor call, just so there's no question:
AlertDialog.Builder builder = new AlertDialog.Builder(ListOfVideos.this);
As a final note, whenever a Context is needed for any UI component, you usually want to use the immediately available Activity.
Here is a example of How to create dialog box..
String message = "Hello";
AlertDialog.Builder alt_bld = new AlertDialog.Builder(
CurrentActi.this);
alt_bld.setTitle("Alert")
.setMessage(message)
.setCancelable(false)
.setPositiveButton("Yes",
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
//here right the code that you want perform onClick
dialog.cancel();
}
})
.setNegativeButton("No", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
dialog.cancel();
}
});
AlertDialog alert = alt_bld.create();
alert.setTitle("Alert");
alert.show();
May be it will help you..
I show dialog of checkboxes (list retrieved from DB) to allow user select, which rows remove. Because android dialog caching, I need to refresh count and names of checkboxes.
In my onCreateDialog:
dialog = new AlertDialog.Builder( this )
.setTitle( "Remove Items" )
.setMultiChoiceItems( items, _selections, new OnMultiChoiceClickListener(){public void onClick (DialogInterface dialog, int which, boolean isChecked){}} )
.setPositiveButton("Smazat", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
dialog.dismiss();
deleteRow(_selections);
} })
.setNegativeButton("Storno", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
dialog.dismiss();
} })
.create();
How refresh values (items,_selections) in onPrepareDialog?
I tried invalidate views, hoping that force android to load items againg(dont work neither), but I think its bad choice as well as removing dialog and recreating.
protected void onPrepareDialog(final int id, final Dialog dialog) {
switch (id) {
case REMOVE_DIALOG_ID:
ListView lv = ((AlertDialog) dialog).getListView();
lv.invalidateViews();
break;
}
Thanks for any ideas!
When you create a list of items using AlertDialog.Builder, it internally takes that and creates a ListAdapater that is dependent on the type of data you passed. Since "items" in your example doesn't look like a resource ID, I'm assuming it's either a CharSequence[] or a Cursor. If you provide more information about what "items" is, I can provide a more concrete example.
For CharSequence[] (like String[]) data, Builder creates an ArrayAdapter instance.
For Cursor data, Builder creates a CursorAdapter
You will need to obtain a reference to this ListAdapter using getListView().getAdapter() on the AlertDialog instance.
For a Cursor, you can get away with calling notifyDataSetChanged() after you have called requery() to update the data set.
Since you can't "update" an array with new data (changing the pointer to a new instance is not the same thing...the instance that the adapter is pointing to stays unchanged), this case is a little more work. You will need to call the add(), clear(), etc. methods of the adapter to remove invalid items and add the updates ones. With the adapters data set fully updated, you may now call notifyDataSetChanged().
Hope that Helps!
I spent lot of time to search for same solution and eventually fixed my problem with simple stuff after trying to use onPrepareDialog too
I use the removeDialog(int) function of the Activity. When a dialog is dismissed, the Activity basically stores the state of the dialog (for performance reasons I would imagine). Calling removeDialog(int) on the dialog forces the activity to unload all references for the dialog and dismisses it from the screen if it's being shown.
did this when my activity lost focus simply add:
public void onStop() {
removeDialog(Id_Dial);
return;
}
My technique is to create an adapter with empty data in onCreateDialog and completely replace the adapter during onPreparDialog.
Example:
#Override
protected Dialog onCreateDialog(int id) {
switch (id) {
case DialogMergeRegion:
title = ...
return new AlertDialog.Builder(BaseDataTabView.this)
.setTitle(title)
.setMultiChoiceItems(new CharSequence[0], null,
new OnMultiChoiceClickListener() {
#Override
public void onClick(DialogInterface dialog, int which, boolean isChecked) {
manageSelectionList(which, isChecked);
}
})
//...
.create();
}
}
#Override
protected void onPrepareDialog(int id, Dialog dialog) {
super.onPrepareDialog(id, dialog);
switch (id) {
case DialogMergeRegion: {
List<String> regionNames = ...// get the data
ListAdapter mergeAdapter = new ArrayAdapter<String>(this, android.R.layout.select_dialog_multichoice, regionNames);
AlertDialog ad = (AlertDialog) dialog;
ad.getListView().setAdapter(mergeAdapter);
break;
}
}
In your onPrepareDialog method, instead of using invalidateViews(), you should try getting the adapter of the ListView and try calling either notifyDataSetChanged() or notifyDataSetInvalidated(). Does that help?
I'm using and ArrayAdapter to populate a ListView. After selecting and item, it displays a confirmation Y/N dialog. If the user's choice is negative, then he should be able to select another item showing the same dialog. And so on.
Here's my code:
lView.setOnItemClickListener(new OnItemClickListener() {
public void onItemClick(final AdapterView<?> parent, final View v, final int index, final long id) {
Toast.makeText("Selected file"+ mFiles.get(index).getfileName(),
Toast.LENGTH_SHORT).show();
SelectedFile = mFiles.get(index);
showDialog(DIALOG_CONFIRMIMPORT_ID);
}
});
The weird thing is that while the "Toast" shows the clicked item every time, only the first selected item since the Activity is initiated is being passed to "SelectedFile". No matter how many times you click a diferent item, "SelectedFile" always assumes the same value, the value of the first clicked item, outside of this code.
Heres's my Dialog code:
Protected Dialog onCreateDialog(int id) {
switch(id) {
case DIALOG_CONFIRMIMPORT_ID:
{
AlertDialog.Builder builder = new AlertDialog.Builder(this);
String message = String.format(getString(R.string.importstudentfileconfirm),SelectedFile.getfileName());
builder.setMessage(message)
.setCancelable(false)
.setPositiveButton(R.string.yes, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
// Activity.this.finish();
// startActivity(new Intent(Activity.this, LOL.class));
}
})
.setNegativeButton(R.string.no, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
SelectedFile = null;
dismissDialog(DIALOG_CONFIRMIMPORT_ID);
mFiles.notifyAll();
}
});
AlertDialog alert = builder.create();
return alert;
}
}
return null;
}
Thank you very much for any help!
I'm guessing this has something to do with the fact that the onCreateDialog method is only called the first time the dialog is created. So the first time you see the dialog it will have the correct filename.
After onCreateDialog is called, onPrepareDialog(...) is called. onPrepareDialog, allows you to change the dialog after it has been created, but before it gets displayed.
Remember that underneath everything, Android isn't creating a new Dialog for you every time you want to show the DIALOG_CONFIRMIMPORT_ID dialog. It is too computationally expensive to instantiate a new dialog every time. Instead, it creates it once, which causes onCreatDialog to be called, followed by the onPrepareDialog. Every other time the dialog is shown, it only calls onPrepareDialog.
Check out the following article on the Android Developer site. It explains things pretty clearly.
http://developer.android.com/guide/topics/ui/dialogs.html#ShowingADialog
So try using onCreateDialog just for initialization of stuff that won't change between showings of the dialog, then use the onPrepareDialog method to dynamically update the contents of the dialog (i.e. getting the new filename)
Cheers!