How to properly code the confirm dialogs with Android? - java

It's supposed to be a very common thing: having dialog boxes to confirm to proceed the flow of the interaction with users. But the best I can come up with with the information I've dug doesn't seem good to me. I primarily extended DialogFragment (following the first searches for examples) and implement the NoticeDialogListener.
I came to believe that this is not the better way because as far as program flow is concerned, it's very cumbersome. Program flow-wise I understand it can be cumbersome anyway as Dialog appears as another thread from the main to begin with, but I suppose there should be a better way to assign different responding method to different dialog. But I haven't been able to find a way except what's following.
Hopefully I've described my question clearly. Thanks in advance for the response.
public class Confirm extends DialogFragment {
public Dialog onCreateDialog(Bundle savedInstanceState) {
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
builder.setTitle(sQ);
builder
.setPositiveButton(sYes, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
mListener.Yes();
}
})
.setNegativeButton(sNo, null);
return builder.create();
}
public interface NoticeDialogListener {
void Yes();
}
private NoticeDialogListener mListener;
#Override
public void onAttach(Activity activity) {
super.onAttach(activity);
mListener = (NoticeDialogListener) activity;
}
}
public class Main extends ActionBarActivity
implements Confirm.NoticeDialogListener {
...
private int iDialogMode;
private final static int DIALOG_ST_0 = 0;
private final static int DIALOG_ST_1 = DIALOG_ST_1 + 1;
private final static int DIALOG_ST_2 = DIALOG_ST_1 + 1;
#Override
public void Yes() {
switch (iDialogMode) {
case DIALOG_ST_0: // follow up HERE0 for what that dialog prompted
break;
case DIALOG_ST_1: // HERE1: feeling not smart
break;
case DIALOG_ST_2: // HERE2: believe there should be a better way
break;
}
}
public ... State_0_doing_something (...) {
...
Confirm diaBox = new Confirm (...);
iDialogMode = DIALOG_ST_0;
diaBox.show(getSupportFragmentManager(), "State_0");
// what's supposed to continue if confirmed will be followed up in HERE0 in Yes()
}
public ... State_1_doing_something_else (...) {
...
Confirm diaBox = new Confirm (...);
iDialogMode = DIALOG_ST_1;
diaBox.show(getSupportFragmentManager(), "State_2");
// what's supposed to continue if confirmed will be followed up in HERE1 in Yes()
}
public ... State_2_doing_yet_something_else (...) {
...
Confirm diaBox = new Confirm (...);
iDialogMode = DIALOG_ST_2;
diaBox.show(getSupportFragmentManager(), "State_3");
// what's supposed to continue if confirmed will be followed up in HERE2 in Yes()
}
}
I am thinking if I can attach a different click listener to each Confirm dialog box created instead of setting the dialog mode/state using global variable/member like that. Am missing function pointers here...

"By the way, how come I couldn't properly post the beginning declaration and ending bracket in the grey box? "
Add 4 blank spaces before that text, or add the ` character at the beggining and end of the code text.
Example:
Fake code that does nothing
"Program flow-wise I understand it can be cumbersome anyway as Dialog appears as another thread from the main to begin with"
This is basically why its not intended for the user to keep on using dialog boxes. The way I saw most programs so far, is that only actions that could severely delay the application or that could possibly charge the user would use dialogs.
Also, note the Activity lifecycle will make you keep its "state" remembered, this can further add to issues with onPause/onResume with your app.

Solved: the only problem is that it's not as nice looking
AlertDialog.Builder builder = new AlertDialog.Builder(Home.theContext);
builder.setMessage(R.string.confirm_delete);
builder.setCancelable(true);
builder.setPositiveButton(R.string.confirm_yes, vCabDelete());
builder.setNegativeButton(Home.theContext.getString(R.string.confirm_no), null);
AlertDialog dialog = builder.create();
dialog.show();
....
private static DialogInterface.OnClickListener vCabDelete() {
return new DialogInterface.OnClickListener() {
public void onClick(DialogInterface di, int id) {
....
}
};
}

Related

Difference between removeDialog(), dismissDialog() and dismiss()

What is different between removeDialog() and dismiss() and dismissDialog()? because I'm able to use them together without any problem.
And is it matter when implementing DialogInterface.OnClickListener or AlertDialog.OnClickListener?
I searched a lot but couldn't find anything useful.
EDIT:
I'm developing for Android 2.3.
Example code:
public final class OptionsPreference extends PreferenceActivity implements DialogInterface.OnClickListener
{
private AlertDialog noInternetDialog = null;
//...
#Override
protected void onPause()
{
if (this.noInternetDialog != null)
{
Log.d(LOG_TAG, "Destroying noInternetDialog...");
this.noInternetDialog.dismiss(); // X?
removeDialog(DIALOG_NOINTERNET); // X?
dismissDialog(DIALOG_NOINTERNET); // X?
this.noInternetDialog = null;
}
super.onPause();
}
#Override
protected final Dialog onCreateDialog(final int id)
{
switch (id)
{
case DIALOG_NOINTERNET:
{
final AlertDialog.Builder _builder = new AlertDialog.Builder(this).setIcon(android.R.drawable.ic_dialog_info).setMessage(R.string.str_nointernet);
_builder.setCancelable(false);
_builder.setPositiveButton(R.string.str_wifisettings, this);
_builder.setNeutralButton(R.string.str_ok, this);
this.noInternetDialog = _builder.create();
if (!isFinishing())
{
this.noInternetDialog.show();
}
return this.noInternetDialog;
}
// ...
}
dismissDialog(int id) : Dismisses the dialog with the specified id. It only hides the dialog but still keeps the internal references by the Activity which contains this dialog so that it can be restored in future.Deprecated in API 13.
removeDialog(int id) : It also dismisses the dialog with the specified id. Means it hides that particular dialog and in addition cleans up all the references by the Activity and hence cannot be restored in future. Deprecated in API 13.
dismiss() : This method operates on a particular dialog because it is a method of Dialog class. It also dismisses the dialog. You have to own a valid dialog in order to dismiss it else you'll get exception.

Android - OnClick usage in subclass instead of super

I've currently ran into a problem where I have a super class called 'PopupWindow' which initialized a AlertDialog.Builder and shows it to the user. However I have two sub-classes called 'CallInitializePopup' and 'CallReinitializePopup'. I would like to "outsource" the input listener(onClick) to these sub-classes and have code individual to the sub class called there.
Snippet of PopupWindow:
alert = new AlertDialog.Builder(mainActivity);
//'setTitle' simply sets the title of the popup
//'setMessage' sets the description, usually a short instruction on what the user should enter
alert.setTitle(POPUP_LOGIN_TITLE);
alert.setMessage(POPUP_LOGIN_TEXT);
//Initialize EditTexts that will populate our popup and set the hints for each
stockSymbolEditText = new EditText(mainActivity);
stockSymbolEditText.setHint(STOCK_SYMBOL_HINT);
stockPriceEditText = new EditText(mainActivity);
stockPriceEditText.setHint(STOCK_PRICE_HINT);
//These TextViews are only there to give the user guidance on what to include regarding the Spinners(since the Spinners doesn't include hints)
buyOrSellTextView = new TextView(mainActivity);
buyOrSellTextView.setText(" Alert - buy or sell");
LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.FILL_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT);
layoutParams.setMargins(0, 0, 0, 35);
LinearLayout layout = new LinearLayout(mainActivity);
layout.setOrientation(LinearLayout.VERTICAL);
layout.addView(stockSymbolEditText, layoutParams);
layout.addView(stockPriceEditText, layoutParams);
//layout.addView(updateIntervalTextView);
//layout.addView(updateIntervalSpinner);
layout.addView(buyOrSellTextView);
layout.addView(buySellSpinner);
alert.setView(layout);
//Finally we show the popup
alert.show();
My first OnClickListener approach in a sub class:
private void setInputListener()
{
Log.d("setInputListener", "called");
alert.setPositiveButton("Set Alert", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int whichButton) {
//Store the values in current variables
stockSymbol = stockSymbolEditText.getText().toString();
stockPrice = stockPriceEditText.getText().toString();
//String selectedInterval = updateIntervalSpinner.getSelectedItem().toString();
buyOrSell = buySellSpinner.getSelectedItem().toString();
Log.d("Alert dialog submitted", "stockSymbol: " + stockSymbol + " - " + "stockPrice: " + stockPrice + " - " + "buyOrSell: " + buyOrSell);
//Only call 'AssignStockCall()' once stockSymbol, stochPrice, and buyOrSell are initialized in the onClick method
//Create a new StockCall with the new info the user included
AssignNewStockCall();
}
});
//With 'setNegativeButton' we don't want to do anything, the user doesn't want to add a new stock call
alert.setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int whichButton) {
//Canceled
}
});
}
The first approach does not show any buttons, and If I were to take a guess that's because we initialize the inputListener after and in another class than when we initialized the AlertDialog.Builder.
The second approach:
//These onClick classes are used by the PopupWindow class, they are assigned to the specific button by supplying a new instance of the classes
final class CancelOnClickListener implements
DialogInterface.OnClickListener
{
public void onClick(DialogInterface dialog, int which)
{
Log.d("onClick", "Cancel");
}
}
final class SetAlertOnClickListener implements
DialogInterface.OnClickListener
{
public void onClick(DialogInterface dialog, int which)
{
Log.d("onClick", "Set Alert");
}
}
This approach doesn't work with the super class, since the super class needs to know if it's a 'CallInitializePopup' or a 'CallReinitializePopup' and there is no such communication between super and sub class.
Any help is highly appreciated!
You will ran in to many problems like this in future if you will not change your coding style. You should learn SOLID principles of object oriented programming at first. https://en.wikipedia.org/wiki/SOLID_%28object-oriented_design%29 And then study design patterns. Derek Banas youtube channel comes at help, since he very clearly explains design patterns.
In your case you are violating Open Closed principle (from SOLID principles). Super class should not depend on subclass.
I wouldn't use inheritance at all in your situation. If you need different implementation of the same action, use Strategy or State design pattern.
Example using Strategy pattern
class PopUpWindow implements DialogInterface.OnClickListener
{
/**
*
*
* other code
*
**/
/** You don't need two different listers. Use same listener since
you can determine which button has been pressed from *int which* **/
alert.setPositiveButton(this);
alert.setNegativeButton(this);
interface Strategy
{
public void doWork();
}
#Override
public void onClick(DialogInterface dialog, int which)
{
switch(which)
{
case dialog.BUTTON_POSITIVE :
getPositiveButtonStrategy().doWork(); break;
case dialog.BUTTON_NEGATIVE :
getNegativeButtonStrategy().doWork(); break;
}
}
private Strategy getPositiveButtonStrategy()
{
if (/** conditions to implementation NO1**/)
return new Strategy
{
#Override
public void doWork()
{
/** your implementation NO1 **/
}
}
else return new Strategy
{
#Override
public void doWork()
{
/** your implementation NO2 **/
}
};
/** you can implement as much Strategies as you need **/
}
}
private Strategy getNegativeButtonStrategy()
{
if (/** conditions to implementation NO1**/)
return new Strategy
{
#Override
public void doWork()
{
/** your implementation NO1 **/
}
}
else return new Strategy
{
#Override
public void doWork()
{
/** your implementation NO2 **/
}
};
/** everything in your class is available for "Strategies" **/
}
}
}
Without knowing SOLID and Design Patterns it is close to impossible to write understandable, maintainable, bug-free code

Jface Dialog, How to retrieve correctly what button pressed the user?

I'm having troubles with a custom Dialog in Eclipse.
in the first place, I created a Class that extend Dialog.
public class ModificarGrupoBCDialog extends Dialog {
private static final int CANCELAR = 999;
private static final int MODIFICAR = 1;
...
somewhere I create the buttons...
protected void createButtonsForButtonBar(Composite parent) {
this.createButton(parent, MODIFICAR, "Modificar", true);
this.getButton(MODIFICAR).setEnabled(puedeAltaGrupoBC());
this.bt_ok = this.getButton(MODIFICAR);
this.createButton(parent, CANCELAR, "Cancelar", false);
Display display = window.getShell().getDisplay();
Image image = new Image(display, ModificarGrupoBCDialog.class.getResourceAsStream("/icons/modificar.png"));
this.getButton(MODIFICAR).setImage(image);
image = new Image(display, ModificarGrupoBCDialog.class.getResourceAsStream("/icons/cancelar.png"));
this.getButton(CANCELAR).setImage(image);
}
and when the user clicks...
protected void buttonPressed(int buttonId) {
switch (buttonId) {
case MODIFICAR:
// Some Code, for Change Button
break;
case CANCELAR:
setReturnCode(CANCELAR);
close();
break;
}
Finally, this is how I open and get the returnCode, in the caller object.
...
ModificarGrupoBCDialog modificarGrupoBC = new ModificarGrupoBCDialog(window.getShell(), window, gr_bc);
if (modificarGrupoBC.getReturnCode() == Window.OK) {
//... Some code on OK
} else {
//another code when cancel pressed.
}
;
as you can see, after trying a while, I have to write setReturnCode() in CANCELAR switch block, is that OK ?
I spect that Dialog class automatically asign the correct return code.
May be someone could point me to a good sample.
I'm reading Vogela's blog, and may be the solution is to override okPressed() method ?
Best Regards.
The standard dialog sets the return code in two places:
protected void okPressed() {
setReturnCode(OK);
close();
}
protected void cancelPressed() {
setReturnCode(CANCEL);
close();
}
so your code doing:
setReturnCode(xxxx);
close();
should be fine as long as the button id you are using does not match the Cancel or OK button ids.
You could also use the approach used by MessageDialog which simply does this:
protected void buttonPressed(int buttonId) {
setReturnCode(buttonId);
close();
}

AlertDialog example giving errors

I'm new to Java/ Android development (I started learning last night) so it is entirely possible I'm doing something horrendously stupid. However, after more than an hour Googling I've come up with nothing. I'm using Eclipse as my editor.
I'm reading the docs here for AlertDialog, which gives an example:
public static class MyAlertDialogFragment extends DialogFragment {
public static MyAlertDialogFragment newInstance(int title) {
MyAlertDialogFragment frag = new MyAlertDialogFragment();
Bundle args = new Bundle();
args.putInt("title", title);
frag.setArguments(args);
return frag;
}
#Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
int title = getArguments().getInt("title");
return new AlertDialog.Builder(getActivity())
.setIcon(R.drawable.alert_dialog_icon)
.setTitle(title)
.setPositiveButton(R.string.alert_dialog_ok,
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int whichButton) {
((FragmentAlertDialog)getActivity()).doPositiveClick();
}
}
)
.setNegativeButton(R.string.alert_dialog_cancel,
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int whichButton) {
((FragmentAlertDialog)getActivity()).doNegativeClick();
}
}
)
.create();
}
}
I originally re-wrote it so I can start committing some of the methods to memory, but got an error "FragmentAlertDialog cannot be resolved to a type". I hit Ctrl+Shift+O to make sure I had the proper imports, but still it didn't go away.
So I copied/ pasted the example code and did the following, in this order:
Hit Ctrl+Shift+O to get the imports right (using android.app.DialogFragment, not android.support.v4.app.DialogFragment)
Declared my package at the top
Replaced R.string.alert_dialog_ok and R.string.alert_dialog_cancel with android.R.string.ok and android.R.string.cancel respectively
Removed setIcon(), as I don't have an icon to put in yet
I'm still getting errors:
FragmentAlertDialog cannot be resolved to a type (x4)
Illegal modifier for the class MyAlertDialogFragment; only public, abstract & final are permitted
Am I doing something wrong, or is there something wrong with the example code?
1.FragmentAlertDialog
Make sure the Activity you want to cast to is named FragmentAlertDialog. Make sure to also save everything - sometimes Eclipse won't make the connection until everything is saved.
2.Illegal modifier for the class MyAlertDialogFragment; only public, abstract & final are permitted
Take out the static modifier:
public class MyAlertDialogFragment extends DialogFragment {
or keep static and move this Fragment so it is enclosed within the Activity you want. This means that MyAlertDialogFragment should be inside your Activity, before that Activity's closing brace.
I'm new to Java/Android development
Don't start off with something so complicated. Learn Java then move to Android.
Hi try these code to implement alert dialog
AlertDialog.Builder alert2 = new AlertDialog.Builder(this);
alert2.setTitle("Your Title");
alert2.setMessage("Your Messages");
final EditText input2 = new EditText(this);
input2.setInputType(InputType.TYPE_CLASS_PHONE);
alert2.setView(input2);
alert2.setPositiveButton(GButton, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int whichButton) {
// Do something with value!
try
{
// do your stuff here
}
catch(Exception e)
{
}
}
});
alert2.setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int whichButton) {
// Canceled.
}
});
alert2.show();

how to detect a search button while an alert is shown in an android

Hi stackoverflow friends
I recently faced an issue that how can i disable global search button in android while an alert is shown in the screen.I don't want to disappear the alert box by using search button. I need to user must click the alertbox button and disappears in that way.So I want to disable the search button while alert box is shown. But I can disable the back button using setCancable(false).How can I solve this ?
THanks in advance.
So, Your intention is to provide non-cancelable alert.
Suggesting to set OnDismissListener and just show alert again. It's not very good from visual perspective (alert get closed and opened again).
Below is some obvious example how to achieve such non-cancelable alert (code is inside Acctivity class):
/** reference to our alert */
private AlertDialog alert = null;
/** to indicate if alert dismissed by key */
private boolean alertKeyPressed = false;
#Override
protected void onResume() {
// Say, we need to show alert when activity resumed
if(true/*provide condition to show alert*/) {
showAlert();
}
}
/**
* Show non dismissable alert
*/
private void showAlert() {
if(null == this.alert) {
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setCancelable(false);
builder.setTitle(R.string.str_alert_title);
builder.setMessage(R.string.str_alert_text);
builder.setIcon(android.R.drawable.ic_dialog_alert);
builder.setNeutralButton("OK", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
YourActivity.this.alertKeyPressed = true;
dialog.dismiss();
}
});
this.alert = builder.create();
this.alert.setOwnerActivity(this);
this.alert.show();
this.alert.setOnDismissListener(new DialogInterface.OnDismissListener() {
#Override
public void onDismiss(DialogInterface dialog) {
// dialog is not allowed to be dismissed, so show it again
YourActivity.this.alert = null;
if(!YourActivity.this.alertKeyPressed) {
showAlert();
}
}
});
}
}
However, I don't think it's the right way to left such alert for the user, sometimes it might be needed for cases like evaluation restriction etc.
Override onSearchRequested in your Activity and have it return false while the dialog is being shown. This should block the request, as per the docs:
You can override this function to force global search, e.g. in
response to a dedicated search key, or to block search entirely (by
simply returning false).
Returns true if search launched, and false if activity blocks it. The
default implementation always returns true.
.setOnKeyListener(new DialogInterface.OnKeyListener()
{
#Override
public boolean onKey(DialogInterface dialog, int keyCode, KeyEvent event)
{
//There you catch the key, do whatever you want to do.
//Return true if you handled the key event, so nothing will trigger.
//Return false if you want your activity to handle.
return true;
}
})
Just add the code above to alert dialog builder. Hope this snippet would help. Good luck.

Categories

Resources