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.
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.
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.
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? 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.
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.
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);
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With