TabLayout & ViewGroup : The specified child already has a parent. You must call removeView() on the child's parent first

173 Views Asked by At

I have a tabLayout setup iwth viewpager on my MainActivity:

tabLayout.setupWithViewPager(viewPager);

The initial fragment loads without any issues. However, when clicking on one of the tab titles I get the following error: "The specified child already has a parent. You must call removeView() on the child's parent first"

here's my fragment setup:

public class ContactsList extends Fragment {

    private static MainActivity mActivity;
    private View view;
    private static Fragment thisFragment;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        mActivity = (MainActivity) getActivity();
        thisFragment= this;
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        View v= inflater.inflate(R.layout.contacts_list_recycler_view, null);
        view=v;
        RecyclerView rv  = (RecyclerView) v.findViewById(R.id.contacts_list_recyclerview);
        setupRecyclerView(rv);
        return rv;
    }

    @Override
    public void onDestroyView() {
        if (view != null) {
             ViewGroup group = (ViewGroup) view.getParent();
            group.removeAllViews();
        }
        super.onDestroyView();
    }

and the viewpager adapter on MainActivity:

static class Adapter extends FragmentPagerAdapter {
    private final List<Fragment> mFragments = new ArrayList<>();
    private final List<String> mFragmentTitles = new ArrayList<>();

    public Adapter(FragmentManager fm) {
        super(fm);
    }

    public void addFragment(Fragment fragment, String title) {
        mFragments.add(fragment);
        mFragmentTitles.add(title);
    }

    @Override
    public Fragment getItem(int position) {
        return mFragments.get(position);
    }

    @Override
    public int getCount() {
        return mFragments.size();
    }

    @Override
    public CharSequence getPageTitle(int position) {
        return mFragmentTitles.get(position);
    }
}

the Logcat has the following:

 java.lang.IllegalStateException: The specified child already has a parent. You must call removeView() on the child's parent first.
        at android.view.ViewGroup.addViewInner(ViewGroup.java:4976)
        at android.view.ViewGroup.addView(ViewGroup.java:4807)
1

There are 1 best solutions below

0
Miguel Tomás On

Well, as it turned out after 4h of bug hunting, the error is not on the code but instead on the layout XML files. when loading the fragment, initially i had:

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <androidx.recyclerview.widget.RecyclerView
        android:id="@+id/contacts_list_recyclerview"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_marginBottom="32dp"
        android:scrollbars="vertical"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent"></androidx.recyclerview.widget.RecyclerView>


</androidx.constraintlayout.widget.ConstraintLayout>

and as it seems constrainLayout is not allowed and will throw the above error. To solve it, all it was needed, was to remove the constrainLayout from the XML:

<?xml version="1.0" encoding="utf-8"?>
<androidx.recyclerview.widget.RecyclerView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/contacts_list_recyclerview"
android:scrollbars="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent" />

and everything worked as intended.