Fragmenty - określone dziecko ma już rodzica. Najpierw musisz wywołać metodę removeView () na rodzicu dziecka

80

Otrzymuję ten błąd. Próbowałem wielu rozwiązań, ale nie udało mi się tego rozwiązać. Pomóż mi! Muszę dodać widok powierzchni i przycisk do działania za pomocą fragmentów.

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

}

Błąd:

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
źródło
kiedy wystąpił wyjątek. Po capturePic kliknięciu lub wcześniej.
maddy d
gdzie mam zadzwonić do getParent? @maddy before it
Vivek
1
opublikuj swój activity_camplik xml
maddy d

Odpowiedzi:

198

Spróbuj wymienić

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

Z

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

lub

View v = inflater.inflate(R.layout.camera_fragment, null);
user3390963
źródło
10
Staraj się nie podawać null jako rodzic, użyj pierwszej opcji, o której wspomniał
Dominika
7
@sudocoder Aby odpowiedzieć na pytanie dlaczego? Nadrzędny to widok główny hierarchii, do której zawyżasz zasób, do którego ma zostać dołączony, LayoutInflater automatycznie spróbuje dołączyć powiększony widok do podanego katalogu głównego. Jednak struktura ma sprawdzanie, że jeśli przekażesz null dla katalogu głównego, ominie tę próbę uniknięcia awarii aplikacji Ur. Parent jest niezbędny do oceny LayoutParams zadeklarowanych w głównym elemencie XML, który jest zawyżany. Przekazywanie niczego tutaj oznacza, że ​​framework nie znasz widoku nadrzędnego zawyżonego XML.
Elltz
2
ładne wyjaśnienie bignerdranch.com/blog/…
Rajesh Khadka
Dziękuję Ci! Zaoszczędziłeś mi godziny.
Pożegnanie
8

Na to pytanie już udzielono odpowiedzi, ale nadal chciałbym dodać powód dodania false jako trzeciego parametru.

Metoda inflate () przyjmuje trzy argumenty:

  • Identyfikator zasobu układu, który chcesz zawyżać.
  • ViewGroup, który ma być elementem nadrzędnym zawyżonego układu. Przekazanie kontenera jest ważne, aby system zastosował parametry układu do widoku głównego rozwiniętego układu, określonego przez widok nadrzędny, w którym się znajduje.
  • Wartość logiczna wskazująca, czy zawyżony układ powinien być dołączony do ViewGroup (drugi parametr) podczas inflacji. (W tym przypadku jest to fałsz, ponieważ system już wstawia zawyżony układ do kontenera - przekazanie wartości true spowoduje utworzenie nadmiarowej grupy widoków w ostatecznym układzie).

Źródło: http://developer.android.com/guide/components/fragments.html

Bharat Kul Ratan
źródło
7

W moim przypadku robiłem setTransition()podczas FragmentTransaction. Poniższy kod zadziałał dla mnie:

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

        }

        ...

}

Prawdopodobnie dzieje się tak, gdy wielokrotnie przełączasz się między fragmentami, że widok nie ma czasu na naprawdę oderwanie się od rodzica z powodu trwającego przejścia.

Irshu
źródło
Tak, mogę to potwierdzić. W moim konkretnym przypadku niektóre z moich fragmentów mają ciężki i złożony interfejs użytkownika, taki jak wyświetlanie Google, MapViewa użytkownik może często nawigować między takimi fragmentami. Ponieważ całkowite odtworzenie ich widoku jest uciążliwe za każdym razem, robię buforowanie widoku (zachowuję wystąpienie widoku w Fragment i zwracam go onCreateView). Jednak z powodu animacji przejścia między 2 takimi fragmentami oba widoki przez chwilę współistnieją i jeśli użytkownik wróci wystarczająco szybko, nastąpi awaria. Więc dzwonienie endViewTransitionjest rozwiązaniem. Wielkie dzięki i +1 zasłużenie.
Mackovich
Poza tym, na marginesie, i co dziwne, mój problem dotyczy obecnie wyłącznie urządzeń HUAWEI z systemem Android 9. Ale ten problem można odtworzyć na Nexusie 5 i innych niepowiązanych urządzeniach. Dlaczego, nie wiem ... czy może istnieć problem z implementacją animacji właściwy dla EMUI OS / Huawei , aby tak często się to zdarzało?
Mackovich
ta odpowiedź jest złota
coolcool1994
5

Używam API 26.0.2 iw moim przypadku nastąpiła awaria z powodu niestandardowych animacji ustawionych dla moich fragmentów. Skomentowanie wezwania do ustawienia niestandardowej animacji rozwiązało problem.

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

Satheesh
źródło
pakiet podziękowań za skomentowanie tego. Otworzyłem ten link, ale przegapiłem twoją odpowiedź. debugowanie tego zajęło 3 dni. Mógłbym spędzić więcej dni, gdyby nie twoja odpowiedź.
Qadir Hussain
czy znalazłeś sposób, aby to działało z setCustomAnimations.?
Qadir Hussain
@QadirHussain Przepraszam Hussain Nie próbowałem.
Satheesh
2

Ja też spotkałem się z tym problemem i to jest moje rozwiązanie. to jest bardzo łatwe

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

Mam nadzieję, że będę dla Ciebie przydatny

AnhSang
źródło
0

Określenie Idelementu nadrzędnego i podrzędnego, szczególnie w przypadku widoków niestandardowych, w xmlpliku może rozwiązać problem.

Sayed Abolfazl Fatemi
źródło
0

Tylko dla twojego odniesienia. Wygląda na to, że problem dotyczy zestawu SDK systemu Android.

Mam taką samą sytuację jak @Satheesh z wersją SDK: 27.0.2 i wydaje się, że próba usunięcia setCustomAnimation działa. Ale usunięcie setCustomAnimations wymaga wielu zmian, wolałbym zachować niestandardową animację. To, co zrobiłem, to uaktualnienie SDK do najnowszej wersji, która na razie jest 27.1.1. I to działa dla mnie.

Pai-Hsiang Huang
źródło
0

Może być pomocne

           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
źródło
0

Miałem nawigację w swoim kodzie i ten błąd pojawił się po kliknięciu przycisku Wstecz z jednego z fragmentów. Rozwiązano to, gdy w nav_graph umieściłem popUpTo w powiązanych działaniach . Niektóre działania zostały wykonane, ale nic się nie wyświetlało.

MMG
źródło
-16

Spróbuj tego.

 ((CamActivity)getActivity()).finish();
maddy d
źródło