1

I'm trying to build a custom AlertDialog by extending the AlertDialog class.
As usual, I'm setting up the dialog inside its onCreate() method. Or, I'm trying to do so:

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    this.setTitle("Some title");
    this.setButton(BUTTON_POSITIVE, "Click me", (DialogInterface.OnClickListener)null);

    final FrameLayout custom = (FrameLayout) this
            .findViewById(android.R.id.custom);

    custom.addView(this.getLayoutInflater().inflate(R.layout.mydlg, null),
            LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT);

}

Now, when it comes to displaying an instance of this dialog, nothing is shown. The current Activity fades out and loses focus but not a single pixel of my dialog is displayed. Pressing Back brings the Activity back to the foreground, indicating to me that a dialog actually is shown, but just a completely empty one.

However, when I create an AlertDialog and use, for instance, dlg.setButton(BUTTON_POSITIVE, "Click me", (DialogInterface.OnClickListener)null); the dialog is shown with the respective button.
Even when I set up my custom dialog in its constructor using the very same code as above everything seems to work ok.

Now, how can this be? Why can't I seem to initialize my dialog in its onCreate() method? Isn't this the way you're supposed to initialize any GUI element? What am I missing?

EDIT

Please note, that something is 'shown', fading out the Activity and taking focus from it. It's just that it seems to be completely empty/invisible.

Here another attempt:

    this.setTitle("Some title");
    this.setButton(BUTTON_POSITIVE, "Click me", (DialogInterface.OnClickListener)null);

    final View v = this.getLayoutInflater().inflate(R.layout.mydlg, null);

    this.setView(v);

These exact lines do work when put into my dialog's constructor.
These exact lines do not work when put into my dialog's onCreate().

What is going on here?!

Generally, am I not supposed to do it in onCreate()? - Am I facing trouble if I resort to doing the above initialization in the constructor instead? (This does not seem too clean to me, anyway.)

JimmyB
  • 12,101
  • 2
  • 28
  • 44
  • Did you find any solution specifically for doing this way? I face the same problem. – gaurav jain Mar 11 '15 at 04:23
  • In a comment below, TheTerribleSwiftTomato figured out that "subclassing AlertDialog and customizing [...] it in its constructors instead of the onCreate() method" should be an ok way of doing things. So that's what I eventually used. – JimmyB Mar 19 '15 at 13:52
  • Hi Hanno, I tried setting the custom dialog in onCreate, for which the result is same as yours, activity losing focus and nothing shown. But when I put same code in constructor, the framelayout for android.R.id.custom returns null. Hence, can you post working code so that I can verify where I go wrong. Thanks. – gaurav jain Mar 20 '15 at 03:48

4 Answers4

2

You need to call the show() method in order to see something.

asenovm
  • 6,397
  • 2
  • 41
  • 52
  • 1
    i didn't realize the view wouldn't be inflated until calling show(), and thus my findViewById()'s would always return null since i hadn't yet called show(). – Keith May 16 '12 at 19:26
1

Sorry I'm late to the party :)

You have to thing differently for the alert dialog.

The way I did it is to customize the view before creating the alert dialog:

// This is the activity that is the background of the AlertDialog
public class Main extends Activity {

    public static final int DIALOG_CONFIG = 1;
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        requestWindowFeature(Window.FEATURE_NO_TITLE);

        setContentView(R.layout.emptybackground);
    }

    @Override
    protected void onStart() {
        super.onStart();

        // Open the alert dialog on openning the Activity
        showDialog(Main.DIALOG_CONFIG );
    }

    protected Dialog onCreateDialog(int id) {
        LayoutInflater factory = LayoutInflater.from(this);
        switch (id) {
        case DIALOG_CONFIG:
            // Here, we load the existing view R.layout.config
            configView = factory.inflate(R.layout.config, null);
            configDialog = new AlertDialog.Builder(this)
                .setTitle("Configuration")
                .setView(configView)
                .create();

            // Using configView, you can do whatever you want with the view. Here, we add value to a spinner.
            Spinner spinner = (Spinner)configView.findViewById(R.id.config_select_conn);
            ArrayAdapter<String> adapter = new ArrayAdapter<String>(this, android.R.layout.simple_spinner_item);
            adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
            adapter.add("TCP");
            adapter.add("Bluetooth");
            spinner.setAdapter(adapter);

            return configPrinter;
        }
        return null;
    }
}
darkzangel
  • 939
  • 9
  • 17
1

You should consider using AlertDialog.Builder instead of subclassing AlertDialog itself. It allows you to do all the things you need in your example (in order: setTitle(),setPositiveButton() and setView() ). Don't forget to call create() at the end to actually get your dialog.

Also, check if your onCreateDialog() and onPrepareDialog() activity methods are implemented correctly. If you don't have them implemented at all (an unmanaged dialog), consider doing that anyway, especially if your app allows for orientation changes. You probably know about this, but here is a tutorial:

http://developer.android.com/guide/topics/ui/dialogs.html

also, DialogFragments are a bit easier way to implement this, but you need a newer API version or the Compatibility package:

http://developer.android.com/reference/android/app/DialogFragment.

One final issue - where are you calling show() in your activity? onResume() should be OK, onCreate() not as much.

mikołak
  • 9,605
  • 1
  • 48
  • 70
  • Using the Builder does work, as does instantiating an AlertDialog and then setting it up from "outside". The Activity's methods seem to be ok, too: A plain AlertDialog for testing is displayed as expected. The docs for the Dialogs have nothing to say about this issue. I would like to encapsulate my dialog's functionality in a dedicated class. Extending AlertDialog would be the natural way. But why can't I set it up in onCreate?! – JimmyB Dec 31 '11 at 12:50
  • I try to show the dialog from the *onClickListener* of a button in my activity. Should be perfectly fine. – JimmyB Dec 31 '11 at 13:07
  • 1
    I would still discourage that unless you have truly generic functionality. But if you do, it seems that the standard way of subclassing AlertDialog and customizing it is to do it in its **constructors** instead of the onCreate() method. That's how the DatePickerDialog is implemented, for example. – mikołak Dec 31 '11 at 17:05
  • I'm trying for practice to implement a password entry dialog. Ideally, I would just have to use something like *return new PasswordDlg()* in *onCreateDialog* and retrieve the entered password when the dialog is dismissed. A little bit of input validation logic should go into the dialog itself, and so the story begins. Thank you for pointing me to the DatePickerDialog. If it's done in the constructor there I guess it should be fine to do so. (I really need to get those sources attached to my android.jar in eclipse... :) ) – JimmyB Dec 31 '11 at 21:17
  • You're welcome. Sorry about yammering about the normal way to create dialogs, but I wanted to avoid any newbie getting the wrong message by accident. – mikołak Jan 04 '12 at 20:59
0

you should call custom_alertDialog.create(); before custom_alertDialog.show();

AminST
  • 323
  • 3
  • 11