Android: AlertDialog looks different in fragment - android

I have an app which uses TabLayout and Fragments, however my initial log in screen is a standard Activity. When I show an alert dialog from the Login screen, the look of the dialog is completely different from when I show one from inside of a fragment.
From Login Screen
From inside of Fragment
The code that I use to show the alertDialog is the following class
import android.app.Activity;
import android.app.AlertDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.graphics.Typeface;
import android.widget.Button;
import android.widget.TextView;
class AlertDialogManager {
private AlertDialog alertDialog;
private Context mContext;
public void showAlertDialog(final Activity activity, String title, String message, Boolean status, final Boolean finishOnClose) {
// Set our context correctly based on what was passed in activity
mContext = (activity.getParent()!=null) ? mContext = activity.getParent() : activity;
// Create our alertDialog Builder
alertDialog = new AlertDialog.Builder(mContext).create();
// Setting Dialog Title
alertDialog.setTitle(title);
// Setting Dialog Message
alertDialog.setMessage(message);
// Setting alert dialog icon
if(status != null) alertDialog.setIcon((status) ? R.drawable.icon_check : R.drawable.icon_alert);
// Setting OK Button
alertDialog.setButton(DialogInterface.BUTTON_POSITIVE, "OK", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
// if the user passed in TRUE for the finishOnClose param - we call try onBackPressed first and if that fails, call finish()
if (finishOnClose) {
try {
activity.onBackPressed();
} catch (Exception e) {
activity.finish();
}
}
}
});
// Showing Alert Message
alertDialog.show();
}
}
To show one in an Activity I use the following:
// At the top of my activity I declare
private final AlertDialogManager alertDialog = new AlertDialogManager();
// Then where I want to show one I use this
alertDialog.showAlertDialog(MyActivity.this, "Title", "Message", false, false);
To show one in a Fragment I use the following:
// At the top of my fragment I declare
private final AlertDialogManager alertDialog = new AlertDialogManager();
alertDialog.showAlertDialog(getActivity(), "Title", "Message", false, false);
Can anyone explain why I would get the 2 completely different "themes" on my dialog when calling from an Activity vs Fragment? I'm stumped.
thank you!!!

What is the older API version you are supporting? because you can use the AlertDialog builde since the API 11. If you are supporting older versions, you have to set the theme.
Example:
ContextThemeWrapper theme;
if ( Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB ) {
theme = new ContextThemeWrapper( context, android.R.style.Theme_Holo_Light_Dialog_NoActionBar );
}
else {
theme= new ContextThemeWrapper( context, android.R.style.Theme_Light_NoTitleBar );
}
AlertDialog.Builder builder = new AlertDialog.Builder(theme);
Hope this help.

Turns out I needed to add the following to the declaration in my manifest for my Login activity
android:theme="#style/Theme.AppCompat.NoActionBar"

Related

how to pass an onclick handler to a custom dialog class

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!

Show AlertDialog from class instance

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.

Simplest yes/no dialog fragment

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;

Show Dialog in GCM onMessage()

I am implementing GCM (Google Cloud Messaging) into my App.
I set it up all like in the Google Tutorial, and it works so far.
I display a notification in the notification-bar when onMessage when the GCMIntentService gets called.
Now I have a method that tells me if the app is in foreground or not.
When the app is in background it shows the notification in the bar with no problem.
But how could I show a Dialog to the user?
When I call:
AlertDialog.Builder builder = new AlertDialog.Builder(context);
where context is the given context from onMessage(), I of course this error:
_Notification.showPopUp() Error: android.view.WindowManager$BadTokenException: Unable to add window --
token null is not for an application
So I tried to replace the context with MainActivity.this, for this purpose I saved it in a static variable; but when i now run it, nothing happens, no error, no dialog appears.
My code for the dialog:
private static AlertDialog.Builder myAlertDialog;
private static void showPopUp(Context context,String kind, String resource_name, Integer resource_id)
{
AlertDialog.Builder builder = new AlertDialog.Builder(context);
builder.setMessage("Are you sure you want to exit?")
.setCancelable(false)
.setPositiveButton("Yes", new DialogInterface.OnClickListener()
{
public void onClick(DialogInterface dialog, int id)
{
}
})
.setNegativeButton("No", new DialogInterface.OnClickListener()
{
public void onClick(DialogInterface dialog, int id)
{
dialog.cancel();
}
});
AlertDialog alert = builder.create();
alert.show();
Log.e("TEST","alert.show()");
}
The last log: alert.show() gets displayed in logcat, but no error.
Spec:
Runnning on the device (Galaxy S2)
Android 4.0.3
Could someone please tell me what is wrong with my code, or does anybody knows some workaround?
Edit:
The part where I save my MainActivity.this:
private static Context context_forshowingPopUp = null;
onCreate
//Set the context for showing a popup View
_Notification.setContext_forshowingPopUp(this);
AlertDialog.Builder builder = new AlertDialog.Builder(getContext_forshowingPopUp());
public static Context getContext_forshowingPopUp()
{
return context_forshowingPopUp;
}
public static void setContext_forshowingPopUp(Context context_forshowingPopUp)
{
_Notification.context_forshowingPopUp = context_forshowingPopUp;
}
you must use YourCurrentActivity.this as a context while building Alertdialog. You can solve like below .
first class :
public class Config{
public static Context context;
}
when your activity creates , just set Config.contex
public class MyActivity extends Activity {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Config.context=this;
...}
//other stuffs
}
In OnMessage
showPopUp(Config.context,kind, resource_name, resource_id);

calling method in a separate class

I have my main class setup and a worker thread, one of my early requests that I make in run() is to call my second class called login. I do this like so:
login cLogin = new login();
cLogin.myLogin();
class login looks like this:
package timer.test;
import android.app.Activity;
import android.app.AlertDialog;
import android.content.DialogInterface;
import android.os.Bundle;
import android.widget.Toast;
public class login extends Activity {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// setContentView(R.layout.main);
}
public void myLogin() {
// prepare the alert box
AlertDialog.Builder alertbox = new AlertDialog.Builder(this);
// set the message to display
alertbox.setMessage(this.getString(R.string.intro));
// add a neutral button to the alert box and assign a click listener
alertbox.setNeutralButton("Register New Account",
new DialogInterface.OnClickListener() {
// click listener on the alert box
public void onClick(DialogInterface arg0, int arg1) {
// the button was clicked
}
});
// add a neutral button to the alert box and assign a click listener
alertbox.setNegativeButton("Login",
new DialogInterface.OnClickListener() {
// click listener on the alert box
public void onClick(DialogInterface arg0, int arg1) {
// the button was clicked
}
});
// show it
alertbox.show();
}
10-01 14:33:33.028: ERROR/AndroidRuntime(440):
java.lang.RuntimeException: Unable to start activity ComponentInfo{timer.test/timer.test.menu}:
java.lang.IllegalStateException:
System services not available to Activities before onCreate()
I put onCreate in but still having the same problem. How can I fix this?
You have a couple of options:
1) Move your public void myLogin() {..} to your main activity. I recommend this solution since you don't need another activity for your purposes.
2) Call startActivity on your login class before calling the myLogin(). Since you inherite from Activity onCreate needs to be called before you call anything else. That's why you get the exception. startActivity is called like this:
Intent i = new Intent(this, login.class);
startActivity(i);
You cannot do it this way simply because you are using the context
AlertDialog.Builder alertbox = new AlertDialog.Builder(this); //this is the activity context passed in..
The context is not available until Activity onCreate is called via startActivity. and not by constructing an new instance of the login object, you can try passing in an context from the activity calling this method
public void myLogin(Context context) {
// prepare the alert box
AlertDialog.Builder alertbox = new AlertDialog.Builder(context);
//blah blah blah...
}
yes and never construct an activity instance via the constructor.. -.-

Categories

Resources