Использование атрибута onClick в макете XML вызывает исключение NoSuchMethodException в диалоговых окнах Android - PullRequest
16 голосов
/ 22 ноября 2010

Я создал пользовательский диалог и макет 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>

В классе диалога я реализовал метод "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");
 }

}

Когда я нажимаю на кнопку, я получаю NoSuchMethodException «dialogClicked».Установка обработчика onClick в макете xml отлично работает для действий, но не для диалогов.Есть идеи?Что я делаю не так?

Ответы [ 9 ]

25 голосов
/ 01 декабря 2010

Определите метод (dialogClicked) в Activity.И измените TestDialog, как следующий код:

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); 
 }
}

Я думаю, что это работает:)

6 голосов
/ 29 ноября 2010

Я думаю, что проблема - в сфере. Я не уверен, как вы обратились к этому в xml, но по сути метод dialogClicked в вашем макете xml не знает, где найти метод, который вы определили в классе диалога.

Стандартный подход, который я видел для привязки кнопок в пользовательских макетах, следующий:

  1. реализовать класс OnClickListener
  2. Свяжите событие нажатия кнопок с классом диалога
  3. Выключите кнопки в кнопке onClick на основе идентификатора. Вам нужно добавить идентификатор для вашей кнопки.

.

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;
    }
}

}

Надеюсь, это поможет. Было бы все еще интересно узнать, существует ли решение для использования xml onClick для привязки к методу. Возможно, дополнительный аргумент в setContentView? что-то другое.

2 голосов
/ 22 ноября 2010

Я нашел следующий код в источнике View.java:

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

-> Представления используют свой контекст для разрешения метода обработчика onclick.

Новый код из источника Dialog.java:

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

В конструкторе диалога создается экземпляр ContextThemeWrapper, который устанавливается в качестве контекста. Этот экземпляр не является ни пользовательским классом диалога, ни вызывающим действием, которое может быть местом для реализации метода обработчика. Поэтому представления не могут найти метод обработчика onclick.

Но мне нужно использовать атрибут XML onclick. Есть ли обходные пути?

1 голос
/ 10 ноября 2011

Исходя из поста Джетт Сии, я реализовал свои диалоги немного по-разному, используя showDialog и dismissDialog, но основы работы андроида: onClick были такими же, мой пример кода ниже для дальнейшего использования.

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;
        }
    }
}

И файл макета:

<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>
1 голос
/ 30 ноября 2010

android:onClick="method" довольно круто, но он не работает на Android 1.5, поэтому я некоторое время избегаю.

Простой обходной путь:

Создайте Dialog Activity и используйте android:theme="@android:style/Theme.Dialog" в себе AndroidManifest.

1 голос
/ 22 ноября 2010

Диалогам нужна подпись

dialogClicked(DialogInterface dialog, int id) { ... }
0 голосов
/ 23 декабря 2011

Система ищет метод в том месте, откуда был накачан макет, или в классе активности, для которого XML был задан в качестве содержимого.

0 голосов
/ 28 ноября 2010

Диалог всегда создается и отображается как часть действия.Согласно 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).

Также вы передаете объект, возвращенный getApplicationContext ();конструктору TestDialog?

0 голосов
/ 27 ноября 2010

Попробуйте определить этот метод (dialogClicked) в действии, а не в диалоге.

В нем может использоваться отражение, поэтому, если вы используете разные действия, просто напишите этот метод в каждом действии, которое может показать это диалоговое окно

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...