Fragmentos: el hijo especificado ya tiene un padre. Primero debe llamar a removeView () en el padre del niño

80

Recibo este error. Probé muchas soluciones pero no pude resolver esto. ¡Ayuadame! Necesito agregar la vista de superficie y el botón a la actividad usando fragmentos.

CamActivity.java:

public class CamActivity extends FragmentActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_cam);
        
        FragmentManager fm = getSupportFragmentManager();
        
        Fragment fragment = fm.findFragmentById(R.id.fragmentContainer);
        
        if(fragment == null) {
            fragment = new CamFragment();
            fm.beginTransaction()
            .add(R.id.fragmentContainer, fragment)
            .commit();
        }
    }
}

CamFragment.java:

public class CamFragment extends Fragment {

    private static final String TAG = "CamFragment";
    
    private Camera mCamera;
    private SurfaceView mSurfaceView;
    
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup parent, Bundle savedInstanceState){
    View v = inflater.inflate(R.layout.camera_fragment, parent);
    
    Button capturePic = (Button)v.findViewById(R.id.img_capture);
    capturePic.setOnClickListener(new View.OnClickListener() {
        
        @Override
        public void onClick(View v) {
            getActivity().finish();
        }
    });
    
    mSurfaceView = (SurfaceView)v.findViewById(R.id.surfaceView1);
    return v;
}

}

Error:

04-18 13:24:12.735: E/AndroidRuntime(6321): FATAL EXCEPTION: main
04-18 13:24:12.735: E/AndroidRuntime(6321): java.lang.RuntimeException: Unable to start activity ComponentInfo{com.pack.camdictionary/com.pack.camdictionary.CamActivity}: java.lang.IllegalStateException: The specified child already has a parent. You must call removeView() on the child's parent first.
04-18 13:24:12.735: E/AndroidRuntime(6321):     at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:1728)
04-18 13:24:12.735: E/AndroidRuntime(6321):     at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:1747)
04-18 13:24:12.735: E/AndroidRuntime(6321):     at android.app.ActivityThread.access$1500(ActivityThread.java:155)
04-18 13:24:12.735: E/AndroidRuntime(6321):     at android.app.ActivityThread$H.handleMessage(ActivityThread.java:993)
04-18 13:24:12.735: E/AndroidRuntime(6321):     at android.os.Handler.dispatchMessage(Handler.java:130)
04-18 13:24:12.735: E/AndroidRuntime(6321):     at android.os.Looper.loop(SourceFile:351)
04-18 13:24:12.735: E/AndroidRuntime(6321):     at android.app.ActivityThread.main(ActivityThread.java:3814)
04-18 13:24:12.735: E/AndroidRuntime(6321):     at java.lang.reflect.Method.invokeNative(Native Method)
04-18 13:24:12.735: E/AndroidRuntime(6321):     at java.lang.reflect.Method.invoke(Method.java:538)
04-18 13:24:12.735: E/AndroidRuntime(6321):     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:901)
04-18 13:24:12.735: E/AndroidRuntime(6321):     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:659)
04-18 13:24:12.735: E/AndroidRuntime(6321):     at dalvik.system.NativeStart.main(Native Method)
04-18 13:24:12.735: E/AndroidRuntime(6321): Caused by: java.lang.IllegalStateException: The specified child already has a parent. You must call removeView() on the child's parent first.
04-18 13:24:12.735: E/AndroidRuntime(6321):     at android.view.ViewGroup.addViewInner(ViewGroup.java:2007)
04-18 13:24:12.735: E/AndroidRuntime(6321):     at android.view.ViewGroup.addView(ViewGroup.java:1902)
04-18 13:24:12.735: E/AndroidRuntime(6321):     at android.view.ViewGroup.addView(ViewGroup.java:1859)
04-18 13:24:12.735: E/AndroidRuntime(6321):     at android.view.ViewGroup.addView(ViewGroup.java:1839)
04-18 13:24:12.735: E/AndroidRuntime(6321):     at android.support.v4.app.NoSaveStateFrameLayout.wrap(NoSaveStateFrameLayout.java:40)
04-18 13:24:12.735: E/AndroidRuntime(6321):     at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:931)
04-18 13:24:12.735: E/AndroidRuntime(6321):     at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1104)
04-18 13:24:12.735: E/AndroidRuntime(6321):     at android.support.v4.app.BackStackRecord.run(BackStackRecord.java:682)
04-18 13:24:12.735: E/AndroidRuntime(6321):     at android.support.v4.app.FragmentManagerImpl.execPendingActions(FragmentManager.java:1467)
04-18 13:24:12.735: E/AndroidRuntime(6321):     at android.support.v4.app.FragmentActivity.onStart(FragmentActivity.java:570)
04-18 13:24:12.735: E/AndroidRuntime(6321):     at android.app.Instrumentation.callActivityOnStart(Instrumentation.java:1166)
04-18 13:24:12.735: E/AndroidRuntime(6321):     at android.app.Activity.performStart(Activity.java:3837)
04-18 13:24:12.735: E/AndroidRuntime(6321):     at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:1701)
04-18 13:24:12.735: E/AndroidRuntime(6321):     ... 11 more
Vivek
fuente
cuando ocurrió la excepción. Al capturePic hacer clic o antes.
maddy d
¿Dónde debo llamar a getParent? @maddy before it
Vivek
1
publique su activity_camarchivo xml
maddy d

Respuestas:

198

Intenta reemplazar

View v = inflater.inflate(R.layout.camera_fragment, parent);

Con

View v = inflater.inflate(R.layout.camera_fragment, parent, false);

o

View v = inflater.inflate(R.layout.camera_fragment, null);
usuario3390963
fuente
10
Trate de evitar pasar null como padre, use la primera opción que mencionó
Dominic
7
@sudocoder Para responder tu por qué ?. Padre es la vista raíz de la jerarquía a la que está inflando el recurso para adjuntar, LayoutInflater intentará automáticamente adjuntar la vista inflada a la raíz proporcionada. Sin embargo, el marco tiene una verificación en su lugar de que si pasa nulo para la raíz, omite este intento de evitar que su aplicación se bloquee. El padre es necesario para evaluar los LayoutParams declarados en el elemento raíz del XML que se está inflando. No pasar nada aquí es decirle al marco que no conoce la vista principal del xml inflado.
Elltz
2
buena explicación bignerdranch.com/blog/…
Rajesh Khadka
¡Gracias! Habías salvado mis horas.
Despedida
8

Esta pregunta ya había sido respondida, pero aún me gustaría agregar la razón para agregar falso como tercer parámetro.

El método inflate () toma tres argumentos:

  • El ID de recurso del diseño que desea inflar.
  • ViewGroup para ser el padre del diseño inflado. Pasar el contenedor es importante para que el sistema aplique parámetros de diseño a la vista raíz del diseño inflado, especificado por la vista principal a la que se dirige.
  • Un booleano que indica si el diseño inflado debe adjuntarse al ViewGroup (el segundo parámetro) durante el inflado. (En este caso, esto es falso porque el sistema ya está insertando el diseño inflado en el contenedor; pasar verdadero crearía un grupo de vistas redundante en el diseño final).

Fuente: http://developer.android.com/guide/components/fragments.html

Bharat Kul Ratan
fuente
7

En mi caso, estaba haciendo setTransition()durante el FragmentTransaction. El siguiente código funcionó para mí:

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

        if(this::rootView.isInitialized){
            if(rootView.getParent() != null){
                (rootView.getParent() as ViewGroup).endViewTransition(rootView)
            }
            return this.rootView

        }

        ...

}

Esto probablemente sucede cuando cambia repetidamente entre fragmentos, y la vista no tiene tiempo para separarse realmente del padre debido a la transición en curso.

Irshu
fuente
Sí, puedo confirmarlo. En mi caso específico, algunos de mis fragmentos tienen una interfaz de usuario pesada y compleja, como mostrar un Google MapViewy el usuario puede navegar con frecuencia entre dichos fragmentos. Debido a que volver a crear su vista por completo es engorroso cada vez, estoy haciendo el almacenamiento en caché de la vista (conservando la instancia de la vista en Fragmento y devolviéndola onCreateView). Pero debido a las animaciones de transición entre 2 fragmentos de este tipo, ambas vistas coexisten brevemente y, si el usuario navega hacia atrás lo suficientemente rápido, se bloqueará. Entonces llamar endViewTransitiones la solución. Muchas gracias y +1 bien merecido.
Mackovich
Además, en una nota al margen y curiosamente, mi problema actualmente se refiere exclusivamente a los dispositivos HUAWEI que ejecutan Android 9. Pero este problema podría reproducirse en un Nexus 5 y otros dispositivos no relacionados. Por qué, no sé ... ¿podría haber un problema de implementación de animación propio de EMUI OS / Huawei para que sea tan fácil que suceda con tanta frecuencia?
Mackovich
esta respuesta es dorada
coolcool1994
5

Estoy usando API 26.0.2 y, en mi caso, el bloqueo se produjo debido a animaciones personalizadas configuradas para mis fragmentos. Al comentar la llamada para configurar la animación personalizada, se solucionó el problema.

fragmentTransaction.setCustomAnimations (android.R.anim.fade_in, android.R.anim.fade_out);

Satheesh
fuente
paquete de gracias por comentar esto. Abrí este enlace pero perdí tu respuesta. Tomó 3 días depurar esto. Podría haber pasado más días si no hubiera visto tu respuesta.
Qadir Hussain
¿Encontraste alguna forma de hacer que esto funcione con setCustomAnimations?
Qadir Hussain
@QadirHussain Lo siento Hussain, no lo intenté.
Sábado
2

También encontré este problema, y ​​esta es mi solución. es muy fácil

View v;

@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
    if (v == null) {
        v = inflater.inflate(R.layout.camera_fragment, container);
    } else {
        ViewGroup parent = (ViewGroup) v.getParent();
        if (parent != null) {
            parent.removeView(v);
        }
    }
    return v;
}

Espero serle útil

AnhSang
fuente
0

Especificar Idel elemento principal y secundario, especialmente para vistas personalizadas, en el xmlarchivo puede resolver el problema.

Sayed Abolfazl Fatemi
fuente
0

Solo para su referencia. Parece ser un problema en el SDK de Android.

Tengo la misma situación que tuvo @Satheesh con la versión del SDK: 27.0.2 e intentar eliminar el setCustomAnimation parece que funciona. Pero para eliminar el setCustomAnimations requiere muchos cambios para mí, preferiría mantener la animación personalizada. Lo que he hecho es actualizar el SDK a la última versión, que es 27.1.1 por ahora. Y funciona para mi.

Pai-Hsiang Huang
fuente
0

Podría ser útil

           View customView1;
           inflater= (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE);
           customView1= inflater.inflate(R.layout.edit_custom_alert_window, null);     
           try {
                if(customView2.getParent()!=null)
                    ((ViewGroup)customView2.getParent()).removeView(customView2);
            }catch (Exception e){

            }
Muhaiminur Rahman
fuente
0

Tenía navegación en mi código y este error se mostró cuando hice clic en el botón Atrás de uno de los fragmentos. Se resolvió cuando en nav_graph puse popUpTo en acciones relacionadas . Se realizaron algunas acciones, pero no apareció nada.

MMG
fuente
-16

prueba esto.

 ((CamActivity)getActivity()).finish();
maddy d
fuente