Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Show android dialogs in sequence

Tags:

android

dialog

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.

like image 958
Basti Avatar asked Mar 15 '18 20:03

Basti


People also ask

How do you show DialogFragment?

Showing the DialogFragment It is not necessary to manually create a FragmentTransaction to display your DialogFragment . Instead, use the show() method to display your dialog. You can pass a reference to a FragmentManager and a String to use as a FragmentTransaction tag.

What is the difference between dialog and DialogFragment?

Dialog: A dialog is a small window that prompts the user to make a decision or enter additional information. DialogFragment: A DialogFragment is a special fragment subclass that is designed for creating and hosting dialogs.

What is DialogFragment used for?

DialogFragment is a utility class which extends the Fragment class. It is a part of the v4 support library and is used to display an overlay modal window within an activity that floats on top of the rest of the content. Essentially a DialogFragment displays a Dialog but inside a Fragment.

How do you check if the current activity has a dialog in front?

How do you check if the current activity has a dialog in front? You can override activity method onWindowFocusChanged(boolean hasFocus) and track the state of your activity. Normally, if some alert dialog is shown above your activity, the activity does not get onPause() and onResume() events.


2 Answers

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.

like image 99
Dziugas Avatar answered Sep 28 '22 04:09

Dziugas


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);
}
like image 43
Reaz Murshed Avatar answered Sep 28 '22 03:09

Reaz Murshed