android-fragments 对话框片段中的视图寻呼机-非法状态异常:片段没有视图

pdkcd3nj  于 2022-11-13  发布在  Android
关注(0)|答案(6)|浏览(132)

我想要实现的目标

  • FragmentActivity单击操作栏中的操作按钮时显示对话框
  • DialogFragment-没有标题的对话框
  • TabHost-对话框顶部的选项卡
  • ViewPagerFragmentPagerAdapter-可切换,哪些内容连接到选项卡
  • 2-3对话框按钮(对话框的不同子类,不同的按钮)-不应位于ViewPagerFragment之一中,这意味着无论ViewPager显示的是什么Fragment,相同的按钮都应保留在对话框的底部。

问题

IllegalStateException: Fragment does not have a view

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

  • 对必要的类使用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来创建所需的按钮,除此之外,对话框的结果是伟大的。
  • 仅限onCreateDialog:上面显示错误消息。我仍然认为这个方法与我想要达到的目标非常接近。
  • onCreateViewonCreateDialog:扩大了onCreateView中的对话框布局,并将对话框按钮添加到onCreateDialog中的AlertDialog.Builder。这显示了对话框,但从AlertDialog.Builder添加的按钮不可见。另外,当单击EditText字段时,键盘不显示。

源代码

大部分来自**Tutorial to implement the use of TabHost in Android 2.2 + ViewPager and FragmentsActivityFragment的代码是在DialogFragment中。但是我用这个答案https://stackoverflow.com/a/18167273/2375978**的源代码中的修改版替换了它的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;
}

堆栈跟踪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

还有...

0tdrvxhp

0tdrvxhp1#

我想我刚刚遇到了同样的问题,通过查看DialogFragment的源代码,我学到了一些东西。
尽管覆盖onCreateDialog(...)是创建自定义对话框的有效方法,但它会导致DialogFragment的视图为空,就像错误消息中所说的那样。在大多数情况下,这是可以的-DialogFragment不需要视图来显示对话框,但如果您想进一步嵌套片段(就像您所做的那样),这就行不通了。
考虑到您希望与AlertDialog.Builder进行交互,我认为确实没有完美的解决方案,但您有几个选择:
1.在对话框中创建按钮作为视图的一部分(不要使用AlertDialog.Builder)。您可以通过覆盖onCreateView * 而不是 * onCreateDialog来完成此操作。您应该能够通过将按钮放在它们自己的片段中来获得您提到的功能。我们在我的工作中也做过类似的事情,我非常喜欢这种方法。
1.实现您自己的类型,该类型继承自Fragment,并且除了允许您需要的内容外,还以各种方式镜像DialogFragment。这不应该太可怕,因为DialogFragment只有~400,并且有大量注解。可能会很有趣。
1.使用常规的PagerAdapter而不是FragmentPagerAdapter。这样,您的DialogFragment没有视图就不会有问题。

igetnqfo

igetnqfo2#

请使用

onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)

而不是onCreateDialog(Bundle savedInstanceState)。不要创建一个警告对话框,使用方法提供的inflater,然后构建你的视图。它对我很有效。
顺祝商祺!

pvabu6sv

pvabu6sv3#

如果您实现onCreateDialog以使用AlertDialog,那么在访问getChildFragmentManager或其他等效项时,您将遇到IllegalStateException: Fragment does not have a view
要解决此问题,请同时实现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/

h6my8fg2

h6my8fg24#

感谢@汤米Visic写了一个非常好的描述,它的工作。
发布对我有用的代码。
我已经从onCreateDialog方法中删除了Dialog构建代码,事实上,我已经删除了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;
}

这种实现面临的另一个问题是:
Activity具有Toolbar/ActionBar时,则它也显示到DialogFragment中,以避免要执行的操作是:实现FragmentonViewCreated方法并添加以下代码

Dialog dialog = getDialog();
dialog.getWindow().requestFeature(Window.FEATURE_NO_TITLE);
float dimAmount = 0.6f;
dialog.getWindow().setDimAmount(dimAmount);

这将从DialogFragment中删除ToolbarActivity将按原样显示。
干杯
谢谢@汤米
问候宙斯

ux6nzvsh

ux6nzvsh5#

我遇到了同样的问题,并实现了以下解决方案:

class MyDialogFragment: DialogFragment {

  private lateinit var dialog: AlertDialog
  private lateinit var dialogView: View

  override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
    // return the view inflated for your dialog fragment
    return dialogView
  }

  // this is called before onCreateView
  override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
    dialogView = LayoutInflater
            .from(ContextThemeWrapper(requireContext(), R.style.MyAlertDialogStyle))
            .inflate(R.layout.fragment_dialog, null, false)
    dialog = AlertDialog
            .Builder(requireContext())
            .setView(dialogView)
            .create()

    dialog.setOnShowListener {
        childFragmentManager
                  .beginTransaction()
                  .replace(R.id.container, MyNestedFragmentInsideTheDialog())
                  .commit()
        // retrieve dialog buttons if any to manage onClickListener yourself
        // dialog.getButton(AlertDialog.BUTTON_POSITIVE)
    }
  }

}

其思想是自己膨胀对话框内容,并保留对它的引用,这样它就可以返回到onCreateView中,然后由childfragmentManager使用;- )

ctzwtxfj

ctzwtxfj6#

您可以将条件置于try和catch之间,

val comeFrom = try {
                args.comeFrom.toString()
            }catch (e:Exception){
                "0"
            }

相关问题