Search code examples
javaandroidandroid-fragmentsandroid-linearlayoutlayout-inflater

How do I inflate a view/container multiple times by button click inside a Fragment?


This is my very first post on StackOverflow. This site has been a lifesaver, so far.

I am pretty new to this and so far I have been able to resolve my problems, but I am stuck on this issue right here.

I am working inside a fragment (which I'm new to). I'm trying to inflate (which I don't know much about it) an existing container inside this fragment, with a view. I hope I'm explaining this correctly.

Context: I am trying to get some measurements (and other variables) from the user to calculate wall areas, lengths, etc. The User shall be able to "Add Walls" through a Button Click; which should just inflate from an existing layout.

I have tried moving the code in different life cycles (onCreate vs onCreatedView etc.). I have also tried passing different paramenters in my LayoutInflator (parent view, setting attachToRoot as false, true, etc.)

CalculatorActivity.java

    public class CalculatorActivity extends AppCompatActivity {

      //...

      private FragmentNewCalc fragmentNewCalc;    

      @Override
      protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_calculator);
        fragmentNewCalc = new FragmentNewCalc();
        //Replace Containers
        getSupportFragmentManager().beginTransaction()
          .replace(R.id.container_wrap, fragmentNewCalc)
          .commit();
    }
}

This inflates in this XML ->

<FrameLayout
    android:id="@+id/container_wrap"
    android:layout_width="match_parent"
    android:layout_height="match_parent" />

FragmentNewCalc.java


      LinearLayout wallContainer;
      LinearLayout test; //testing with LinearLayout
      CardView newWallCard; //this is what I want to use though


      @Nullable
      @Override
      public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        View v = inflater.inflate(R.layout.frag_new_calc, container, false);

        wallContainer = (LinearLayout) v.findViewById(R.id.new_wall_container);
         //LayoutInflater inflater2; //testing
        //inflater2 = getLayoutInflater();
        //newWallCard = (CardView) inflater.inflate(R.layout.frag_new_walls, container, false);
        test = (LinearLayout) inflater.inflate(R.layout.wall_add_section, null); //tested this wallContainer as parent view and true/false   

        fab_add_wall = (FloatingActionButton) v.findViewById(R.id.fab_add_wall);


        fab_add_wall.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                wallContainer.addView(test);


            }
        });


        return v;
    }
}

This is where the inflation should occur: (part of a bigger layout with CoordinatorLayout, Scrollview, etc.)

    <LinearLayout
        android:id="@+id/new_wall_container"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="vertical">

The first time I click the button, the user interface successfully adds the inflated layout (works as intended), but upon consecutive clicks, I get the error:

java.lang.IllegalStateException: The specified child already has a parent. You must call removeView() on the child's parent first.

Of course I don't want to remove that view, but want to keep adding to it. scratches head

I had this working before I started changing everything to Fragments. So that tells me, that is probably has to do with the fact, that I'm inside a fragment now.

I have spent all day trying to figure this one out. I am not sure if my logic is flawed, because I just started working with Fragments or if it is my lack of understanding of the LayoutInflator. Probably both. O:-)


Solution

  • Inside your onClick, please inflate the view

    public void onClick(View v) { 
    
        inflater.inflate(R.layout.wall_add_section, wallContainer, true);
    }