I'm very new to Android, and have a basic question. I need at certain points to display a user notification in a dialog box, which they can simply acknowledge with the OK button.
I'm using:
myActivity.runOnUiThread(new Runnable() {
public void run() {
AlertDialog alertDialog = new AlertDialog.Builder(myContext).create();
alertDialog.setTitle("Alert");
alertDialog.setMessage("My message");
alertDialog.setButton(AlertDialog.BUTTON_NEUTRAL, "OK",
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
dialog.dismiss();
}
});
alertDialog.show();
}
});
This works well in the Main program, but within a called method it needs the Activity and the Context from the main program. Can anybody tell me how to pass these? getApplicationContext() seems to be acceptable, but I can't figure out how to pass the Activity.
Better still of course would be to get the parent Context and Activity within the method, but I can't get that to work either.
I'd be grateful for any help.
-update 10/07/21
Rahul has given me the solution to the problem I posed: how to pass in the Activity and Context.
The problem is that the dialog still doesn't show.
I found a variation online as follows:
AlertDialog.Builder builder = new AlertDialog.Builder(myContext);
builder.setTitle("Alert")
.setMessage("My message")
.setCancelable(false)
.setPositiveButton("OK", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
dialog.dismiss();
}
});
AlertDialog alert = builder.create();
alert.show();
but this doesn't work either.
I'm puzzled that such a common and simple task needs so much code. In the desktop languages I'm used to it can be done in a single line.
So my titled question stands, but can anyone see where the code is faulty?
Many thanks
You can either pass activity to the class when initializing the object or you can pass activity when calling the function.
Case 1 (Recommended)
Pass Activity when calling the function:
MyObj myObj = new MyObj();
myObj.showDialog(myValue, ActivityName.this);
Where function will look like this:
public void showDialog(int myValue, Activity activity){
...
}
Then you can use this activity instance inside the method.
Case 2
Pass Activity when initializing the object:
MyObj myObj = new MyObj(ActivityName.this);
Where Class will look like this:
class MyObj{
private Activity thisActivity;
public MyObj(Activity activity){
thisActivity = Activity;
}
...
}
Then you can use this activity instance.
When you have activity object available you can replace context object with it.
Related
I'm trying to create a custom class for displaying a Yes/No AlertDialog, but I want to onClick handler to be in the activity that instantiates the custom class. So far, the custom class looks like this:
public class YesNoDialog {
private Context gContext = null;
private DialogInterface.OnClickListener onClickListener;
private AlertDialog alertDialog = null;
public YesNoDialog(Context context,
DialogInterface.OnClickListener listener) {
this.gContext = context;
this.onClickListener = listener;
}
public void ShowDialog() {
AlertDialog.Builder alertDialogBuilder = new
AlertDialog.Builder(this.gContext);
alertDialogBuilder.setTitle("Hello World");
alertDialogBuilder
.setMessage("Are you sure?")
.setCancelable(false)
.setPositiveButton("Yes",this.onClickListener)
.setNegativeButton("No",this.onClickListener);
alertDialog = alertDialogBuilder.create();
alertDialog.show();
}
}
My thinking was to pass the context and onClick handler to the object in the constructor, then assign the handler to the .setPositive and .setNegative buttons.
I implemented the DialogInterface.OnClickListener in my MainActivity class:
public class MainActivity
extends AppCompatActivity
implements DialogInterface.OnClickListener {
And created the onClick handler in MainActivity that should be called when either the Yes or No buttons are clicked in the dialog.
#Override
public void onClick(DialogInterface dialog, int id) {
Log.d("DIALOG RETURNS ID=", Integer.toString(id));
dialog.dismiss();
}
I'm not sure if I'm on the right track or not, but I got stuck in trying to figure out how I would now pass the onClick handler to the YesNoDialog object. I've tried several variations of this:
YesNoDialog dialog = new YesNoDialog(this, MainActivity.onClick);
With no success (won't compile). I have also tried passing only the context, assuming that maybe that's all I really need for .setPositive and .setNegative button handlers, but that didn't work either...this calls require a DialogInterface.OnClickListener.
It feels like I'm close, but I can't get over the hurdle. Can anyone help me connect the dots?
Create a class (DialogUtils) and add this method in it.
public static void showPopUp(Context context
, String title
, String msg
, String positiveBtnTxt
, String negativeBtnTxt
, DialogInterface.OnClickListener positiveBtnListener
, DialogInterface.OnClickListener negativeBtnListener){
final AlertDialog errorDialog;
AlertDialog.Builder errorDialogBuilder = new AlertDialog.Builder(context, R.style.NativeDialogue);
errorDialogBuilder.setTitle(title);
errorDialogBuilder.setMessage(msg);
errorDialogBuilder.setPositiveButton(positiveBtnTxt, positiveBtnListener);
errorDialogBuilder.setNegativeButton(negativeBtnTxt, negativeBtnListener);
errorDialog = errorDialogBuilder.create();
errorDialog.show();
}
Call the method like this :
DialogUtils.showPopUp(this, "title", "message", "positive btn name", "Negative Btn name", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
"Your action"
}
}, new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
"Your action"
}
});
This is described in the official documentation on dialogs in Android. In short, you need to do the following steps:
Create a DialogFragment for your dialog so it is properly restored when the device rotates or changes the configuration in some other way.
Create an interface which will allow you to send the result of the dialog.
Implement this interface in the activity.
Cast the activity to the interface inside the DialogFragment in onAttach and store it in some field. Don't forget to set to null in onDetach.
When a dialog button is clicked, you can call the appropriate interface method, and the activity will get the result.
Alternatively, if you only ever use this dialog with one activity, you may not declare an interface and simply store a reference to the activity.
Hey you can make one method in your MainActivity class. Like below.
public void onClickOnYesButton(int id){
}
Pass the MainActivity reference like below.
public YesNoDialog(MainActivity context) {
this.gContext = context;
}
And call the onClickOnYessButton by using the MainActivity reference!
Job done!
I have created a separate message popup class based on an offical Android example but I can't figure out how to launch this dialog from another activity. The popup class is:
public class PopupMessage extends DialogFragment {
String message = "";
#Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
// Use the Builder class for convenient dialog construction
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
builder.setMessage(message)
.setPositiveButton("Ok", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
//
}
});
// Create the AlertDialog object and return it
return builder.create();
}
}
In my other class I have created an instance:
import com.mcsapp.PopupMessage;
private PopupMessage popup;
popup = new PopupMessage();
When a button is clicked I want to call this. I have this:
case R.id.chooseLocationButton:
if(editTextLocation.getText().toString().equals("")) {
popup.message = "Test";
popup.getDialog().show();
}
break;
}
I have tried a variety of "popup" commands but all result in a crash. I'm sure it's simply I just can't find the correct code. The "message" parameter sets just fine so the import is working.
Thanks
popup.show(getFragmentManager(), "PopupMsgFragment");
You may want to change getFragmentManager() with getSupportFragmentManager() if you are using support v4 activity.
I have a custom class that extends a View, where I draw some geometric objects on the canvas. I also have a dialog class where I display a simple dialog. (FinePartita.java)
My MainActivity.java (from where I call my View)
public class MainActivity extends Activity {
#Override
public void onCreate(Bundle icicle) {
super.onCreate(icicle);
PaschiPongView ppv = new PaschiPongView(getApplicationContext());
setContentView(ppv);
}
}
PaschiPongView.java
public class PaschiPongView extends View {
// a lot of code here
}
FinePartita.java (the example is from Google)
public class FinePartita extends DialogFragment {
#Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
// Use the Builder class for convenient dialog construction
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
builder.setMessage(R.string.doUreallyWantToExit)
.setPositiveButton(R.string.yes, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
// FIRE ZE MISSILES!
}
})
.setNegativeButton(R.string.no, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
// User cancelled the dialog
}
});
// Create the AlertDialog object and return it
return builder.create();
}
}
The problem is, I need to display the dialog in my PaschiPongView class, but I can't do it because it needs a FragmentManager and since my class extends a View, it doesn't have it.
I can't call it like this:
FinePartita test = new FinePartita();
test.show(getFragmentManager(), "dialog"); // doesn't work
Any suggestions would be appreciated.
First, I'll answer your answer directly. This is a bit dirty, but does seem safe:
The Context object of a View is always the Activity holding it.
So casting Activity to the result of the getContext() should do the trick:
((Activity) getContext()).getFragmentManager();
Second, let's talk about why you SHOULDN'T do this:
As a rule, I never let my views handle business logic roles. Why? Because I don't wanna tie general use cases to a specific view. Doing so, I.E. letting your views affect the flow of the application, means keeping track of application state is hard, and changing flows is harder. And also code duplication. And ties you to UI design decisions that might not be applicable in the future.
I always implement a master controller that the views report their state to. Let's call it FlowControl. This is the object in charge of deciding what dialogs to show, how to handle results and so forth. Also, this is a good place to store a reference to FragmentManager. See where I'm going with this?
DialogFragment is a Fragment which shows dialogs. If you want to show the fragment you need a FragmentManager which can be accessed using Activity's getFragmentManager() method.
DialogFragment's show method will show the Fragment not the Dialog.
I'd like to make a dialog fragment that asks "Are you sure?" with a "yes/no" reply.
I've looked at the documentation and it's really verbose, going all over the place, explaining how to make advanced dialog boxes, but no intact code on making a simple 'hello world' kind of dialog box. Most tutorials utilize the deprecated dialog box system. The official blog seems to be unnecessarily complicated and difficult to understand.
So, what's the simplest way to create and display a really basic Alert Dialog? Bonus points if it's using the support library.
A DialogFragment is really just a fragment that wraps a dialog. You can put any kind of dialog in there by creating and returning the dialog in the onCreateDialog() method of the DialogFragment.
Heres an example DialogFragment:
class MyDialogFragment extends DialogFragment{
Context mContext;
public MyDialogFragment() {
mContext = getActivity();
}
#Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(mContext);
alertDialogBuilder.setTitle("Really?");
alertDialogBuilder.setMessage("Are you sure?");
//null should be your on click listener
alertDialogBuilder.setPositiveButton("OK", null);
alertDialogBuilder.setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
dialog.dismiss();
}
});
return alertDialogBuilder.create();
}
}
To create the dialog call:
new MyDialogFragment().show(getFragmentManager(), "MyDialog");
And to dismiss the dialog from somewhere:
((MyDialogFragment)getFragmentManager().findFragmentByTag("MyDialog")).getDialog().dismiss();
All of that code will work perfectly with the support library, by just changing the imports to use the support library classes.
So, what's the simplest way to create and display a really basic Alert
Dialog? Bonus points if it's using the support library.
Simply create a DialogFragment(SDK or support library) and override its onCreateDialog method to return an AlertDialog with the desired text and buttons set on it:
public static class SimpleDialog extends DialogFragment {
#Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
return new AlertDialog.Builder(getActivity())
.setMessage("Are you sure?")
.setPositiveButton("Ok", null)
.setNegativeButton("No way", null)
.create();
}
}
To do something when the user uses one of the buttons you'll have to provide an instance of a DialogInterface.OnClickListener instead of the null references from my code.
For those coding with Kotlin and Anko, you can now do dialogs in 4 lines of code:
alert("Order", "Do you want to order this item?") {
positiveButton("Yes") { processAnOrder() }
negativeButton("No") { }
}.show()
because of Activity / Fragment lifecycle #athor & #lugsprog approach can fail,
more elegant way is to **get activity context from method onAttach and store it as weak reference ** (&try to avoid non default constructor in DialogFragment!, to pass any argument to dialog use arguments) like this:
public class NotReadyDialogFragment extends DialogFragment {
public static String DIALOG_ARGUMENTS = "not_ready_dialog_fragment_arguments";
private WeakReference<Context> _contextRef;
public NotReadyDialogFragment() {
}
#Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
/** example pulling of arguments */
Bundle bundle = getArguments();
if (bundle!=null) {
bundle.get(DIALOG_ARGUMENTS);
}
//
// Caution !!!
// check we can use contex - by call to isAttached
// or by checking stored weak reference value itself is not null
// or stored in context -> example allowCreateDialog()
// - then for example you could throw illegal state exception or return null
//
AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(_contextRef.get());
alertDialogBuilder.setMessage("...");
alertDialogBuilder.setNegativeButton("Przerwij", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
dialog.dismiss();
}
});
return alertDialogBuilder.create();
}
#Override
public void onAttach(Activity activity) {
super.onAttach(activity);
_contextRef = new WeakReference<Context>(activity);
}
boolean allowCreateDialog() {
return _contextRef !== null
&& _contextRef.get() != null;
}
EDIT:
& if You wanna dismiss dialog then:
try to get it
check if it's exist
check if it's showing
dismiss
something like this :
NotReadyDialogFragment dialog = ((NotReadyDialogFragment) getActivity().getFragmentManager().findFragmentByTag("MyDialogTag"));
if (dialog != null) {
Dialog df = dialog.getDialog();
if (df != null && df.isShowing()) {
df.dismiss();
}
}
EDIT2: & if u wanna set dialog as non cancelable u should change onCreatweDialog return statement like this:
/** convert builder to dialog */
AlertDialog alert = alertDialogBuilder.create();
/** disable cancel outside touch */
alert.setCanceledOnTouchOutside(false);
/** disable cancel on press back button */
setCancelable(false);
return alert;
I am developing an Android app, this app has a dozen of Activities, each one is for a corresponding screen. Now I have this common subtitle bar on top of the screens.
this subtitle bar has a button to display an alert dialog which shows link list to go to a different screen.
I could write a same function for each activity to call the alert dialog, but that would be tedious if I want to modify them, so I created this class:
public class MenuAlertDialog extends Activity {
/*
#Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
}
*/
public void createMenu(final Context context){
AlertDialog.Builder dlg = new AlertDialog.Builder(context);
dlg.setTitle("menu");
String[] items = {"pageA", "pageB", "pageC", "pageD", "pageE"};
dlg.setItems(items, new DialogInterface.OnClickListener(){
#Override
public void onClick(DialogInterface dialog, int which){
switch(which){
case 0:
Intent intent = new Intent(context, MainActivity.class);
startActivity(intent);
break;
default:
break;
}
}
});
dlg.show();
}
}
and call it from each activity, like this:
MenuAlertDialog menu = new MenuAlertDialog();
menu.createMenu(this);
from inside of onCreate.
It can display the alertDialog, but whenever I press pageA link, it fails with an unexpected error.
Logcat says its a nullpointererror and the cause seems
startActivity(intent);
What am I doing wrong?
Remove the code
extends Activity
as you have no need to extend your class that you are creating since it does not rely on any activity related functionality.
Where you call startActivity(intent); replace it with
context.startActivity(intent);
You should change the class to Extends Dialog and not activity.
Also for Try this:
Check out this tutorial on how to create a custom dialog. Custom Dialog
Also Here Another Tutorial
And Here