16

I have created a custom dialog and a layout xml:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent">
    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Tap Me"
        android:onClick="dialogClicked" />
</LinearLayout>

In the dialog class I've implemented the method "dialogClicked(View v)":

public class TestDialog extends Dialog {

 public TestDialog(final Context context)
 {
  super(context);
 }

 @Override
 protected void onCreate(final Bundle savedInstanceState)
 {
  super.onCreate(savedInstanceState);
  setContentView(R.layout.dialog);
 }

 public void dialogClicked(final View view)
 {
  System.out.println("clicked");
 }

}

When I tap the button I get a NoSuchMethodException 'dialogClicked'. Setting the onClick handler in layout xml works fine for activities, but not in dialogs. Any ideas? What I'm doing wrong?

Octavian A. Damiean
  • 38,480
  • 19
  • 92
  • 99
Impression
  • 727
  • 1
  • 5
  • 14
  • 1
    Did you tried removing "final" modifier from dialogClicked(final View view) to dialogClicked(View view)? – 100rabh Nov 29 '10 at 13:03
  • http://stackoverflow.com/questions/12582695/android-dialog-nosuchmethodexception-error-when-using-xml-onclick/26263507#26263507 – Amit Yadav Oct 08 '14 at 18:10

9 Answers9

25

Define the method (dialogClicked) in Activity. And modify TestDialog like the following code:

public class TestDialog extends Dialog {
 Context mContext;
 public TestDialog(final Context context)
 {

  super(context);
  mContext=context;
 }

 @Override
 protected void onCreate(final Bundle savedInstanceState)
 {
  super.onCreate(savedInstanceState);
  LinearLayout ll=(LinearLayout) LayoutInflater.from(mContext).inflate(R.layout.dialog, null);
  setContentView(ll); 
 }
}

I think it works :)

Jett Hsieh
  • 3,129
  • 23
  • 33
  • Yes, that's the main point: Define the method (dialogClicked) in Activity, if you use onClick. – Mathias Conradt Dec 01 '10 at 06:20
  • Thx... now I can catch the event at least in the activity and have an entry for further optimization to move the handler method into the dialog implementation. – Impression Dec 01 '10 at 09:05
  • @Jett Hsieh ok fine but how will i write code for button cancel and button select so that i can dismiss dialog i m getting error in this technique – Erum Oct 23 '14 at 06:01
6

I think the issue is one of scope. I'm not sure how'd you address this in xml, but essentially the dialogueClicked method in your layout xml doesn't know where to find the method you've defined in the dialog class.

The standard approach i've seen to bind buttons in custom layouts is as follows.

  1. implement the OnClickListener class
  2. Bind the buttons click event to the dialog class
  3. Switch out the buttons in the onClick button based on id. You'd need to add an id to your button.

.

public class TestDialog extends Dialog implements android.view.View.OnClickListener
{
    protected void onCreate(final Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.dialog);
        ((Button)findViewById(R.id.dialog_btn_mybutton)).setOnClickListener(this);
    }



public void onClick(View view) 
{
    switch (view.getId())
    {
        case R.id.dialog_btn_mybutton:
            //do stuff
            // dismiss();
            // cancel etc.
        break;
    }
}

}

Hope that helps. Would still be interested in knowing if there was a solution to using xml onClick to bind to the method. Perhaps an additional argument in the setContentView? something r'other.

Emile
  • 10,786
  • 4
  • 45
  • 56
2

I've found the following code in the View.java source:

public void onClick(View v) {
                            if (mHandler == null) {
                                try {
                                    mHandler = getContext().getClass().getMethod(handlerName,
                                            View.class);
    ...

-> The views uses its context to resolve the onclick handler method.

Noew the following code from Dialog.java source:

public Dialog(Context context, int theme) {
    mContext = new ContextThemeWrapper(context, theme == 0 ? com.android.internal.R.style.Theme_Dialog : theme);
    ...

In the constructor of the dialog an instance of ContextThemeWrapper gets created and set as context. This instance is neither the custom dialog class, nor the calling activity, which can be the place for implementing the handler method. Therefore views are not able to find the onclick handler method.

But I have to use the onclick XML attribut. Any workarounds available?

Impression
  • 727
  • 1
  • 5
  • 14
1

Dialogs need the signature

dialogClicked(DialogInterface dialog, int id) { ... }
David Hedlund
  • 121,697
  • 28
  • 196
  • 213
  • Can you give me a more concrete example, beacause your answer does not work - in the way, I have understood :) I've tried to use this method in the calling activity and the dialog. But still get the NoSuchMethodExcepion dialogClicked(View). – Impression Nov 22 '10 at 09:24
  • Don't want catch the normal onClick event by OnClickListener, want to use the android:onClick functionality. – Impression Nov 25 '10 at 22:56
1

android:onClick="method" is pretty cool, but it doesn't work on Android 1.5 so I am avoiding for some time.

An easy workaround:

Make your Dialog an Activity and use android:theme="@android:style/Theme.Dialog" in you AndroidManifest.

Macarse
  • 87,001
  • 42
  • 169
  • 229
1

Following on from Jett Hsieh's post, I've implemented my dialogs slightly differently using showDialog and dismissDialog, but the fundamentals of getting the android:onClick working have been the same, my example code is below for future reference.

public class ExampleActivity extends Activity { 
    static final int DIALOG_DISCLAIMER = 0;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);

        showDialog(DIALOG_DISCLAIMER);
    }

    protected Dialog onCreateDialog(int id)
    {
        Dialog dialog;
        switch(id)
        {
            case DIALOG_DISCLAIMER:
                dialog = new Dialog(this);
                dialog.setContentView(R.layout.main_disclaimer);

                LinearLayout ll = (LinearLayout) LayoutInflater.from(this).inflate(R.layout.main_disclaimer, null);
                dialog.setContentView(ll);

                break;
            default:
                dialog = null;
        }       
        return dialog;
    }

    public void onClick(View v)
    {
        switch(v.getId())
        {
            case R.id.maindisclaimer_button_accept:
                dismissDialog(DIALOG_DISCLAIMER);
                break;
        }
    }
}

And the layout file:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
              android:layout_width="fill_parent" 
              android:layout_height="fill_parent" 
              android:id="@+id/linearLayout1" 
              android:padding="10dp" 
              android:orientation="vertical"
              android:background="@drawable/roundedcorners">
    <Button
            android:id="@+id/maindisclaimer_button_accept"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="center"
            android:text="@string/string_accept"
            android:onClick="onClick" >
        </Button>
</LinearLayout>
Kennifer
  • 1,315
  • 2
  • 15
  • 21
0

Try to define that method (dialogClicked) in the activity and not in the dialog.

It might use reflection so if you use different activities just write that method in each activity that might show that dialog

Pedro Loureiro
  • 11,134
  • 2
  • 28
  • 37
  • I've already tried before I'm asking my question at stackoverflow - does not work. At his moment I think, this problem can't be fixed, because of the reflection mechanism within the default view implementation. – Impression Nov 27 '10 at 18:04
0

A dialog is always created and displayed as part of an Activity. According to Android References:

If you decide to create a dialog outside of the onCreateDialog() method, 
it will not be attached to an Activity. You can, however, 
attach it to an Activity with setOwnerActivity(Activity).

Also, are you passing the object returned by getApplicationContext(); to the constructor of TestDialog?

Raunak
  • 6,177
  • 9
  • 36
  • 52
  • Does not work (tested it). According to the code, I 've posted in an answer, you can see that Android's dialog constructor implementation creates an own, private instance of the context (ContextThemeWrapper). The reflection call, which is used by the onclick event to determine the handler method, is against these internal created context. – Impression Nov 28 '10 at 10:42
0

system looks for the method in the where the layout has been inflated from, or in the activity class to which the xml was set as content.

noob
  • 204
  • 2
  • 12