web-dev-qa-db-ja.com

DialogFragmentのViewPager-IllegalStateException:フラグメントにビューがありません

達成したいこと

  • FragmentActivityから、アクションバーのアクションボタンをクリックしたときにダイアログを表示する
  • DialogFragment-タイトルのないダイアログ
  • TabHost-ダイアログ上部のタブ
  • ViewPagerFragmentPagerAdapter-Swipable、タブに接続されているコンテンツ
  • 2-3ダイアログボタン(ダイアログの異なるサブクラス、異なるボタン)-ViewPagerFragmentの1つに配置することは想定されていません。つまり、FragmentViewPagerの表示に関係なく、同じボタンがダイアログの下部に残る必要があります。


問題

_IllegalStateException: Fragment does not have a view
_


これまでに試した/行ったこと

  • 必要なクラスに_Android.support.v4_パッケージを使用する
  • getChildFragmentManager()の代わりにgetSupportedFragmentManager()を呼び出す
  • このリンクから提案された投稿#10を実装しましたhttps://code.google.com/p/Android/issues/detail?id=42601Fragmentが表示していると思われる2つのViewPagerクラスと、DialogFragmentクラスにコードを直接コピー/貼り付けます。
  • 私のカスタムDialogFragmentでは、最初にonCreateViewをオーバーライドし、次にonCreateDialogをオーバーライドしてから、両方を同時にオーバーライドしようとしました。これらすべてを実行する必要がありましたが、予期しない結果が発生しました。
    • onCreateViewのみ:_AlertDialog.Builder_に到達できず、必要なボタンを作成できません。
    • onCreateDialogのみ:上記のエラーメッセージ。私は、この方法が自分が達成したいものに近づいたのと同じくらい近いとまだ想像しています。
    • onCreateViewonCreateDialogの両方:onCreateViewのダイアログレイアウトを拡張し、onCreateDialogの_AlertDialog.Builder_にダイアログボタンを追加しました。これによりダイアログが表示されましたが、_AlertDialog.Builder_から追加されたボタンは表示されませんでした。さらに、EditTextフィールドをクリックしてもキーボードが表示されませんでした。


ソースコード

ほとんどはから来ていますAndroid 2.2 + ViewPager and FragmentsActivityFragmentのコードは、代わりにDialogFragmentにあります。ただし、ViewPagerを、この回答のソースコードからの変更されたものに置き換えましたhttps://stackoverflow.com/a/18167273/2375978。これは、高さを_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
_


また...

  • https://code.google.com/p/Android/issues/detail?id=42601 に記載されている他の可能な解決策を試すことができませんでした。 #2と#13、コードでコードをどこでどのように使用できるのか理解していないため(#18を書いた人と同じ船に乗っていると思います)。
30
Henrik Wassdahl

私はこれと同じ問題に遭遇し、 DialogFragment のソースを見ていくつかのことを学んだと思います。

OnCreateDialog(...)のオーバーライドはカスタムダイアログを作成する有効な方法ですが、エラーメッセージが示すように、DialogFragmentのビューがnullになるように見えます。ほとんどの場合これで問題ありません-DialogFragmentはダイアログを表示するためにビューを必要としませんが、フラグメントをさらにネストしたい場合(そうするように)、これは飛ばないでしょう。

AlertDialog.Builderとやり取りしたいと考えると、私が見ることができる完全なソリューションは実際にはありませんが、いくつかのオプションがあります。

  1. ダイアログのボタンをビューの一部として作成します(AlertDialog.Builderは使用しません)。これを行うには、onCreateDialogのonCreateViewinsteadをオーバーライドします。ボタンを独自のフラグメントに配置することで、言及した機能を取得できるはずです。私たちのライブでも似たようなことをしていますが、私はこの方法を非常に好みます。
  2. Fragmentから継承し、必要なものを許可することを除いて、あらゆる方法でDialogFragmentを反映する独自の型を実装します。 DialogFragmentはたったの〜400で、非常にコメントされているので、これはそれほど怖いものではありません。楽しいかもしれません。
  3. FragmentPagerAdapterの代わりに通常のPagerAdapterを使用してください。この方法では、DialogFragmentにビューがないことは問題になりません。
36
Tommy Visic

使用

onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)

onCreateDialog(Bundle savedInstanceState)の代わりに。警告ダイアログを作成せず、メソッドが提供するインフレーターを使用して、ビューを構築します。わたしにはできる。

宜しくお願いします!

20
Skycorsarius

それが機能した本当に良い説明を書いてくれた@Tommy Visicに感謝します。

私のために働いたコードを投稿する。

Dialogビルドコードを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;
}

この実装でもう1つ問題が発生しました。

ActivityToolbar/ActionBarが含まれている場合は、DialogFragmentにも表示され、実行されることを回避できます。onViewCreatedメソッドを実装してFragmentとコードの下に追加

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

これにより、ToolbarDialogFragmentから削除され、Activityがそのまま表示されます。

乾杯

ありがとう@Tommy

ゼウスよろしく

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/

1
Desmond Lua