为什么我可以在活动/提要中使用onClick,但是,不是在对话框片段中?

时间:2014-05-24 18:20:44

标签: android android-activity android-dialogfragment

在Android上这里是一个很好的代码片段,

展示如何在对话框片段 ...

上实现五个按钮

android DialogFragment android:onClick="buttonCancel" causes IllegalStateException could not find a method

在您的DialogFragment中,您必须为所有按钮/图像视图等 setOnClickListener(this)

然后你实现View.OnClickListener并有一个这样的例程......

public void onClick(View v)
    {
    Utils.Log("Fucking 'A' sort of... ");
    switch (v.getId())
        {
        case R.id.postfragment_send:
            break;
        etc etc etc
        default:
            break;
        }
    }

这太棒了。 BUT。


在我的主要活动中,我有一个ListView。自定义单元格有五个按钮。很简单,在主要活动中,我有五个以我喜欢的名字命名的例程......

public void clickedComments(View v)
    {
    int position = feed.getPositionForView(v);
    ...etc etc
    }
public void clickedExplosions(View v)
    {
    int position = feed.getPositionForView(v);
    ...etc etc
    }
public void clickedTanks(View v)
    {
    int position = feed.getPositionForView(v);
    ...etc etc
    }

然后你就做了这个令人难以置信的简单(“螺丝Xcode!”)......

enter image description here

惊人!


我的问题,为什么我不能在对话框片段中使用'onClick系统'?

我做错了什么? Android专家可以解释两者之间的根本区别吗?为了记录我的项目只有4.1+。

谢谢!


在这里,我使用上述第一种方法粘贴片段的完整示例。

public class HappyPopupFragment extends DialogFragment implements View.OnClickListener
    {
    @Override
    public Dialog onCreateDialog(Bundle savedInstanceState)
        {
        Dialog dialog = super.onCreateDialog(savedInstanceState);

        dialog.getWindow().requestFeature(Window.FEATURE_NO_TITLE);
        dialog.getWindow().setGravity(Gravity.CENTER_HORIZONTAL | Gravity.TOP);
        dialog.getWindow().setBackgroundDrawableResource(android.R.color.transparent);

        return dialog;
        }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
        {
        View view = inflater.inflate(R.layout.happy_popup, container);
        _setupButtons(view);
        return view;
        }

    public void onClick(View v)
        {
        Utils.Log("Fucking 'A' sort of... ");
        switch (v.getId())
            {
            case R.id.button_a:
                Utils.Log("tanks !!");
                break;

            case R.id.button_b:
                Utils.Log("bombs !!");
                break;

            case R.id.button_c:
                Utils.Log("guns !!");
                break;

            case R.id.button_d:
                Utils.Log("ammo !!");
                break;

            default:
                break;
            }
        }

    private void _setupButtons(View view)
        {
        ((ImageView)view.findViewById(R.id.button_a)).setOnClickListener(this);
        ((ImageView)view.findViewById(R.id.button_b)).setOnClickListener(this);
        ((ImageView)view.findViewById(R.id.button_c)).setOnClickListener(this);
        ((TextView)view.findViewById(R.id.button_d)).setOnClickListener(this);
        }

    }

3 个答案:

答案 0 :(得分:2)

这实际上是一个非常简单的答案,但您必须通过记住Android 1.0没有Fragments来启动它。

首先让我们看看活动到底是什么:

java.lang.Object
   ↳    android.content.Context
       ↳    android.content.ContextWrapper
           ↳    android.view.ContextThemeWrapper
               ↳    android.app.Activity

扩展Context的对象,它是什么。

因此,当您扩展XML布局时,该方法inflate正在执行诸如创建和设置视图之类的内容:

View v = new View(context) // see the context here ?

然后当您设置XML onClick:commentsClick时,单击时发生的是:

getContext().commentsClick(View.this); // look, the context again

所以让我们分析一下:

XML onClick尝试回调上下文,这意味着回调膨胀它的活动。看到IllegalStateException消息说它无法找到方法?好吧,因为它不在活动中。可能如果你将commentsClick放在创建DialogFragment的Activity中,它会起作用,但那只是坏O.O.,对吧?

使用XML onClick的东西是一个很好的促进者,可以避免使用巨大的switch(int) case,但它是一个解决方案,它不能扩展到可能会增加布局的其他类,例如{{ 1}}。

答案 1 :(得分:1)

您可以在每个View及其子类上使用onClickListener

setOnClickListener将实现View.OnclickListener的类的实例作为参数。

如果setOnClickListener(this)上有错误,则表示此引用的对象是未实现View.OnClickListener的类的对象


换句话说......

以下是如何让onClickListener为自定义对话框片段中的自定义列表视图中的自定义单元格工作!

在列表视图的ADAPTER类(1)中,您将拥有设置每个单元格值的代码。 (设置文本和操作系统。)实际上,在每个单元格按钮的相同代码集onClickListener中:

v.nameTV.setText( "User Name" );
v.inviteIV.setOnClickListener( ourBoss ); // like this

问题是如何设置监听器。实际上你希望它成为你的对话片段。 " ourBoss"将是 DialogFragment 。所以(2)当对话框片段创建适配器时,将其传递给:

在创建适配器的对话框片段中

fosAdapter = new YourHappyAdapter(
   getActivity(), getActivity().getLayoutInflater(),
   otherStuff, otherStuff, this);

并在适配器本身......

public class YourHappyAdapter extends BaseAdapter
  {
  YourDialogFragmentClass ourBoss;

  public FosAdapter(
        Context context, LayoutInflater inflater,
         blah, blah,
         YourDialogFragmentClass ydfc)
        {
        blah
        blah

        ourBoss = ydfc;
        }

最后,然后(3)以通常的方式,在YourDialogFragmentClass中,你可以拥有通常的onClick代码!!万岁,你已经完成了!!

  public void onClick(View v)
    {
    switch (v.getId())
      {
      case R.id.submit_button: // from the overall fragment screen
        _searchNow();
        break;

      case R.id.cell_button:      // that one's from a cell.
        Utils.Log("IT WORKED !!!!!!!!!!!!!!!!! !!");
        userWantsANewTank(v);
        break;

      default:
        break;
      }
    }

使用"老式的"(基本上)是不现实的。 xml-handy-onClick方法,在执行自定义表和自定义对话框片段时!

希望它有所帮助!

答案 2 :(得分:1)

这只是Android DialogFragment API的一个事实。片段XML布局中定义的回调方法在包含此片段的Activity中调用。它比你的意思更简单,因为在以前的Android API中,这样的" XML定义"回调也在活动中被调用。

(从我的评论中转移出来,因为它可以解答我对主题问题的回答。也许这对本主题的未来读者来说会更方便。)