在布局 xml 中使用 onClick 属性会导致 Android 对话框中出现 NoSuchMethodException

发布于 2024-10-04 05:30:28 字数 995 浏览 10 评论 0原文

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

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?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(9

桃扇骨 2024-10-11 05:30:28

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

我认为它有效:)

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 :)

墨小墨 2024-10-11 05:30:28

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

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

  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 中还有一个附加参数?其他的东西。

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.

千笙结 2024-10-11 05:30:28

我在 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 处理程序方法。

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

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?

记忆で 2024-10-11 05:30:28

对话框需要签名

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

Dialogs need the signature

dialogClicked(DialogInterface dialog, int id) { ... }
染柒℉ 2024-10-11 05:30:28

android:onClick="method" 非常酷,但它在 Android 1.5 上不起作用,所以我回避了一段时间。

一个简单的解决方法:

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

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.

情痴 2024-10-11 05:30:28

继 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>

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>
过潦 2024-10-11 05:30:28

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

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

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

鲜血染红嫁衣 2024-10-11 05:30:28

对话框总是作为活动的一部分创建和显示。根据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 的构造函数?

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?

权谋诡计 2024-10-11 05:30:28

系统在布局膨胀的位置或将 xml 设置为内容的活动类中查找方法。

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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文