showDialog() managing two consecutive dialogs, rotation event and screen saver / HOME button
Has anyone managed to make dialogs which can handle all of the following requirements:
- Be preserved during rotation changes (the android:configChanges attribute will not be used)
- Be preserved when activating the screen saver (or go to HOME) and coming back to the Activity
- Displaying one dialog right after the other is dismissed.
- Displaying one dialog right after the other is dismissed adding rotations on both dialogs.
Explanation for the two consecutive dialogs: One dialog shows with a question "are you sure you want to..?". Then at positive response from the user perform the action, and present the result in a dialog. This should be a very common situation indeed.
Here's some of what I've tried:
Using AlertDialog.show() instead of showDialog(). Successfully saving the state (including it's click actions) in on onSaveInstanceState to read it in onCreate. In this way the dialogs were recreated after rotation. There were no problems displaying the two dialogs in a row either, i.e bullet 2 and 3. Last thing however didn't work. To not leak window I had to remove the dialog in onSaveInstanceState (it would be removed anyway). Then I found no way of recreating it when coming back from having activated the screen saver on my phone. Someone knows which code will be called at returning after screen saver? When I tested it neither onCreate, onResume, onRestoreInstanceState etc were called.
Using the showDialog methods. This works fine for bullet 1 and 3, i.e the state is preserved during rotation (if using static dialog references) and it also handles the screen saver correctly. However bullet 2 is problematic. Either the second dialog does not want to show at all because of "Window already focused, ignoring focus gain ..", or the dialogs get mixed up, or the action of the first dialog is performed without asking the user of it. To demonstrate some of the issues I created the quick test code below.
Running this test code on the emulator and rotating the second dialog will make it leak window and then the first dialog be shown again.
main.xml
<Button android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Perform action"
android:onClick="performAction" />
public class ShowDialogTest extends Activity {
private static final int DIALOG_QUESTION = 0;
private static final int DIALOG_INFO = 1;
private static AlertDialog questionDialog;
private static AlertDialog infoDialog;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
}
@Override
public void onResume() {
super.onResume();
showQuestionDialog();
}
/**
* Button click which will bring the dialogs back up.
*/
public void performAction(View v) {
showQuestionDialog();
}
private void showInfoDialog() {
createInfoDialog();
showDialog(DIALOG_INFO);
}
private void showQuestionDialog() {
createQuestionDialog();
showDialog(DIALOG_QUESTION);
}
private void createInfoDialog() {
infoDialog = new AlertDialog.Builder(this).create();
infoDialog.setTitle("The result");
infoDialog.setMessage("Info about the result of the action");
DialogInterface.OnClickListener onClick1 = new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
}
};
infoDialog.setButton(DialogInterface.BUTTON_POSITIVE, "OK", onClick1);
}
private void createQuestionDialog() {
questionDialog = new AlertDialog.Builder(this).create();
questionDialog.setTitle("A Question");
questionDialog.setMessage("Are you sure?");
DialogInterface.OnClickListener onClick = new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
// Do something here ..
// Alert the user about the result
showInfoDialog();
}
};
DialogInterface.OnClickListener onCancelClick = new OnClickListener() {
public void onClick(DialogInterface dialog, int which)开发者_运维技巧 {
}
};
questionDialog
.setButton(DialogInterface.BUTTON_POSITIVE, "OK", onClick);
questionDialog.setButton(DialogInterface.BUTTON_NEGATIVE, "Cancel",
onCancelClick);
}
@Override
protected Dialog onCreateDialog(int id) {
switch (id) {
case DIALOG_QUESTION:
return questionDialog;
case DIALOG_INFO:
return infoDialog;
}
// Error case (should be handled better ;)
return new Dialog(this);
}
PS. The reason for using the create dialog methods is because the Activity need to put custom text and button actions to the dialog before displaying it. This is not shown in the code. DS
I've read some other forum posts and tried other things. Please only answer if you know how to fix this without creating new problems. You are of course more than welcome to put suggestions in a comment.
Thank you for your time
try this:
@Override
protected Dialog onCreateDialog(int id) {
AlertDialog dialog = new AlertDialog.Builder(this).create();
if(id == yourCodeValue){
LayoutInflater inflator = LayoutInflater.from(context);
View view = inflator.inflate(R.layout.yourview, null);
Button positive = (Button)view.findViewById(R.id.btn_positive);
Button negative = (Button)view.findViewById(R.id.btn_negative);
positive.setOnClickListener(new Button.OnClickListener(){
public void onClick(View v) {
removeDialog(0);
}
});
negative.setOnClickListener(new Button.OnClickListener(){
public void onClick(View v) {
removeDialog(0);
}
});
dialog.setView(view);
}
return dialog;
}
Show this dialog using showDialog(int value)
.
It will solve your first 2 points and the 3 and 4th point it's upto you how you handle it..
The main problem was that I declared the dialogs in the Activity instead of in the onCreateDialog() method. I.e don't do this:
private static AlertDialog questionDialog;
Make sure to also declare the OnClickListener object in the onCreateDialog() method.
This makes sure bullet 1, 3 and 4 is fulfilled. Since showDialog() is used bullet 2 is fulfilled. This simply didn't work with the AlertDialog.show() method.
精彩评论