在DialogFragment中为AlertDialog夸大自定义视图的问题

我正在尝试在DialogFragment使用自定义视图创build一个AlertDialog 。 这个视图必须从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) 

而如果我尝试使用这样的DialogFragmentgetLayoutInflator(Bundle)

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

我得到一个StackOverflowError

有谁知道如何膨胀AlertDialog的自定义视图?

第一个错误行给我提示,这与你如何创build对话框有关,而不是对话框本身。

你是否自动创build对话框(这可能意味着在视图全部设置之前被调用)或响应button单击? 由于实例化顺序,我最初遇到了碎片问题。

我使用相同的代码来设置视图,我的结果工作。 我剪掉了另一个设置,使其看起来更清洁,但它可以使用或不使用它。

 @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(); } 

我很惊讶这些答案,因为他们都不能解决问题。

DialogFragment允许你重复使用同一个UI作为对话框,并作为一个片段集成到你的应用程序中。 相当有用的function。 根据谷歌的文档,你可以通过覆盖onCreateDialog和onCreateView来实现。 http://developer.android.com/reference/android/app/DialogFragment.html

这里有三种情况:

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

解决scheme:AlertDialog类正在调用另一个调用requestFeature的类。 要解决这个问题..不要使用AlertDialog,而是使用普通的Dialog或者其他的super.onCreateDialog函数返回。 这个我find的解决scheme效果最好。

警告:其他对话如DatePickerDialog,ProgressDialog,TimePickerDialog都从AlertDialoginheritance,并可能导致相同的错误。

底线:D​​ialogFragment是好的,如果你需要创build非常定制的界面,需要在几个地方使用。 它似乎没有工作来重用现有的android对话框。

避免请求function崩溃,并使用相同的布局:

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

我有同样的问题。 在我的情况下,这是因为Android Studio创build了一个模板onCreateView重新充实新视图,而不是返回在onCreateDialog中创build的视图。 onCreateView在onCreateDialog之后被调用,所以解决方法是简单地重新使用fragment视图。

 @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { return this.getView(); } 

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

.setView(R.layout.dialog)

在你的代码中你打电话

  create(). 

用。。。来代替

 show(). 

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

 @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(); } 

你想要做的就是像通常那样在onCreateView方法中创build自定义视图。 如果你想做一些改变对话框标题的东西,你可以在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(..); 

瞧,与您自己的自定义视图对话。

因为我需要很长的时间来解决同样的问题(popup一个简单的文本对话框),我决定分享我的解决scheme:

布局文件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> 

显示“对话框”的活动实现了一个内部类(因为DialogFragment是一个片段而不是一个对话框;更多信息请参阅https://stackoverflow.com/a/5607560/6355541 )。 活动可以通过两个function激活和停用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"); }