Basti
Basti

Reputation: 1190

Show android dialogs in sequence

In my app some dialogs are opened from different places at the same time. (Some dialogs are self build fragments others AlertDialogs) This causes some of them to disappear, because the last called dialog closes all previously opened ones.

Is there a nice way to make them queue up and show after each other instead of glitch out like that?

I was considering making my own dialog class which instead of disposing the dialog it load up the next one and disposes once none are left in the queue. I am hoping there is an easier way to solve my problem without so much effort behind it.

Upvotes: 5

Views: 3768

Answers (2)

Dziugas
Dziugas

Reputation: 1570

You could try a solution that your very own question hinted at; a queue. This solution should work with any dialogs which extend the Dialog class.

To do so add a Dialog queue to your activity as a global variable:

LinkedBlockingQueue<Dialog> dialogsToShow = new LinkedBlockingQueue<>();

In addition to the above, implement, in the Activity that wants to show the dialogs, a method called showDialog() which accepts the target dialog as a parameter. This method will add the dialog to the queue and also ensure that the dialog calls the next one in the queue to be shown after it is dismissed.

void showDialog(final Dialog dialog) {
        if(dialogsToShow.isEmpty()) {
            dialog.show();
        }
        dialogsToShow.offer(dialog);
        dialog.setOnDismissListener((d) -> {
            dialogsToShow.remove(dialog);
            if(!dialogsToShow.isEmpty()) {
                dialogsToShow.peek().show();
            }
        }); 
}

Please note that I didn't test the above code.

Upvotes: 11

Reaz Murshed
Reaz Murshed

Reputation: 24211

You don't actually have to implement your own implementation of Dialog here in this case as far as I have understood. You just have to maintain your own queue data structure in sqlite database or somewhere else. When a dialog is popped up, show the first one from your queue and then on pressing positive button you need to dequeue the content you just have shown and then show the next one until the queue is empty.

Call dialog.dismiss() when no other content is left in your queue. This does not require implementing your own custom dialog. You can add an onShowListener to the AlertDialog where you can then override the onClickListener of the button.

final AlertDialog dialog = new AlertDialog.Builder(context)
        .setView(v)
        .setTitle(R.string.my_title)
        .setPositiveButton(android.R.string.ok, null) // Set to null. We override the onclick
        .setNegativeButton(android.R.string.cancel, null)
        .create();

dialog.setOnShowListener(new DialogInterface.OnShowListener() {

    @Override
    public void onShow(DialogInterface dialogInterface) {

        Button button = ((AlertDialog) dialog).getButton(AlertDialog.BUTTON_POSITIVE);
        button.setOnClickListener(new View.OnClickListener() {

            @Override
            public void onClick(View view) {
                // TODO: Show content and dequeue

                // Dismiss once all contents are shown 
                dialog.dismiss();
            }
        });
    }
});

dialog.show();

Hope that helps.

Update

As far as I could understand, you need to show Dialog with new content along with a new layout each time you create those. In that case, you might consider achieve this behaviour in several ways. I would suggest using a LocalBroadcastManager.

In your Activity, create a BroadcastReceiver and register it in your onCreate function.

@Override
public void onCreate(Bundle savedInstanceState) {

  ...

  // Register to receive messages.
  // We are registering an observer (mMessageReceiver) to receive Intents
  // with actions named "open-next-dialog".
  LocalBroadcastManager.getInstance(this).registerReceiver(mMessageReceiver,
      new IntentFilter("open-next-dialog"));
}

// Our handler for received Intents. This will be called whenever an Intent
// with an action named "open-next-dialog" is broadcasted.
private BroadcastReceiver mMessageReceiver = new BroadcastReceiver() {
  @Override
  public void onReceive(Context context, Intent intent) {
    // Get extra data included in the Intent
    String message = intent.getStringExtra("message");
    int layoutId = intent.getIntExtra("layout_id");
    showDialog(layoutId, message);
  }
};

@Override
protected void onDestroy() {
  // Unregister since the activity is about to be closed.
  LocalBroadcastManager.getInstance(this).unregisterReceiver(mMessageReceiver);
  super.onDestroy();
}

Now when a Dialog is clicked, you need to send a broadcast after dismissing the Dialog. So the onClick function of your Dialog will look like.

@Override
public void onClick(View view) {
    // TODO: Do whatever you want to do in your onClick
    // And then Dismiss the dialog 
    dialog.dismiss();
    openNextDialogIfAny();
}

Don't forget to add openNextDialogIfAny function in your Activity as well which will trigger the next Dialog.

// Send an Intent with an action named "open-next-dialog". The Intent sent should be received by your Activity
private void openNextDialogIfAny() {
  if(messageStack.isEmpty()) return; // No more dialogs to be shown.

  Intent intent = new Intent("open-next-dialog");
  intent.putExtra("message", messageStack.pop());
  intent.putExtra("layout_id", layoutStack.pop());
  LocalBroadcastManager.getInstance(YourActivity.this).sendBroadcast(intent);
}

Upvotes: 0

Related Questions