I am trying to include an AlertDialog builder within a method that prompts for a pin code and when the positive button is pressed, checks it against a database value and returns a true or false value to the method caller.
For example: Adding/editing/deleting a user task requires a pin code. I don't want to generate a different AlertDialog for all three (and more) of these actions. I want to wrap the following code within a TaskService class that I can call from any activity, and react based on the result from within that activity.
So TaskService.java would have:
public boolean isCorrectPin(View v){
AlertDialog.Builder builder = new AlertDialog.Builder(v.getContext());
final EditText editText = new EditText(context);
builder.setView(editText);
builder.setPositiveButton("OK", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
if (editText.getText().toString()) == getPinCode(){
//return true
}
}
});
builder.show();
}
and OpenTaskAdapter.java would have:
public void onBindViewHolder(ViewHolder holder, int position){
holder.btnMarkAsComplete.setOnClickListener(new View.OnClickListener(){
#Override
public void onClick(View v){
if (service.isCorrectPin(v) {
//complete task
}
}
});
holder.btnDelete.setOnClickListener(new View.OnClickListener(){
#Override
public void onClick(View v){
if (service.isCorrectPin(v) {
//delete task
}
}
});
It's important to note that these two button listeners could be in totally different activities.
You can create your own method to generate dialog with listener:
public void isCorrectPin(Context context, String title, String message, String btnPositive, final DialogSingleButtonListener dialogSingleButtonListener) {
final AlertDialog.Builder dialogBuilder = new AlertDialog.Builder(context);
dialogBuilder.setTitle(title);
dialogBuilder.setMessage(message);
dialogBuilder.setPositiveButton(btnPositive, new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
if (editText.getText().toString() == getPinCode()){
dialogSingleButtonListener.onButtonClicked(dialog);
}
}
});
AlertDialog dialog = dialogBuilder.create();
dialog.show();
}
And the listener class:
public interface DialogSingleButtonListener {
public abstract void onButtonClicked(DialogInterface dialog);
}
And use it like:
service.isCorrectPin(context, title, message, btnPositive
new DialogSingleButtonListener() {
#Override
public void onButtonClicked(DialogInterface dialog) {
//code here is only called if they entered a correct pin.
}
}
);
A dialog can't "return" a value in the way that it looks like you're expecting. A dialog can make changes to some other object, but you can't have a bit of code block on it and wait for the user to finish interacting with it.
Instead, you'll need to set up listeners for when the prompt dialog is dismissed or buttons or clicked, or whatever other event signals that you have what you need from it. Those listeners can then read the data gathered and set by the dialog.
this is how i'm doing :
public Boolean showAlert(String message)
{
action = false;
AlertDialog.Builder alertDialog = new AlertDialog.Builder(HAActivity.this);
// Setting Dialog Title
alertDialog.setTitle(getString(R.string.app_name));
// Setting Dialog Message
alertDialog.setMessage(message);
// Setting Icon to Dialog
// Setting Positive "Yes" Button
alertDialog.setPositiveButton("OK", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog,int which) {
// Write your code here to invoke YES event
action = true;
}
});
// Setting Negative "NO" Button
alertDialog.setNegativeButton("Cancle", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
// Write your code here to invoke NO event
action = false;
dialog.cancel();
}
});
// Showing Alert Message
alertDialog.show();
return action;
}
and calling function like this :
//activity in which you create function
if (Activity.showAlert("Do you really want to delete ??"))
{
//delete it anyway.
}
Related
I'm working on a small class which can generate Alert dialog boxes. The constructor of the class looks like this:
void popupMessage(String title, String message, String pText, String nText, boolean cancelable) {
setPopupResult(999);
AlertDialog.Builder dialog = new AlertDialog.Builder(currentActivity);
dialog.setMessage(message).setCancelable(cancelable);
dialog.setNegativeButton(nText, new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
setPopupResult(0);
}
});
dialog.setPositiveButton(pText, new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
setPopupResult(1);
}
});
AlertDialog alert = dialog.create();
alert.setTitle(title);
alert.show();
}
as you see based on pressing the yes or no button the code sets the value of a private variable to 0 or 1 which can be accessed by a getter method. (the value is set to 999 at the top, this indicates that the user did no press anything yet)
The problem I'm facing is that from in the calling activity I somehow should be able to capture when the popupResult variable changes from 999 to either 0 or 1. How can I do that?
(I could be wrong handling the Alert dialog like this, feel free to educate me)
Since the user's clicking on your dialog buttons is asynchronous to when you're showing the dialog, one way to do it, would be to provide some kind of callback to your method, that is called when the buttons are clicked.
Example:
/* define this inside your dialog class */
public interface Callback {
void onOkClicked();
void onCancelClicked();
}
void popupMessage(String title, String message, String pText, String nText, boolean cancelable, Callback callback) {
...
/* positive button clicklistener, for negative button, use callback.onCancelClicked() */
public void onClick(DialogInterface dialog, int which) {
callback.onOKClicked();
}
...
}
/* Using the method */
popupMessage(..., new Callback() {
void onOKClicked() {
/* do something when OK was clicked */
}
void onCancelClicked() {
/* do something when Cancel was clicked */
}
});
I see that you already have the context of the activity in the variable currentActivity. Create the method setPopupResult() in your activity like this:
public void setPopupResult(int x) {
// your code goes here
}
and in popupMessage(), if the class of your activity is MainActivity:
dialog.setNegativeButton(nText, new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
((MainActivity) currentActivity).setPopupResult(0);
}
});
dialog.setPositiveButton(pText, new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
((MainActivity) currentActivity).setPopupResult(1);
}
});
Please, i would like to show back details after the user must have input something, back on alert dialog box in Android studio. I used this code below:
editText = (EditText) findViewById(R.id.my_edit_txt);
editText.getText().toString();
But it doesn't show on the confirmation dialog box I created.
It looks like you didn't set the text of your AlertDialog, but this is just an assumption because there is not enough code in your question. Calling editText.getText().toString() does not do anything but return a String. It does not assign it to anything. An example with an AlertDialog would be the following:
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
builder.setMessage(editText.getText().toString());
builder.setPositiveButton(R.string.ok, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
// User clicked OK button
}
});
builder.setNegativeButton(R.string.cancel, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
// User cancelled the dialog
}
});
// Set other dialog properties
...
// Create the AlertDialog
AlertDialog dialog = builder.create();
I've took this example from Android Developers and modified it so that it includes the text of your EditText. This code should work because you not only call the toString() method but also assign it's return value to the AlertDialog's message property.
This is my entire code for the alert dialog box:
public void alertdialog(View view){
mybtn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
AlertDialog.Builder cfmalt = new AlertDialog.Builder(Dashboard.this);
//cfmalt.setMessage("Do you want to quit?").setCancelable(false);
//editText.getText().toString();
cfmalt.setMessage(editText.getText().toString()+"\n"+ vol_edit2.getText().toString());
cfmalt.setMessage(dt.getMonth())
//cfmalt.setMessage("Name:").setMessage(vol_edit2.getText().toString());
cfmalt.setPositiveButton("Yes", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialogInterface, int i) {
finish();
}
});
cfmalt.setNegativeButton("No", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialogInterface, int i) {
dialogInterface.cancel();
}
});
I am using an AlertDialog to ask the user to enter a numerical value on a long press of a view. This uses the Android soft-keyboard. For a better user experience I would like the keyboard "Enter" button to programmatically click the Alert Dialog's positive button and run it's onClick. This is really awkward because I can't find any reference to the positive button in the dialog objects. Code to illustrate:
customStakeView.setOnLongClickListener(new View.OnLongClickListener() {
#Override
public boolean onLongClick(View view) {
final AlertDialog.Builder builder = new AlertDialog.Builder(context);
builder.setTitle("Custom Stake");
customStakeSet = false;
// Set up the input
final EditText input = new EditText(context);
input.setTextAlignment(View.TEXT_ALIGNMENT_CENTER);
// Specify the type of input expected;
input.setInputType(InputType.TYPE_CLASS_NUMBER);
input.setOnKeyListener(new View.OnKeyListener() {
#Override
public boolean onKey(View view, int keyCode, KeyEvent keyEvent) {
if(keyEvent.getAction() == KeyEvent.ACTION_DOWN){
if(!input.getText().toString().equals("")){
switch (keyCode){
case KeyEvent.KEYCODE_ENTER:
//Positive Button Outcome
}
}
}
return false;
}
});
builder.setView(input);
// Set up the buttons
builder.setPositiveButton("OK", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
String newStake = input.getText().toString();
if (!newStake.equals("")) {
newStake = newStake.replaceAll("[^\\d.]", ""); //strip down to currency format
customStake = new Stake(newStake);
customStakeSet = true;
deselectAll();
selectCustomStake();
InputMethodManager imm = (InputMethodManager) context.getSystemService(Context.INPUT_METHOD_SERVICE);
imm.hideSoftInputFromWindow(input.getWindowToken(), InputMethodManager.HIDE_NOT_ALWAYS);
}
}
});
builder.setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
dialog.cancel();
}
});
builder.show();
return true;
}
});
I've caught the KeyEvent, and if this was a button added via XML, or even defined with a variable, I would easily be able to do
button.performClick();
but AlertDialog doesn't seem to have such a reference
EDIT:
From documentation, use getButton(whichButton)
Gets one of the buttons used in the dialog. Returns null if the specified button does not exist or the dialog has not yet been fully created (for example, via show() or create()).
whichButton can be BUTTON_POSITIVE or any other button you have specified.
Below is a screenshot of it.
You aren't catching AlertDialog returned by .create() method. getButton() is not available to builder, but to AlertDialog object.
builder.setPositiveButton(...);
// you're missing this
final AlertDialog alertDialog = builder.create();
// then, use it like this
alertDialog.getButton(DialogInterface.Button_POSITIVE).performClick();
I'm designing function using AlertDialog to act like a InputBox in VB6. However using the code below, AlertDialog won't return values.
Seems that the function returns before the user makes the input.
public String InputBox(Context srcpage, String Msg, String Title, String InputDataType_TXT_or_NUM)
{
ResetReturnText();
AlertDialog.Builder dlgAlert = new AlertDialog.Builder(srcpage);
dlgAlert.setMessage(Msg);
dlgAlert.setTitle(Title);
// Set an EditText view to get user input
final EditText inputTxt = new EditText(srcpage);
//Set the input type of the EditText
//-------------------------------------------------------
if(InputDataType_TXT_or_NUM=="TXT")
inputTxt.setInputType(InputType.TYPE_TEXT_VARIATION_PERSON_NAME);
else if(InputDataType_TXT_or_NUM=="NUM")
inputTxt.setInputType(InputType.TYPE_CLASS_NUMBER);
else
return "Invalid Data Type";
//-------------------------------------------------------
dlgAlert.setView(inputTxt);
dlgAlert.setPositiveButton("Ok", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int whichButton) {
ReturnText = inputTxt.getText().toString();
}
});
dlgAlert.setNegativeButton("Cancel",null);
dlgAlert.create().show();
return ReturnText;
}
I Want these code to return values with function calls like:
String NewProvince="";
NewProvince = InputBox(this, "Province:", "Add/Edit Province", "TXT");
Log.w("Input:",NewProvince);
Can I ask you guys to help me with fixing this problem?
Thanks!
You have to use a different approach, based on "callback".
So your function has simply to return void and do the stuff inside the onClick listener.
private void buildDialog() {
// build your dialog with everything
dialog.setPositiveButton("Ok", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int whichButton) {
// do what you want with the value
doSomethingWithValue(value);
}
});
}
protected void doSomethingWithValue(String value) {
Log.i("MyTAG", value);
}
I have an alert dialog with a single-choice list and two buttons: an OK button and a cancel button. The code below show how I implemented it.
private final Dialog createListFile(final String[] fileList) {
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setTitle("Compare with:");
builder.setSingleChoiceItems(fileList, -1, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int whichButton) {
Log.d(TAG,"The wrong button was tapped: " + fileList[whichButton]);
}
});
builder.setPositiveButton("OK", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int whichButton) {}
});
builder.setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int whichButton) {}
});
return builder.create();
}
My goal is to obtain the name of the selected radio button when the OK button is tapped. I tried to save the string in a variable, but inside an inner class it is possible to access only final variables. Is there a way to avoid using a final variable to store the selected radio button?
Using a final variable obviously won't work (since it can only be assigned once, at declaration time). So-called "global" variables are usually a code smell (especially when they become part of an Activity class, which is usually where AlertDialogs are created).
The cleaner solution is to cast the DialogInterface object to an AlertDialog and then call getListView().getCheckedItemPosition(). Like this:
new AlertDialog.Builder(this)
.setSingleChoiceItems(items, 0, null)
.setPositiveButton(R.string.ok_button_label, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int whichButton) {
dialog.dismiss();
int selectedPosition = ((AlertDialog)dialog).getListView().getCheckedItemPosition();
// Do something useful withe the position of the selected radio button
}
})
.show();
This has been answered just fine, but I keep finding this answer from Google and I wanted to share a non-anonymous class solution. I prefer reusable classes myself and may be helpful to others.
In this example, I'm using a DialogFragment implementation and retrieving a value via a callback method.
The callback method to get values from a Dialog can be done by creating a public interface
public interface OnDialogSelectorListener {
public void onSelectedOption(int selectedIndex);
}
Also the DialogFragment implements DialogInterface.OnClickListener which means you can register the class you've implemented as the OnClickListener for the DialogFragment that is being created.
For example
public Dialog onCreateDialog(Bundle savedInstanceState) {
final AlertDialog.Builder builder = new AlertDialog.Builder(this.getActivity());
builder.setTitle(R.string.select);
builder.setSingleChoiceItems(mResourceArray, mSelectedIndex, this);
builder.setPositiveButton(R.string.ok, this);
builder.setNegativeButton(R.string.cancel, this);
return builder.create();
}
The line
builder.setSingleChoiceItems(mResourceArray, mSelectedIndex, this);
Creates a choice dialog with the options from a resource array stored in mResourceArray. This also preselects an option index from what is stored in mSelectedIndex and finally it sets this itself as the OnClickListener. (See full code at the end if this paragraph is a tad confusing)
Now, the OnClick method is where you grab the value that comes from the dialog
#Override
public void onClick(DialogInterface dialog, int which) {
switch (which) {
case Dialog.BUTTON_NEGATIVE: // Cancel button selected, do nothing
dialog.cancel();
break;
case Dialog.BUTTON_POSITIVE: // OK button selected, send the data back
dialog.dismiss();
// message selected value to registered callbacks with the
// selected value.
mDialogSelectorCallback.onSelectedOption(mSelectedIndex);
break;
default: // choice item selected
// store the new selected value in the static variable
mSelectedIndex = which;
break;
}
}
What happens here is when an item is selected, it's stored in a variable. If the user clicks the Cancel button, no update is sent back and nothing changes. If the user clicks the OK button, it returns the value to the Activity that created it via the callback created.
As an example, here is how you would create the dialog from a FragmentActivity.
final SelectorDialog sd = SelectorDialog.newInstance(R.array.selector_array, preSelectedValue);
sd.show(getSupportFragmentManager(), TAG);
Here, the resource array _R.array.selector_array_ is an array of strings to show in the dialog and preSelectedValue is the index to select on open.
Finally, your FragmentActivity will implement OnDialogSelectorListener and will receive the callback message.
public class MyActivity extends FragmentActivity implements OnDialogSelectorListener {
// ....
public void onSelectedOption(int selectedIndex) {
// do something with the newly selected index
}
}
I hope this is helpful to someone, as it took me MANY attempts to understand it. A full implementation of this type of DialogFragment with a callback is here.
public class SelectorDialog extends DialogFragment implements OnClickListener {
static final String TAG = "SelectorDialog";
static int mResourceArray;
static int mSelectedIndex;
static OnDialogSelectorListener mDialogSelectorCallback;
public interface OnDialogSelectorListener {
public void onSelectedOption(int dialogId);
}
public static DialogSelectorDialog newInstance(int res, int selected) {
final DialogSelectorDialog dialog = new DialogSelectorDialog();
mResourceArray = res;
mSelectedIndex = selected;
return dialog;
}
#Override
public void onAttach(Activity activity) {
super.onAttach(activity);
try {
mDialogSelectorCallback = (OnDialogSelectorListener)activity;
} catch (final ClassCastException e) {
throw new ClassCastException(activity.toString() + " must implement OnDialogSelectorListener");
}
}
public Dialog onCreateDialog(Bundle savedInstanceState) {
final AlertDialog.Builder builder = new AlertDialog.Builder(this.getActivity());
builder.setTitle(R.string.select);
builder.setSingleChoiceItems(mResourceArray, mSelectedIndex, this);
builder.setPositiveButton(R.string.ok, this);
builder.setNegativeButton(R.string.cancel, this);
return builder.create();
}
#Override
public void onClick(DialogInterface dialog, int which) {
switch (which) {
case Dialog.BUTTON_NEGATIVE:
dialog.cancel();
break;
case Dialog.BUTTON_POSITIVE:
dialog.dismiss();
// message selected value to registered calbacks
mDialogSelectorCallback.onSelectedOption(mSelectedIndex);
break;
default: // choice selected click
mSelectedIndex = which;
break;
}
}
}
Question from a comment How to call this from a Fragment instead of an Activity.
First make a few changes to the DialogFragment.
Remove the onAttach event since that's not the easiest way in this scenario.
Add a new method to add a reference to the callback
public void setDialogSelectorListener (OnDialogSelectorListener listener) {
this.mListener = listener;
}
Implement the listener in your Fragment
public class MyFragment extends Fragment implements SelectorDialog.OnDialogSelectorListener {
// ....
public void onSelectedOption(int selectedIndex) {
// do something with the newly selected index
}
}
Now create a new instance and pass in a reference to the Fragment to use it.
final SelectorDialog sd = SelectorDialog.newInstance(R.array.selector_array, preSelectedValue);
// this is a reference to MyFragment
sd.setDialogSelectorListener(this);
// mActivity is just a reference to the activity attached to MyFragment
sd.show(this.mActivity.getSupportFragmentManager(), TAG);
final CharSequence[] choice = {"Choose from Gallery","Capture a photo"};
int from; //This must be declared as global !
AlertDialog.Builder alert = new AlertDialog.Builder(activity);
alert.setTitle("Upload Photo");
alert.setSingleChoiceItems(choice, -1, new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
if (choice[which] == "Choose from Gallery") {
from = 1;
} else if (choice[which] == "Capture a photo") {
from = 2;
}
}
});
alert.setPositiveButton("OK", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
if (from == 0) {
Toast.makeText(activity, "Select One Choice",
Toast.LENGTH_SHORT).show();
} else if (from == 1) {
// Your Code
} else if (from == 2) {
// Your Code
}
}
});
alert.show();
As others have pointed out, implementation 'com.google.android.material:material:1.0.0' it is more simply
Refere this material guide for more. https://material.io/develop/android/docs/getting-started/
CharSequence[] choices = {"Choice1", "Choice2", "Choice3"};
boolean[] choicesInitial = {false, true, false};
AlertDialog.Builder alertDialogBuilder = new MaterialAlertDialogBuilder(getContext())
.setTitle(title)
.setPositiveButton("Accept", null)
.setNeutralButton("Cancel", null)
.setMultiChoiceItems(choices, choicesInitial, new DialogInterface.OnMultiChoiceClickListener() {
#Override
public void onClick(DialogInterface dialog, int which, boolean isChecked) {
}
});
alertDialogBuilder.show();
Try this.
final String[] fonts = {"Small", "Medium", "Large", "Huge"};
AlertDialog.Builder builder = new AlertDialog.Builder(TopicDetails.this);
builder.setTitle("Select a text size");
builder.setItems(fonts, new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
if ("Small".equals(fonts[which])) {
Toast.makeText(MainActivity.this,"you nailed it", Toast.LENGTH_SHORT).show();
}
else if ("Medium".equals(fonts[which])) {
Toast.makeText(MainActivity.this,"you cracked it", Toast.LENGTH_SHORT).show();
}
else if ("Large".equals(fonts[which])){
Toast.makeText(MainActivity.this,"you hacked it", Toast.LENGTH_SHORT).show();
}
else if ("Huge".equals(fonts[which])){
Toast.makeText(MainActivity.this,"you digged it", Toast.LENGTH_SHORT).show();
}
// the user clicked on colors[which]
}
});
builder.show();