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

Hen*_*ahl 29 android android-fragments android-viewpager android-dialogfragment

我想要实现的目标

  • FragmentActivity节目的对话点击操作栏的操作按钮时,
  • DialogFragment - 没有标题的对话
  • TabHost - 对话框顶部的选项卡
  • ViewPagerwith FragmentPagerAdapter- Swipable,其内容连接到Tabs
  • 2-3对话框按钮(对话框的不同的子类,不同的按钮) -不应该是在一个ViewPagerFragment,这意味着相同的按钮应保持在对话框的底部,不管是什么FragmentViewPager是显示.


问题

IllegalStateException: Fragment does not have a view
Run Code Online (Sandbox Code Playgroud)


到目前为止我尝试/做过的事情

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


源代码

大多数来自Tutorial在Android 2.2 + ViewPager和Fragments中实现TabHost的使用.ActivityFragment相反的代码是在DialogFragment.但是我用这个答案/sf/answers/1271709141/的源代码替换了它的ViewPager .这是为了能够wrap_content在高度.

我相信,我项目中的错误代码是用DialogFragmentonCreateDialog方法.

@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;
}
Run Code Online (Sandbox Code Playgroud)


堆栈跟踪LogCat日志

FATAL EXCEPTION: main
java.lang.IllegalStateException: Fragment does not have a view
    at android.support.v4.app.Fragment$1.findViewById(Fragment.java:1425)
    at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:901)
    at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1088)
    at android.support.v4.app.BackStackRecord.run(BackStackRecord.java:682)
    at android.support.v4.app.FragmentManagerImpl.execPendingActions(FragmentManager.java:1444)
    at android.support.v4.app.FragmentManagerImpl.executePendingTransactions(FragmentManager.java:461)
    at android.support.v4.app.FragmentPagerAdapter.finishUpdate(FragmentPagerAdapter.java:141)
    at android.support.v4.view.ViewPager.populate(ViewPager.java:1011)
    at android.support.v4.view.ViewPager.populate(ViewPager.java:880)
    at android.support.v4.view.ViewPager.onMeasure(ViewPager.java:1374)
    at my.app.package.name.WrapContentHeightViewPager.onMeasure(WrapContentHeightViewPager.java:31)
    at android.view.View.measure(View.java:15481)
    at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:5059)
    at android.widget.LinearLayout.measureChildBeforeLayout(LinearLayout.java:1396)
    at android.widget.LinearLayout.measureVertical(LinearLayout.java:681)
    at android.widget.LinearLayout.onMeasure(LinearLayout.java:574)
    at android.view.View.measure(View.java:15481)
    at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:5059)
    at android.widget.FrameLayout.onMeasure(FrameLayout.java:310)
    at android.view.View.measure(View.java:15481)
    at android.widget.RelativeLayout.measureChildHorizontal(RelativeLayout.java:617)
    at android.widget.RelativeLayout.onMeasure(RelativeLayout.java:399)
    at android.view.View.measure(View.java:15481)
    at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:5059)
    at android.widget.FrameLayout.onMeasure(FrameLayout.java:310)
    at android.view.View.measure(View.java:15481)
    at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:5059)
    at android.widget.FrameLayout.onMeasure(FrameLayout.java:310)
    at android.view.View.measure(View.java:15481)
    at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:5059)
    at android.widget.LinearLayout.measureChildBeforeLayout(LinearLayout.java:1396)
    at android.widget.LinearLayout.measureVertical(LinearLayout.java:681)
    at android.widget.LinearLayout.onMeasure(LinearLayout.java:574)
    at android.view.View.measure(View.java:15481)
    at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:5059)
    at android.widget.FrameLayout.onMeasure(FrameLayout.java:310)
    at android.view.View.measure(View.java:15481)
    at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:5059)
    at android.widget.FrameLayout.onMeasure(FrameLayout.java:310)
    at android.view.View.measure(View.java:15481)
    at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:5059)
    at android.widget.FrameLayout.onMeasure(FrameLayout.java:310)
    at com.android.internal.policy.impl.PhoneWindow$DecorView.onMeasure(PhoneWindow.java:2377)
    at android.view.View.measure(View.java:15481)
    at android.view.ViewRootImpl.performMeasure(ViewRootImpl.java:1982)
    at android.view.ViewRootImpl.measureHierarchy(ViewRootImpl.java:1200)
    at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:1398)
    at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:1118)
    at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:4525)
    at android.view.Choreographer$CallbackRecord.run(Choreographer.java:725)
    at android.view.Choreographer.doCallbacks(Choreographer.java:555)
    at android.view.Choreographer.doFrame(Choreographer.java:525)
    at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:711)
    at android.os.Handler.handleCallback(Handler.java:615)
    at android.os.Handler.dispatchMessage(Handler.java:92)
    at android.os.Looper.loop(Looper.java:137)
    at android.app.ActivityThread.main(ActivityThread.java:4946)
    at java.lang.reflect.Method.invokeNative(Native Method)
    at java.lang.reflect.Method.invoke(Method.jav
Run Code Online (Sandbox Code Playgroud)


也...

Tom*_*sic 37

我想我只是遇到了同样的问题,通过查看DialogFragment的源代码学到了一些东西.

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

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

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


Sky*_*ius 20

使用

onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
Run Code Online (Sandbox Code Playgroud)

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

最好的祝福!


Des*_*Lua 7

如果你实现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?
    }
}
Run Code Online (Sandbox Code Playgroud)

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