I'm working on a project where I have a parent LinearLayout with id=linear_parent created on activity_main.xml. Inside this parent layout, n numbers of LinearLayouts are created programmatically base on user input at EditText (id=no_of_views_input). And inside the each of these Linearlayouts, there are more child views (imageView, edit, button) created programmatically.
Suppose a user enters 4 no_of_views_input, the views heirarchy would be something like,
============
- linear_parent
- linearLayout //position 1
- imageView
- edit
- button
- linearLayout //position 2
- imageView
- edit
- button
- linearLayout //position 3
- imageView
- edit
- button
- linearLayout //position 4
- imageView
- edit
- button
- linearLayout //position 1
===========
After these layouts and views are created, I want to rearrange the LinearLayouts, base on user input from child id=edit. Suppose the user enters 1 on edit at LinearLayout position 3 , what I want is, the current LinearLayout at position 3 must be added to position 1 along with its children, and finally remove the old Linearlayout which was at position 3. (would be currently at position 4 if indexes are shifted down).
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
android:orientation="vertical">
<LinearLayout
android:id="@ id/linear_parent"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="20dp"
android:gravity="center"
android:orientation="vertical">
<!-- Views are added here programmatically -->
</LinearLayout>
<EditText
android:id="@ id/no_of_views_input"
android:layout_width="100dp"
android:layout_height="40dp"
android:hint="Number of view to add"/>
<Button
android:id="@ id/add_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Add"/>
</LinearLayout>
MainActivity.java
public class MainActivity extends AppCompatActivity {
LinearLayout linear_parent;
Button add_button;
EditText no_of_views_input;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
linear_parent = findViewById(R.id.linear_parent);
add_button= findViewById(R.id.add_button);
no_of_views_input= findViewById(R.id.no_of_views_input);
no_of_views_input.setInputType(InputType.TYPE_CLASS_NUMBER);
add_button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
if (!no_of_views_input.getText().toString().isEmpty()) {
String no_of_views_temp = no_of_views_input.getText().toString();
int no_of_views = Integer.parseInt(no_of_views_temp);
for (int i = 0; i < no_of_views; i ) {
LinearLayout linearLayout = new LinearLayout(MainActivity.this);
LinearLayout.LayoutParams lp_ll = new LinearLayout.LayoutParams(600, 1500);
lp_ll.setMargins(0, 50, 0, 0);
linearLayout.setOrientation(LinearLayout.VERTICAL);
linearLayout.setId(View.generateViewId()); // id = 1, 2, 3, 4, ...
int linearLayoutID = linearLayout.getId();
linearLayout.setLayoutParams(lp_ll);
ImageView imageView = new ImageView(MainActivity.this);
LinearLayout.LayoutParams lp_image = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, 800);
imageView.setBackgroundColor(Color.Yellow);
imageView.setLayoutParams(lp_image);
EditText edit = new EditText(MainActivity.this);
LinearLayout.LayoutParams lp_edit = new LinearLayout.LayoutParams(300, ViewGroup.LayoutParams.WRAP_CONTENT);
edit.setBackgroundColor(Color.WHITE);
edit.setInputType(InputType.TYPE_CLASS_NUMBER);
edit.setHint("move to index");
edit.setLayoutParams(lp_edit);
Button button = new Button(MainActivity.this);
LinearLayout.LayoutParams lp_button= new LinearLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
button.setBackgroundColor(Color.BLUE);
button.setText("Move");
button.setLayoutParams(lp_button);
linear_parent.addView(linearLayout);
linearLayout.addView(imageView);
linearLayout.addView(edit);
linearLayout.addView(button);
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
String indexTarget_temp = edit.getText().toString();
int indexTarget = Integer.parseInt(indexTarget_temp );
int childCount = linear_parent.getChildCount();
int currentLinearLayoutPos = linear_parent.indexOfChild(linearLayout);
try {
linear_parent.addView(linearLayout, indexTarget - 1); //adding current linearLayout to indexTarget
//error occurs this line
linear_parent.removeView(linear_parent.getChildAt(currentLinearLayoutPos 1)); //removing linearLayout at old index
}
catch(IllegalStateException e) {
e.printStackTrace();
}
}
});
}
}else {
Toast.makeText(MainActivity.this, "Enter index no", Toast.LENGTH_SHORT).show();
}
}
});
}
}
The error I'm getting is
java.lang.IllegalStateException: The specified child already has a parent. You must call removeView() on the child's parent first.
Any help would be highly appreciated.
CodePudding user response:
Try to remove the child from its parent before adding it as a subview:
try {
if (linearLayout.getParent() != null) {
// Remove child from parent
((ViewGroup) linearLayout.getParent()).removeView(linearLayout)
}
linear_parent.addView(linearLayout, indexTarget - 1);
}
catch(IllegalStateException e) {
e.printStackTrace();
}
However, consider switching to a RecyclerView
.
It would simplify your code structure.