viewpager example ejemplo custom activity android android-fragments android-viewpager android-dialogfragment

android - example - ViewPager en DialogFragment-IllegalStateException: Fragment no tiene una vista



fragmentpageradapter example (4)

Lo que quiero lograr

  • Desde FragmentActivity muestra un cuadro de diálogo al hacer clic en un botón de acción en la barra de acciones
  • DialogFragment : un diálogo sin título
  • TabHost : pestañas en la parte superior del cuadro de diálogo
  • ViewPager con FragmentPagerAdapter - Swipable, cuyo contenido está conectado a las pestañas
  • 2-3 Botones de diálogo (diferentes subclases del cuadro de diálogo, botones diferentes): no se supone que estén en uno de los ViewPager de ViewPager , lo que significa que los mismos botones deben permanecer en la parte inferior del ViewPager de diálogo, independientemente de lo que ViewPager Fragment the ViewPager .


El problema

IllegalStateException: Fragment does not have a view


Lo que he intentado / hecho hasta ahora

  • Usar el paquete android.support.v4 para las clases necesarias
  • Llamar a getChildFragmentManager() lugar de getSupportedFragmentManager()
  • Implementé lo que se sugiere en la publicación n.º 10 de este enlace https://code.google.com/p/android/issues/detail?id=42601 . Copio / pego el código directamente en mis dos clases de Fragment , que se supone que se muestra en DialogFragment , más la clase DialogFragment .
  • En mi DialogFragment personalizado, primero intenté reemplazar onCreateView , luego onCreateDialog y luego ambos al mismo tiempo. Todo lo cual pude ejecutar pero con resultados inesperados.
    • Solo onCreateView : no se puede llegar a AlertDialog.Builder para crear los botones necesarios, salvo que los resultados del AlertDialog.Builder de diálogo fueron excelentes.
    • Solo onCreateDialog : el mensaje de error que se muestra arriba. Todavía me imagino que este método será lo más cercano a lo que quiero lograr.
    • Tanto onCreateView como onCreateDialog : onCreateDialog el diseño del onCreateView diálogo en onCreateView y agregaron los botones de diálogo a AlertDialog.Builder en onCreateDialog . Esto mostraba el diálogo, pero los botones agregados de AlertDialog.Builder no eran AlertDialog.Builder . Además, el teclado no apareció al hacer clic en un campo EditText .


Código fuente

La mayoría viene de Tutorial para implementar el uso de TabHost en Android 2.2 + ViewPager y Fragments . El código del ActivityFragment está en cambio en un DialogFragment . Sin embargo, reemplacé su ViewPager con uno modificado del código fuente de esta respuesta https://stackoverflow.com/a/18167273/2375978 . Esto fue para ser wrap_content en altura.

El código defectuoso en mi proyecto está en el método onCreateDialog , creo.

@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; }


Stack trace LogCat log

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


También...

  • Sin éxito, he podido probar la otra posible solución mencionada en https://code.google.com/p/android/issues/detail?id=42601 , mencionada en la publicación # 2 y # 13, porque no he entendido cómo y dónde puedo usarlo en mi código (supongo que estoy en el mismo bote que la persona que escribió el número 18).

Creo que me encontré con este mismo problema y aprendí algunas cosas mirando la fuente de DialogFragment .

Parece que aunque anular onCreateDialog (...) es una forma válida de crear un cuadro de diálogo personalizado, dará como resultado que DialogFragment tenga una vista nula, tal como indica el mensaje de error. En la mayoría de los casos, esto está bien: el DialogFragment no necesita una Vista para mostrar un Diálogo, pero si desea anidar más fragmentos (como lo hace), esto no funcionará.

Teniendo en cuenta que desea interactuar con AlertDialog.Builder, realmente no hay una solución perfecta que yo pueda ver, pero tiene algunas opciones:

  1. Cree los botones en su cuadro de diálogo como parte de la Vista (sin usar AlertDialog.Builder). Para ello, anula onCreateView en lugar de onCreateDialog. Debería poder obtener la funcionalidad que menciona al colocar los botones en su propio fragmento. Hacemos algo similar en mi concierto, y prefiero este método.
  2. Implemente su propio tipo que hereda de Fragment y que refleja el DialogFragment en todos los sentidos, excepto en permitir lo que necesita. Esto no debería ser demasiado aterrador ya que DialogFragment es solo ~ 400 y está muy comentada. Podría ser divertido.
  3. Use un PagerAdapter regular en lugar de un FragmentPagerAdapter. De esta forma, no importará que su DialogFragment no tenga una Vista.

Gracias a @Tommy Visic por escribir una descripción realmente buena, funcionó.

Publicando el código que funcionó para mí.

He eliminado el código de construcción Dialog del método onCreateDialog eliminado de hecho el método onCreateDialog y la vista de diálogo que he estado implementando en la vista personalizada del cuadro de Dialog''s he incluido como una View en el método onCreateView y todas las cosas comenzaron a funcionar.

@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; }

Uno de los problemas enfrentados con esta implementación es:

Cuando una Activity tiene una Toolbar/ActionBar entonces también se muestra en el DialogFragment para evitar que lo que se debe hacer es: Implementar el método onViewCreated de Fragment y agregar el código siguiente

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

Esto eliminará la Toolbar de Toolbar del DialogFragment y la Activity se mostrará tal como está.

Aclamaciones

Gracias @Tommy

Saludos Zeus


Si implementa onCreateDialog para usar AlertDialog , se topará con IllegalStateException: Fragment does not have a view al acceder a getChildFragmentManager o algo equivalente.

Para resolver este problema, implemente tanto onCreateDialog como onCreateView , donde onCreateView devuelve la vista inflada en 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") // Error // 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/


Utilizar el

onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)

en lugar de onCreateDialog (Bundle savedInstanceState). No cree un diálogo de alerta, use el inflador proporcionado por el método y cree su vista. Esto funciona para mi.

¡Atentamente!