【问题标题】:Using onClick attribute in layout xml causes a NoSuchMethodException in Android dialogs在布局 xml 中使用 onClick 属性会导致 Android 对话框中出现 NoSuchMethodException
【发布时间】:2011-05-13 17:21:38
【问题描述】:

我已经创建了一个自定义对话框和一个布局 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'。在布局 xml 中设置 onClick 处理程序适用于活动,但不适用于对话框。有任何想法吗?我做错了什么?

【问题讨论】:

标签: android onclick nosuchmethoderror


【解决方案1】:

对话框需要签名

dialogClicked(DialogInterface dialog, int id) { ... }

【讨论】:

  • 你能给我一个更具体的例子吗,因为你的答案不起作用-顺便说一句,我已经理解了:) 我尝试在调用活动和对话框中使用这种方法。但仍然得到 NoSuchMethodExcepion dialogClicked(View)。
  • 不想通过 OnClickListener 捕获正常的 onClick 事件,想使用 android:onClick 功能。
【解决方案2】:

我在 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 实例被创建并设置为上下文。这个实例既不是自定义对话框类,也不是调用Activity,可以作为实现handler方法的地方。因此视图无法找到 onclick 处理程序方法。

但我必须使用 onclick XML 属性。有没有可用的解决方法?

【讨论】:

  • 由于这不是答案,我宁愿将其作为对您问题的进一步调查。
【解决方案3】:

尝试在活动中而不是在对话框中定义该方法(dialogClicked)。

它可能会使用反射,因此如果您使用不同的活动,只需在每个可能显示该对话框的活动中编写该方法

【讨论】:

  • 在我在 stackoverflow 提问之前我已经尝试过 - 不起作用。目前我认为,由于默认视图实现中的反射机制,这个问题无法解决。
【解决方案4】:

对话框总是创建并显示为 Activity 的一部分。根据 Android 参考资料:

如果你决定在 onCreateDialog() 方法之外创建一个对话框,
它不会附加到 Activity。但是,您可以
使用 setOwnerActivity(Activity) 将其附加到 Activity。

另外,你是否传递了 getApplicationContext(); 返回的对象?到TestDialog的构造函数?

【讨论】:

  • 不起作用(已测试)。根据我在答案中发布的代码,您可以看到Android的对话框构造函数实现创建了一个自己的私有上下文实例(ContextThemeWrapper)。 onclick 事件用来确定处理程序方法的反射调用是针对这些内部创建的上下文。
【解决方案5】:

我认为问题是范围之一。我不确定你是如何在 xml 中解决这个问题的,但基本上你的布局 xml 中的 dialogClicked 方法不知道在哪里可以找到你在对话框类中定义的方法。

我见过的在自定义布局中绑定按钮的标准方法如下。

  1. 实现 OnClickListener 类
  2. 将按钮单击事件绑定到对话框类
  3. 根据 id 切换 onClick 按钮中的按钮。您需要为按钮添加一个 ID。

.

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 中的附加参数?别的东西。

【讨论】:

    【解决方案6】:

    android:onClick="method" 很酷,但它不适用于 Android 1.5,所以我暂时避免使用。

    一个简单的解决方法:

    将Dialog 设为Activity 并在AndroidManifest 中使用android:theme="@android:style/Theme.Dialog"。

    【讨论】:

      【解决方案7】:

      在Activity中定义方法(dialogClicked)。 并修改 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); 
       }
      }
      

      我认为它有效:)

      【讨论】:

      • 是的,这就是重点:在Activity中定义方法(dialogClicked),如果你使用onClick的话。
      • Thx... 现在我至少可以在 Activity 中捕获该事件,并有一个条目进行进一步优化,以将处理程序方法移动到对话框实现中。
      • @Jett Hsieh 很好,但我将如何编写按钮取消和按钮选择的代码,以便我可以关闭对话框,我在这种技术中遇到错误
      【解决方案8】:

      继 Jett Hsieh 的帖子之后,我使用 showDialog 和dismissDialog 实现了我的对话框略有不同,但让 android: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>
      

      【讨论】:

        【解决方案9】:

        系统在布局被膨胀的地方,或者在 xml 被设置为内容的活动类中寻找方法。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2012-09-16
          • 1970-01-01
          • 2012-12-27
          • 2011-11-06
          • 2015-02-07
          • 1970-01-01
          • 1970-01-01
          • 2012-05-22
          相关资源
          最近更新 更多