【问题标题】:android DialogFragment android:onClick="buttonCancel" causes IllegalStateException could not find a methodandroid DialogFragment android:onClick="buttonCancel" 导致 IllegalStateException 找不到方法
【发布时间】:2014-05-25 02:05:07
【问题描述】:

我的对话片段有问题。我想使用 android:onClick 属性,因为我认为代码更清晰。

在我的布局中,我有以下声明:

<Button
        android:id="@+id/dialog_new_database_button_cancel"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_weight="1"
        android:text="@string/button_cancel"
        android:maxLines="1"
        style="?android:attr/buttonBarButtonStyle"
        android:onClick="buttonCancel"
        />

现在是我的 DialogFragment

import android.os.Bundle;
import android.support.v4.app.DialogFragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;

public class DialogNewDatabase extends DialogFragment {

    public DialogNewDatabase() {
        // Empty constructor required for DialogFragment
        super();
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
    super.onCreateView (inflater, container, savedInstanceState);
        View view = inflater.inflate(R.layout.dialog_new_database, container);    
        getDialog().setTitle("Hello");
        return view;
    }

    @Override
    public void onCreate(Bundle bundle) {
        setCancelable(true);
        setRetainInstance(true);
        super.onCreate(bundle);

    }

    @Override
    public void onDestroyView() {
        if (getDialog() != null && getRetainInstance())
            getDialog().setDismissMessage(null);
        super.onDestroyView();
    }

    public void buttonCancel (View view) {
        dismiss();
    }

    public void buttonOK (View view) {

    }

}

现在当我尝试单击取消按钮时,我得到:

java.lang.IllegalStateException: Could not find a method buttonCancel(View) in the activity class android.view.ContextThemeWrapper for onClick handler on view class android.widget.Button with id 'dialog_new_database_button_cancel'
at android.view.View$1.onClick(View.java:3031)
at android.view.View.performClick(View.java:3511)
at android.view.View$PerformClick.run(View.java:14105)
at android.os.Handler.handleCallback(Handler.java:605)
at android.os.Handler.dispatchMessage(Handler.java:92)
at android.os.Looper.loop(Looper.java:137)
at android.app.ActivityThread.main(ActivityThread.java:4482)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:511)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:787)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:554)
at dalvik.system.NativeStart.main(Native Method)
Caused by: java.lang.NoSuchMethodException: buttonCancel [class android.view.View]
at java.lang.Class.getConstructorOrMethod(Class.java:460)
at java.lang.Class.getMethod(Class.java:915)
at android.view.View$1.onClick(View.java:3024)
... 11 more

有什么想法吗?这可能与我使用 import android.support.v4.app.DialogFragment (support v4) 的事实有关吗?如何解决(我还是更喜欢在 xml 布局中使用 android:onClick)。

【问题讨论】:

  • 相关SO question
  • @gunar 它不能解决问题。该讨论仅表明无法在使用 Fragments 时管理 onClick。
  • 您的问题是您使用的是onClick 属性。在那个链接中,我强调了为什么不应该使用这个属性。但是如果你很固执并且想要使用它,在这种情况下,你必须将 Activity 的操作委托给DialogFragment,就像下面的 reis_eliel 回答一样。
  • @gunar 非常感谢您的帮助。我可能会使用传统的 setOnClickListener(new Button.OnClickListener() { ... 但我真的不明白为什么 google 会添加一些不起作用的东西。(
  • 它们有效,但您不知道如何使用它们:P ...顺便说一句,将您的问题标记为已接受。否则人们会停止回复你。

标签: java android android-layout


【解决方案1】:

我会尝试另一种适合我的方法:

  1. 在您的片段中实现 OnClickListener:

    public class DialogNewDatabase extends DialogFragment implements OnClickListener`
    
  2. 在 xml 中有一个具有唯一 id 的按钮,不需要需要android:clickable

    <Button  android:id="@+id/dialog_new_database_button_cancel" />
    
  3. 在您的片段中覆盖方法onClick() 并在您的点击时插入一个反应:

    public void onClick(View v) {       
      switch (v.getId()) {
        case R.id.dialog_new_database_button_cancel:
            // your stuff here
            this.dismiss();
    
            break;          
        default:                
            break;
       }
    }   
    
  4. 导入必要的:

    import android.view.View.OnClickListener; 
    
  5. 在按钮上启动 onClickListener:

    private Button bCancel = null;
    bCancel = (Button) findViewById(R.id.dialog_new_database_button_cancel);
    bCancel.setOnClickListener(this);
    // it is possible that you might need the refrence to the view.
    // replace 2nd line with (Button) getView().findViewById(...);
    

    这样,您可以在同一个 onClick 方法中处理更多可点击按钮。您只需要使用可点击小部件的正确 ID 添加更多案例。

【讨论】:

  • 对不起,它不起作用。我在开关上放了断点,调试时它甚至不会停在这里。缺少什么?
  • 也许导入android.content.DialogInterface.OnClickListener;应该使用监听器吗?使用 public void onClick(DialogInterface dialog, int position) 方法?
  • 没办法,无论是 import android.view.View.OnClickListener 还是 android.content.DialogInterface.OnClickListener 都不起作用。调试器不会在方法的开头停止。我什至放了 Toast 消息想知道我的调试器是否工作正常。没门。唯一有效的方法是: cancel.setOnClickListener(new Button.OnClickListener() { public void onClick(View v) {dismiss(); } }); (是的,当我尝试使用 onClick 方法时,我将前一个方法的代码行标记为注释。这很令人惊讶不是......
  • 现在它像梦一样运作。谢谢你。但我仍然很好奇为什么 android:onClick 属性不起作用。 :(
  • @bofredo 感谢非常有用的代码摘录!我发了一个赏金来表示感谢。干杯。
【解决方案2】:

我认为这与支持片段无关。

问题似乎源于您在 XML 上注册了一个 onClick,该 XML 是基于在单击时绑定片段的活动而触发的。

由于您的“buttonCancel”方法在活动中不存在(因为它在片段内),所以它失败了。

我不认为这真的是一个理想的解决方案,但您可以在您的活动上注册您的“buttonCancel”方法以使该错误消失,并使在活动上注册的“buttonCancel”方法仅调用该方法存在于片段中,以防您想将动作/视图行为保留在片段中。

【讨论】:

  • 准确地说,我们有以下带有 ViewPager/Fragments/ 的构造 Activity,然后运行此 DialogFragment。我确定 android:onClick 已链接到 DialogFragment 并根据您的回答我了解 Android 试图在主 Activity 中找到它?很难相信它是这样设计的。
  • 我做了一个小测试,我在主要活动中添加了public void buttonCancel(查看视图)方法。但问题重演 - 仍然是同样的例外。也许我的 DialogFragment 类应该实现任何接口?
  • 我还将 buttonCancel 方法放在了 Fragment 类中。没门。 (
  • 好吧,还有其他一些事情:您的活动方法是否公开?是在托管片段的活动上吗?你的项目 API lvl 1.6+ 吗?
  • 是的方法是公开的。 android:minSdkVersion="14" android:targetSdkVersion="18"
【解决方案3】:

试试:

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
super.onCreateView (inflater, container, savedInstanceState);
    View view = inflater.inflate(R.layout.dialog_new_database, container);    
    getDialog().setTitle("Hello");
    return view;

    private void buttonCancel (View view) {
    dismiss();
    }
    private void buttonOK (View view) {
    }
}

【讨论】:

  • 将其设为私有无济于事。
猜你喜欢
  • 2014-06-19
  • 2014-10-07
  • 2013-04-01
  • 1970-01-01
  • 2017-07-11
  • 1970-01-01
  • 1970-01-01
  • 2014-03-07
  • 1970-01-01
相关资源
最近更新 更多