Reputation: 1190
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
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
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