Fragmente - Das angegebene Kind hat bereits einen Elternteil. Sie müssen removeView () zuerst auf dem übergeordneten Element des Kindes aufrufen

80

Ich erhalte diesen Fehler. Ich habe viele Lösungen ausprobiert, aber ich konnte das nicht lösen. Hilf mir! Ich muss die Oberflächenansicht und die Schaltfläche mithilfe von Fragmenten zur Aktivität hinzufügen.

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
quelle
als die Ausnahme auftrat. Beim capturePic Klicken oder davor.
Papa d
wo soll ich getParent anrufen ?? @ Papa davor
Vivek
1
activity_cam
poste

Antworten:

196

Versuchen Sie zu ersetzen

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

Mit

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

oder

View v = inflater.inflate(R.layout.camera_fragment, null);
user3390963
quelle
10
Versuchen Sie zu vermeiden, Null als Elternteil zu übergeben, verwenden Sie die erste Option, die er erwähnte
Dominic Bartl
7
@sudocoder Um Ihr Warum zu beantworten?. Übergeordnet ist die Stammansicht der Hierarchie, in die Sie die anzuhängende Ressource aufblasen. LayoutInflater versucht automatisch, die aufgeblasene Ansicht an den angegebenen Stamm anzuhängen. Das Framework verfügt jedoch über eine Überprüfung, dass, wenn Sie für das Stammverzeichnis null übergeben, dieser Versuch umgangen wird, um zu verhindern, dass Ihre App abstürzt. Elternschaft ist erforderlich, um die im Stammelement des aufgeblasenen XML deklarierten LayoutParams auszuwerten. Wenn Sie hier nichts übergeben, wird dem Framework mitgeteilt, dass Sie die übergeordnete Ansicht der aufgeblasenen XML nicht kennen.
Elltz
2
nette Erklärung bignerdranch.com/blog/…
Rajesh Khadka
Vielen Dank! Du hattest meine Stunden gerettet.
Abschied
8

Diese Frage wurde bereits beantwortet, aber ich möchte dennoch den Grund für das Hinzufügen von false als dritten Parameter hinzufügen .

Die inflate () -Methode akzeptiert drei Argumente:

  • Die Ressourcen-ID des Layouts, das Sie aufblasen möchten.
  • Die ViewGroup soll das übergeordnete Element des aufgeblasenen Layouts sein. Das Übergeben des Containers ist wichtig, damit das System Layoutparameter auf die Stammansicht des aufgeblasenen Layouts anwenden kann, die in der übergeordneten Ansicht angegeben ist, in der es sich befindet.
  • Ein Boolescher Wert, der angibt, ob das aufgeblasene Layout während des Aufblasens an die ViewGroup (den zweiten Parameter) angehängt werden soll. (In diesem Fall ist dies falsch, da das System das aufgeblasene Layout bereits in den Container einfügt. Wenn Sie true übergeben, wird im endgültigen Layout eine redundante Ansichtsgruppe erstellt.)

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

Bharat Kul Ratan
quelle
7

In meinem Fall habe ich das setTransition()während der gemacht FragmentTransaction. Der folgende Code hat bei mir funktioniert:

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

        }

        ...

}

Dies passiert wahrscheinlich, wenn Sie wiederholt zwischen Fragmenten wechseln und die Ansicht aufgrund des laufenden Übergangs keine Zeit bekommt, sich wirklich vom übergeordneten Element zu lösen.

Irshu
quelle
Ja, das kann ich bestätigen. In meinem speziellen Fall haben einige meiner Fragmente eine umfangreiche und komplexe Benutzeroberfläche, z. B. das Anzeigen eines Google, MapViewund der Benutzer kann häufig zwischen solchen Fragmenten navigieren. Da das vollständige Neuerstellen ihrer Ansicht jedes Mal umständlich ist, führe ich das Zwischenspeichern von Ansichten durch (Beibehalten der Instanz der Ansicht in Fragment und Zurückgeben in onCreateView). Aufgrund von Übergangsanimationen zwischen zwei solchen Fragmenten existieren beide Ansichten kurz nebeneinander, und wenn der Benutzer schnell genug zurück navigiert, stürzt sie ab. Anrufen endViewTransitionist also die Lösung. Vielen Dank und +1 verdient.
Mackovich
Nebenbei bemerkt und seltsamerweise betrifft mein Problem derzeit ausschließlich HUAWEI-Geräte mit Android 9. Dieses Problem könnte jedoch auf einem Nexus 5 und anderen nicht verwandten Geräten reproduziert werden. Warum, ich weiß nicht ... könnte es ein Problem mit der Implementierung von Animationen geben, das für EMUI OS / Huawei geeignet ist, damit es so einfach ist, so häufig vorzukommen ?
Mackovich
Diese Antwort ist golden
coolcool1994
5

Ich verwende API 26.0.2 und in meinem Fall ereignete sich der Absturz aufgrund von benutzerdefinierten Animationen, die für meine Fragmente festgelegt wurden. Das Problem wurde behoben, indem der Aufruf zum Festlegen der benutzerdefinierten Animation auskommentiert wurde.

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

Satheesh
quelle
Dankesbündel für den Kommentar. Ich habe diesen Link geöffnet, aber Ihre Antwort verpasst. Das Debuggen dauerte 3 Tage. Ich hätte mehr Tage verbringen können, wenn ich Ihre Antwort nicht gesehen hätte.
Qadir Hussain
Haben Sie eine Möglichkeit gefunden, dies mit setCustomAnimations zum Laufen zu bringen?
Qadir Hussain
@ QadirHussain Sorry Hussain, ich habe es nicht versucht.
Satheesh
2

Ich bin auch auf dieses Problem gestoßen, und das ist meine Lösung. es ist sehr leicht

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

Ich hoffe, Ihnen nützlich zu sein

AnhSang
quelle
0

Die Angabe Idfür das übergeordnete und das untergeordnete Element, insbesondere für benutzerdefinierte Ansichten, in der xmlDatei kann das Problem lösen.

Sagte Abolfazl Fatemi
quelle
0

Nur dass du weist. Es scheint ein Problem im Android SDK zu sein.

Ich habe die gleiche Situation wie @Satheesh mit der SDK-Version: 27.0.2 und der Versuch, setCustomAnimation zu entfernen, scheint zu funktionieren. Um die setCustomAnimations zu entfernen, müssen jedoch viele Änderungen vorgenommen werden. Ich würde es vorziehen, die benutzerdefinierte Animation beizubehalten. Ich habe das SDK auf die neueste Version 27.1.1 aktualisiert. Und es funktioniert bei mir.

Pai-Hsiang Huang
quelle
0

Könnte hilfreich sein

           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
quelle
0

Ich hatte Navigation in meinem Code und dieser Fehler wurde angezeigt, als ich auf die Schaltfläche "Zurück" eines der Fragmente klickte. Es wurde gelöst, als ich in nav_graph popUpTo in verwandte Aktionen s setzte. Einige Aktionen wurden ausgeführt, aber es wurde nichts angezeigt.

MMG
quelle
-16

Versuche dies.

 ((CamActivity)getActivity()).finish();
Papa d
quelle