skip to Main Content

I am working on android studio. I have created some fragments and they are smoothly working. The app would be collecting data from users for order booking. Now, I have a button and on this button click, I am calling another layout to enter the products. The data is selected from the json file. Below is my code

Fragment

Button addProduct;
private LinearLayout mLinearLayout;
public View layout2;
public View view = null;

public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {

   if (view == null) {
        view = inflater.inflate(R.layout.new_survey_form_layout, container, false); // my main layout
        mLinearLayout = view.findViewById(R.id.ll_prod);// the layout in which I want to call my below layout
        layout2 = inflater.inflate(R.layout.product_layout, mLinearLayout, false);// product layout


        this.initElements(view);// all of my fields against my new_survey_layout_form_layout
        this.initElementsPrd(layout2); // the fields of my second layout
    }
}

 private void initElementsPrd(View view) {
    productAuto = (AutoCompleteTextView) view.findViewById(R.id.tv_product);
    qtyEditText = (EditText) view.findViewById(R.id.prod_qty);
    prodPriceEditText = (EditText)view.findViewById(R.id.prod_price);
    prodSpecsEditText = (EditText)view.findViewById(R.id.prod_specs);
    setProd();// to set the adapters for selecting the product name
}
 private void setProd()
{
    Log.d("Ali", "sub div");
    if (prodArrayList == null) {
        prodArrayList = new ArrayList<String>();
        Log.d("Ali", "prod new");
    } else {
        prodArrayList.clear();
        Log.d("Ali", "prod clear");
    }

    if (isNewSurvey) {
        prodArrayList.addAll(new ProductManager(getActivity()).getAvailableProducts());
        Log.d("Ali", "prod is new booking");
    } else {
        prodArrayList.addAll(new ProductManager(getActivity()).getProducts());
        Log.d("Ali", "sub div edit survey");
    }
    if (prodAdapter == null) {
        Log.d("Ali", "sub div new adapter");
        prodAdapter = new ArrayAdapter<String>(getActivity(), android.R.layout.simple_spinner_dropdown_item, prodArrayList);
        productAuto.setAdapter(prodAdapter);
    } else {
        Log.d("Ali", "sub div notify");
        prodAdapter.notifyDataSetChanged();
    }
}

        addProduct.setOnClickListener(v -> {


        addLayout();

    });

Now when I click the add button for the first time it does show the layout of the product but when I click on the same button for the second time the app crashes. Below is the working

enter image description here

Error Message

The specified child already has a parent. You must call removeView() on the child’s parent first.

Solution Tried

Inside add layout function I have done the following

 private void addLayout(){
    layout2 = LayoutInflater.from(mContext).inflate(R.layout.product_layout, mLinearLayout, false);
    productAuto = (AutoCompleteTextView) view.findViewById(R.id.tv_product);
    qtyEditText = (EditText) view.findViewById(R.id.prod_qty);
    prodPriceEditText = (EditText)view.findViewById(R.id.prod_price);
    prodSpecsEditText = (EditText)view.findViewById(R.id.prod_specs);

 }

The product form is shown every time when I click on the Add new Product button. But I can’t select a product in this case.

Update 1

I have taken addProduct button in this.initElements(view);

private void initElements(View view) {

    newSurveyScrollview = (ScrollView) view.findViewById(R.id.new_survey_scrollview);
 refNofield1 = (EditText) view.findViewById(R.id.ref_no_field_1);
    consumerNameEditText = (EditText) view.findViewById(R.id.consumer_name);
    consumerAddressEditText = (EditText) view.findViewById(R.id.consumer_address);
    latitudeEditText = (EditText) view.findViewById(R.id.latitude);
    longitudeEditText = (EditText) view.findViewById(R.id.longitude);
    placeEditText = (EditText) view.findViewById(R.id.place);
    subDivisionSpinner = (Spinner) view.findViewById(R.id.sub_division_spinner);
cameraButton = (Button) view.findViewById(R.id.open_camera);
    saveButton = (Button) view.findViewById(R.id.save_survey_form);
    resetButton = (Button) view.findViewById(R.id.survey_reset);
    getRefNoButton = (Button) view.findViewById(R.id.get_ref_no_button);
    getLatLangButton = (ImageButton) view.findViewById(R.id.get_lat_lang_button);
    addProduct = (Button)view.findViewById(R.id.btn_prd);

}

Error Log

Process: com.example.thumbsol.accuratesurvey, PID: 6854
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:5038)
    at android.view.ViewGroup.addView(ViewGroup.java:4869)
    at android.view.ViewGroup.addView(ViewGroup.java:4809)
    at android.view.ViewGroup.addView(ViewGroup.java:4782)
    at com.example.thumbsol.accuratesurvey.fragments.SurveyFormFragment.addLayout(SurveyFormFragment.java:1904)
    at com.example.thumbsol.accuratesurvey.fragments.SurveyFormFragment.lambda$initListeners$1$com-example-thumbsol-accuratesurvey-fragments-SurveyFormFragment(SurveyFormFragment.java:550)
    at com.example.thumbsol.accuratesurvey.fragments.SurveyFormFragment$$ExternalSyntheticLambda3.onClick(Unknown Source:2)
    at android.view.View.performClick(View.java:6608)
    at android.view.View.performClickInternal(View.java:6585)
    at android.view.View.access$3100(View.java:785)
    at android.view.View$PerformClick.run(View.java:25921)
    at android.os.Handler.handleCallback(Handler.java:873)
    at android.os.Handler.dispatchMessage(Handler.java:99)
    at android.os.Looper.loop(Looper.java:201)
    at android.app.ActivityThread.main(ActivityThread.java:6810)
    at java.lang.reflect.Method.invoke(Native Method)
    at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:547)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:873)

The error comes at below part

 private void addLayout() {

    mLinearLayout.addView(layout2);
}

Update 2

I have removed the second layout part from onCreatView and done the following

private void addLayout() {
   layout2 = LayoutInflater.from(mContext).inflate(R.layout.product_layout, mLinearLayout, false);
    this.initElementsPrd(layout2);
    mLinearLayout.addView(layout2);
}

Below is what I am getting now

enter image description here

The autocomplete is working for the 1st one but for the second or 3rd upto N its not working.

Any help would be highly appreciated.

2

Answers


  1. Chosen as BEST ANSWER

    Following the Gowtham K K answer I have done the following changes in my code

    private void addLayout() {
        layout2 = LayoutInflater.from(mContext).inflate(R.layout.product_layout, mLinearLayout, false);
        productAuto = (AutoCompleteTextView) layout2.findViewById(R.id.tv_product);
        qtyEditText = (EditText) layout2.findViewById(R.id.prod_qty);
        prodPriceEditText = (EditText)layout2.findViewById(R.id.prod_price);
        prodSpecsEditText = (EditText)layout2.findViewById(R.id.prod_specs);
        removeProduct = (Button)layout2.findViewById(R.id.btn_rmv);
       
        setProd();
        
    }
    

    Then in my setProd() function

     prodArrayList = new ArrayList<String>();
        if (isNewSurvey) {
            prodArrayList.addAll(new ProductManager(getActivity()).getAvailableProducts());
            Log.d("Ali", "prod is new booking");
        } else {
            prodArrayList.addAll(new ProductManager(getActivity()).getProducts());
            Log.d("Ali", "sub div edit survey");
        }
        prodAdapter = new ArrayAdapter<String>(getActivity(), android.R.layout.simple_spinner_dropdown_item, prodArrayList);
        productAuto.setAdapter(prodAdapter);
    

    Implementing the above solution my program is working now


  2. You are adding a layout by calling this method. But autocomplete textview will not work for the newly added layout because you haven’t set the adapter to newly added Layout.
    You need to call setProd() in addLayout() to bind adapter to autocomplete text view when new layout is added.

     private void addLayout(){
        layout2 = LayoutInflater.from(mContext).inflate(R.layout.product_layout, mLinearLayout, false);
        productAuto = (AutoCompleteTextView) view.findViewById(R.id.tv_product);
        qtyEditText = (EditText) view.findViewById(R.id.prod_qty);
        prodPriceEditText = (EditText)view.findViewById(R.id.prod_price);
        prodSpecsEditText = (EditText)view.findViewById(R.id.prod_specs);
        setProd();
     }
    

    Note: For handling dynamic layouts it would be better to handle view object in a list and handle instead of reinstantiating every time to existing object.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search