50

我正在尝试DialogFragmentAlertDialog. 这个视图必须是从 xml 扩展而来的。在我的DialogFragment课堂上,我有:

@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
    return new AlertDialog.Builder(getActivity())
        .setTitle("Title")
        .setView(getActivity().getLayoutInflater().inflate(R.layout.dialog, null))
        .setPositiveButton(android.R.string.ok, this)
        .setNegativeButton(android.R.string.cancel, null)
        .create();
}

我尝试过其他通货膨胀方法,.setView()例如:

.setView(getActivity().getLayoutInflater().inflate(R.layout.dialog, (ViewGroup) getView(), false))

.setView(getActivity().getLayoutInflater().inflate(R.layout.dialog, (ViewGroup) getTargetFragment().getView(), false))

在显示此对话框的片段中设置目标片段后。

所有这些膨胀我的自定义视图的尝试都会导致以下异常:

E/AndroidRuntime(32352): android.util.AndroidRuntimeException: requestFeature() must be called before adding content
E/AndroidRuntime(32352):        at com.android.internal.policy.impl.PhoneWindow.requestFeature(PhoneWindow.java:214)
E/AndroidRuntime(32352):        at com.android.internal.app.AlertController.installContent(AlertController.java:248)
E/AndroidRuntime(32352):        at android.app.AlertDialog.onCreate(AlertDialog.java:314)
E/AndroidRuntime(32352):        at android.app.Dialog.dispatchOnCreate(Dialog.java:335)
E/AndroidRuntime(32352):        at android.app.Dialog.show(Dialog.java:248)
E/AndroidRuntime(32352):        at android.support.v4.app.DialogFragment.onStart(DialogFragment.java:339)
E/AndroidRuntime(32352):        at android.support.v4.app.Fragment.performStart(Fragment.java:1288)
E/AndroidRuntime(32352):        at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:873)
E/AndroidRuntime(32352):        at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1041)
E/AndroidRuntime(32352):        at android.support.v4.app.BackStackRecord.run(BackStackRecord.java:625)
E/AndroidRuntime(32352):        at android.support.v4.app.FragmentManagerImpl.execPendingActions(FragmentManager.java:1360)
E/AndroidRuntime(32352):        at android.support.v4.app.FragmentManagerImpl$1.run(FragmentManager.java:411)
E/AndroidRuntime(32352):        at android.os.Handler.handleCallback(Handler.java:587)
E/AndroidRuntime(32352):        at android.os.Handler.dispatchMessage(Handler.java:92)
E/AndroidRuntime(32352):        at android.os.Looper.loop(Looper.java:132)
E/AndroidRuntime(32352):        at android.app.ActivityThread.main(ActivityThread.java:4028)
E/AndroidRuntime(32352):        at java.lang.reflect.Method.invokeNative(Native Method)
E/AndroidRuntime(32352):        at java.lang.reflect.Method.invoke(Method.java:491)
E/AndroidRuntime(32352):        at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:844)
E/AndroidRuntime(32352):        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:602)
E/AndroidRuntime(32352):        at dalvik.system.NativeStart.main(Native Method)

如果我尝试像这样使用DialogFragment's getLayoutInflator(Bundle)

.setView(getLayoutInflater(savedInstanceState).inflate(R.layout.dialog, null))

我得到一个StackOverflowError.

有谁知道如何为AlertDialogin扩展自定义视图DialogFragment

4

9 回答 9

92

第一个错误行提示我这与您创建对话框的方式有关 - 而不是对话框本身。

您是自动创建对话框(这可能意味着在视图全部设置之前调用它)还是响应按钮单击?由于实例化顺序,我最初遇到了片段问题。

我使用与您相同的代码来设置视图,并且我的结果有效。我剪掉了其他设置以使其看起来更干净,但无论有没有它都可以使用。

@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
    AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());

    View view = getActivity().getLayoutInflater().inflate(R.layout.dialog_layout, null);
    builder.setView(view);

    return builder.create();
}
于 2012-01-17T20:01:58.197 回答
23

我对这些答案感到惊讶,因为它们都没有解决问题。

DialogFragment 允许您为对话框重用相同的 UI,并在其他地方作为片段集成到您的应用程序中。很实用的功能。根据谷歌的文档,您可以通过覆盖 onCreateDialog 和 onCreateView 来实现这一点。 http://developer.android.com/reference/android/app/DialogFragment.html

这里有三种情况:

  1. 仅覆盖 onCreateDialog - 作为对话框工作,但不能集成到其他地方。
  2. 仅覆盖 onCreateView - 不能用作对话框,但可以集成到其他地方。
  3. 覆盖两者 - 作为对话框工作,可以集成到其他地方。

解决方案:AlertDialog 类正在调用另一个调用 requestFeature 的类。要解决此问题.. 不要使用 AlertDialog,而是使用普通 Dialog 或 super.onCreateDialog 返回的任何内容。这是我发现的解决方案效果最好。

警告:DatePickerDialog、ProgressDialog、TimePickerDialog 等其他对话框都继承自 AlertDialog,并且可能会导致相同的错误。

底线:如果您需要创建需要在多个地方使用的非常定制的界面,DialogFragment 是很好的选择。重用现有的android对话框似乎不起作用。

于 2014-01-30T20:46:06.980 回答
11

避免请求功能崩溃并使用相同的布局:

public class MyCombinedFragment extends DialogFragment
{
    private boolean isModal = false;

    public static MyCombinedFragment newInstance()
    {
        MyCombinedFragment frag = new MyCombinedFragment();
        frag.isModal = true; // WHEN FRAGMENT IS CALLED AS A DIALOG SET FLAG
        return frag;
    }

    public MyCombinedFragment()
    {
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) 
    {
        if(isModal) // AVOID REQUEST FEATURE CRASH
        {
        return super.onCreateView(inflater, container, savedInstanceState);
        }
        else
        {
        View view = inflater.inflate(R.layout.fragment_layout, container, false);
        setupUI(view);
        return view;
        }
    }

    @Override
    public Dialog onCreateDialog(Bundle savedInstanceState)
    {
        AlertDialog.Builder alertDialogBuilder = null;
        alertDialogBuilder = new AlertDialog.Builder(getActivity());
        View view = getActivity().getLayoutInflater().inflate(R.layout.fragment_layout, null);
        alertDialogBuilder.setView(view);
        alertDialogBuilder.setTitle(“Modal Dialog“);
        alertDialogBuilder.setPositiveButton("Cancel", new DialogInterface.OnClickListener()
        {
            @Override
            public void onClick(DialogInterface dialog, int which)
            {
                dialog.dismiss();
            }
        });
        setupUI(view);
        return alertDialogBuilder.create();
    }
}
于 2014-02-08T08:13:35.180 回答
2

我有同样的问题。就我而言,这是因为 Android Studio 创建了一个模板 onCreateView,它重新膨胀了一个新视图,而不是返回在 onCreateDialog 中创建的视图。onCreateView 在 onCreateDialog 之后调用,因此解决方案是简单地重新启动片段视图。

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
                         Bundle savedInstanceState) {
    return this.getView();
}
于 2014-11-25T16:30:16.633 回答
1

面临同样的问题,花了很多时间来摆脱错误。最后将资源 ID 传递给 setView() 方法解决了这个问题。添加设置视图如下:

.setView(R.layout.dialog)

于 2015-12-09T05:53:04.227 回答
0

在您调用的代码中

 create().

用。。。来代替

show().
于 2011-09-22T00:52:15.257 回答
0

我没有从 XML 膨胀,但我已经成功地在 DialogFragment 中生成了动态视图:

@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
    m_editText = new EditText(getActivity());
    return new AlertDialog.Builder(getActivity())
            .setView(m_editText)
            .setPositiveButton(android.R.string.ok,null)
            .setNegativeButton(android.R.string.cancel, null);
            .create();
}
于 2011-11-03T21:29:57.077 回答
0

您想要做的是像往常一样在 onCreateView 方法中创建您的自定义视图。如果你想做一些事情,比如改变对话框的标题,你可以在 onCreateView 中做。

这是一个例子来说明我的意思:

        @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        getDialog().setTitle("hai");
        View v = inflater.inflate(R.layout.fragment_dialog, container, false);
        return v;
    }

然后你只需调用:

DialogFragment df = new MyDialogFragment();
df.show(..);

瞧,一个带有您自己的自定义视图的对话框。

于 2011-12-13T13:16:19.853 回答
0

由于我需要很长时间来解决同样的问题(弹出一个简单的文本对话框),我决定分享我的解决方案:

布局文件connectivity_dialog.xml 包含一个带有消息文本的简单TextView:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
              android:layout_width="wrap_content"
              android:layout_height="wrap_content"
              android:gravity="center"
              android:layout_gravity="center">
    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginStart="20dp"
        android:layout_marginEnd="20dp"
        android:layout_marginTop="20dp"
        android:layout_marginBottom="20dp"
        android:text="Connectivity was lost"
        android:textSize="34sp"
        android:gravity="center"
        />
</RelativeLayout>

显示“对话框”的 Activity 实现了一个内部类(因为 DialogFragment 是一个片段而不是一个对话框;更多信息请参见https://stackoverflow.com/a/5607560/6355541)。Activity 可以通过两个函数激活和停用 DialogFragment。如果您使用的是 android.support.v4,您可能需要更改为 getSupportFragmentManager():

public static class ConnDialogFragment extends DialogFragment {
    public static ConnDialogFragment newInstance() {
        ConnDialogFragment cdf = new ConnDialogFragment();
        cdf.setRetainInstance(true);
        cdf.setCancelable(false);
        return cdf;
    }
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        return inflater.inflate(R.layout.connectivity, container, false);
    }
}

private void dismissConn() {
    DialogFragment df = (DialogFragment) getFragmentManager().findFragmentByTag("conn");
    if (df != null) df.dismiss();
}

private void showConn() {
    FragmentTransaction ft = getFragmentManager().beginTransaction();
    Fragment prev = getFragmentManager().findFragmentByTag("conn");
    if (prev != null) ft.remove(prev);
    ft.addToBackStack(null);
    ConnDialogFragment cdf = ConnDialogFragment.newInstance();
    cdf.show(ft, "conn");
}
于 2017-02-17T17:04:03.930 回答