我正在尝试使用DialogFragment
中的自定义视图创建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)
如果我尝试使用DialogFragment
getLayoutInflator(Bundle)
这样的话:
.setView(getLayoutInflater(savedInstanceState).inflate(R.layout.dialog, null))
我得到StackOverflowError
。
是否有人知道如何为AlertDialog
中的DialogFragment
充气自定义视图?
答案 0 :(得分:86)
第一个错误行给出了一个暗示,这与你如何创建对话框有关 - 而不是对话框本身。
您是自动创建对话框(可能意味着在视图全部设置之前调用此对话框)还是响应按钮单击?由于实例化顺序,我最初遇到了碎片问题。
我使用相同的代码来设置视图,我的结果有效。我删除了其他设置,使其看起来更干净,但无论是否有效都可以。
@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();
}
答案 1 :(得分:22)
我对这些答案感到惊讶,因为他们都没有解决问题。
DialogFragment允许您为对话框重用相同的UI,并将其作为片段集成到您的app中。相当有用的功能。根据Google的文档,您可以通过覆盖onCreateDialog和onCreateView来实现此目的。 http://developer.android.com/reference/android/app/DialogFragment.html
这里有三种情况:
解决方案: AlertDialog类正在调用另一个调用requestFeature的类。解决这个问题..不要使用AlertDialog,而是使用普通的Dialog或者任何super.onCreateDialog返回。我找到的解决方案效果最好。
警告: 其他对话框,如DatePickerDialog,ProgressDialog,TimePickerDialog都继承自AlertDialog,可能会导致相同的错误。
底线: 如果您需要创建需要在多个地方使用的非常自定义的界面,DialogFragment是很好的。它似乎不能重用现有的android对话框。
答案 2 :(得分: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();
}
}
答案 3 :(得分:2)
我遇到了同样的问题。在我的例子中,因为Android Studio在创建了一个模板onCreateView,它重新夸大了一个新视图而不是返回在onCreateDialog中创建的视图。在onCreateDialog之后调用onCreateView,因此解决方案是简单地重新访问片段视图。
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
return this.getView();
}
答案 4 :(得分:1)
面对同样的问题,花了很多时间来摆脱错误。最后将资源ID传递给setView()方法解决了这个问题。添加设置视图如下:
.setView(R.layout.dialog)
答案 5 :(得分:0)
在您调用的代码中
create().
替换为
show().
答案 6 :(得分: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();
}
答案 7 :(得分: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(..);
瞧,这是一个带有你自己的自定义视图的对话框。
答案 8 :(得分:0)
由于我需要很长时间来解决同样的问题(弹出一个简单的文本对话框)我决定分享我的解决方案:
layoutfile 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>
活动显示&#34;对话框&#34;实现一个内部类(因为DialogFragment是一个片段而不是一个Dialog;更多信息请参见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");
}