DialogFragment中的ViewPager - IllegalStateException:Fragment没有视图

时间:2013-11-30 18:15:09

标签: android android-fragments android-viewpager android-dialogfragment

我想要实现的目标

  • 单击操作栏中的操作按钮时,FragmentActivity显示一个对话框
  • DialogFragment - 没有标题的对话
  • TabHost - 对话框顶部的标签
  • ViewPagerFragmentPagerAdapter - 可切换,内容已连接到标签
  • 2-3对话框按钮(对话框的不同子类,不同的按钮) - 不应该在ViewPager的{​​{1}}之一,这意味着相同的按钮应保留在底部对话框,无论Fragment显示Fragment是什么。


问题

ViewPager


到目前为止我尝试过/做过什么

  • IllegalStateException: Fragment does not have a view 包用于必要的类
  • 致电android.support.v4而非getChildFragmentManager()
  • 通过此链接 https://code.google.com/p/android/issues/detail?id=42601 实施了#10建议的帖子。我将代码直接复制/粘贴到我的两个getSupportedFragmentManager()类中,Fragment假设要显示这些类,再加上ViewPager类。
  • 在我的自定义DialogFragment中,我首先尝试覆盖DialogFragment,然后onCreateView,然后同时覆盖onCreateDialog。所有这些我都要跑,但意外的结果。
    • onCreateView:无法到达AlertDialog.Builder创建所需的按钮,而Dialog的结果非常棒。
    • onCreateDialog:上面显示的错误消息。我仍然认为这种方法与我想达到的目标一样接近。
    • onCreateViewonCreateDialog:在onCreateView中夸大了对话框布局,并将对话框按钮添加到AlertDialog.Builder中的onCreateDialog。这显示了对话框,但AlertDialog.Builder中添加的按钮不可见。另外,点击EditText字段时键盘没有显示。


源代码

大多数来自 Tutorial to implement the use of TabHost in Android 2.2 + ViewPager and Fragments ActivityFragment的代码改为DialogFragment。但是,我使用此答案 https://stackoverflow.com/a/18167273/2375978 的源代码中的修改后的ViewPager替换了它。这是为了wrap_content高度。

我相信,我的项目中的错误代码采用DialogFragment的{​​{1}}方法。

onCreateDialog


堆栈跟踪LogCat日志

@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
    AlertDialog.Builder builder = new AlertDialog.Builder(getActivity(), AlertDialog.THEME_HOLO_DARK);
    LayoutInflater inflater = getActivity().getLayoutInflater();
    view = inflater.inflate(R.layout.dialog_test, null);
    addActionButtons(builder, view);    
    builder.setView(view);

    mViewPager = (WrapContentHeightViewPager) view.findViewById(R.id.viewpager);

    initialiseTabHost();

    List<Fragment> fragments = getFragments();

    pageAdapter = new DialogPageAdapter(getChildFragmentManager(), fragments);
    mViewPager.setAdapter(pageAdapter);
    mViewPager.setOnPageChangeListener(this);

    Dialog dialog = builder.create();
    dialog.requestWindowFeature(Window.FEATURE_NO_TITLE);
    dialog.getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE);
    dialog.show();

    return dialog;
}


另外...

4 个答案:

答案 0 :(得分:35)

我想我刚遇到同样的问题并通过查看DialogFragment的来源了解了一些事情。

看起来即使重写onCreateDialog(...)是创建自定义对话框的有效方法,它也会导致DialogFragment具有空视图,就像错误消息所示。在大多数情况下这很好 - DialogFragment不需要View来显示对话框,但如果你想进一步嵌套片段(就像你那样),这将不会飞。

考虑到你想要与AlertDialog.Builder交互,我真的找不到完美的解决方案,但你有几个选择:

  1. 在对话框中创建按​​钮作为View的一部分(不使用AlertDialog.Builder)。您可以通过覆盖onCreateDialog的onCreateView 而不是来完成此操作。您应该能够通过将按钮放在自己的片段中来获得您提到的功能。我们在演出时做了类似的事情,我更喜欢这种方法。
  2. 实现您自己的类型,该类型继承自Fragment,并以各种方式镜像DialogFragment,除了允许您需要的内容。这不应该太吓人,因为DialogFragment只有~400并且评论很多。可能很有趣。
  3. 使用常规的PagerAdapter而不是FragmentPagerAdapter。这样,您的DialogFragment没有View。

答案 1 :(得分:20)

使用

onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)

而不是onCreateDialog(Bundle savedInstanceState)。不要创建警报对话框,使用方法提供的inflater,并构建视图。它对我有用。

祝你好运!

答案 2 :(得分:2)

感谢@Tommy Visic编写了一个非常好的描述,它起作用了。

发布适合我的代码。

我已从Dialog方法infact删除onCreateDialog方法中移除了onCreateDialog建筑代码,以及我在Dialog's自定义视图中实施的对话视图在View方法中将其作为onCreateView包含在内,所有内容都开始有效。

@Nullable
@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
    View view = inflater.inflate(R.layout.login_sigup_screen, null, false);
    bind = ButterKnife.bind(this, view);
    initViewPager();
    return view;
}

这个实现面临的另一个问题是:

ActivityToolbar/ActionBar时,它也会显示在DialogFragment中,以避免要做的是: 实施onViewCreated的{​​{1}}方法并添加以下代码

Fragment

这将从Dialog dialog = getDialog(); dialog.getWindow().requestFeature(Window.FEATURE_NO_TITLE); float dimAmount = 0.6f; dialog.getWindow().setDimAmount(dimAmount); 移除ToolbarDialogFragment将按原样显示。

干杯

谢谢@Tommy

此致 宙斯

答案 3 :(得分:1)

如果实现onCreateDialog以使用AlertDialog,则在访问IllegalStateException: Fragment does not have a view或类似的东西时会碰到getChildFragmentManager

要解决此问题,请同时实现onCreateDialogonCreateView,其中onCreateView返回以onCreateDialog夸大的视图。

class LocationPickerDialog : DialogFragment() {

    lateinit var customView: View

    override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
        return customView
    }

    override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
        Log.d(TAG, "onCreateDialog")
        // StackOverflowError
        // customView = layoutInflater.inflate(R.layout.dialog_location_picker, null)
        customView = activity!!.layoutInflater.inflate(R.layout.dialog_location_picker, null)

        val builder = AlertDialog.Builder(context!!)
                .setView(customView)
                .setPositiveButton(android.R.string.ok) { _, _ ->
                    // do something
                }
                .setNegativeButton(android.R.string.cancel) { _, _ ->
                    // do something
                }
        val dialog = builder.create()

        return dialog
    }

    override fun onActivityCreated(savedInstanceState: Bundle?) {
        // if onCreateView doesn't return a view 
        // java.lang.IllegalStateException: Fragment does not have a view
        mapFragment = childFragmentManager.findFragmentByTag("map") as SupportMapFragment?
    }
}

https://code.luasoftware.com/tutorials/android/android-alertdialog-in-dialogfragment-fragment-does-not-have-a-view/