I was trying to create a TextView programatically and add it to my layout by using addView() function, but I get the runtime exception which is saying "The specified child already has a parent. You must call removeView() on the child's parent first". I've looked all the questions asked about this subject, but still couldn't understand how to and when to use removeView() function.
So here's my code:
import android.content.Intent;
import android.graphics.Color;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.DisplayMetrics;
import android.util.Log;
import android.view.View;
import android.widget.RelativeLayout;
import android.widget.RelativeLayout.LayoutParams;
import android.widget.TextView;
import java.util.Random;
public class MainActivity extends AppCompatActivity {
private int maxNumber = 6;
private Integer[] numbers = new Integer[maxNumber];
private Integer[] textSizes = new Integer[maxNumber];
private Integer[] colors = new Integer[8];
private Integer[] randomColors = new Integer[maxNumber];
private Integer[][] margins;
private LayoutParams params[];
private int maxValue = 1000;
private int maxSize = 50;
private int minSize = 15;
private int viewCount = 0;
private int startCount = 3;
private int layoutHeight;
private int layoutWidth;
private int score = 0;
private RelativeLayout layout;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
layout = (RelativeLayout) findViewById(R.id.layout);
LayoutParams layoutParams = new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT);
layout.setLayoutParams(layoutParams);
DisplayMetrics displayMetrics = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(displayMetrics);
layoutHeight = displayMetrics.heightPixels;
layoutWidth = displayMetrics.widthPixels;
String[] colorsTxt = getApplicationContext().getResources().getStringArray(R.array.colors);
for (int i = 0; i < colorsTxt.length; i++) {
int newColor = Color.parseColor(colorsTxt[i]);
colors[i] = newColor;
}
createTextView(3);
}
private void createTextView(int num)
{
final TextView tv = new TextView(this);
createProperties(num);
eliminateSameRandoms();
for(int i = viewCount; i < (viewCount + num); i++)
{
tv.setLayoutParams(params[i]);
tv.setText(String.valueOf(numbers[i]));
tv.setTextColor(randomColors[i]);
tv.setTextSize(textSizes[i]);
createListener(tv);
layout.addView(tv);
}
viewCount += num;
}
private void createListener(final TextView textView)
{
textView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (Integer.parseInt(String.valueOf(textView.getText())) == getBiggest()) {
score++;
if(viewCount == startCount * startCount) {
startCount++;
createTextView(startCount);
}
else {
createTextView(startCount);
}
} else {
Intent i = new Intent(MainActivity.this, FailActivity.class);
i.putExtra("score", score);
startActivity(i);
}
}
});
}
private int getBiggest()
{
int max = 0;
for(int i : numbers)
{
if(i > max)
{
max = i;
}
}
return max;
}
private void createProperties(int num)
{
createRandoms(num);
createColors(num);
createTextSizes(num);
createMargins(num);
createParams(num);
}
private void createRandoms(int numRandoms)
{
for(int i = viewCount; i < (viewCount + numRandoms); i++)
{
numbers[i] = new Random().nextInt(maxValue);
}
}
private void createParams(int numParams)
{
params = new LayoutParams[numParams];
for(int i = viewCount; i < (viewCount + numParams); i++)
{
params[i] = new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
params[i].leftMargin = margins[i][0];
params[i].topMargin = margins[i][1];
}
}
private void createMargins(int numMargins)
{
margins = new Integer[numMargins][2];
for(int i = viewCount; i < (viewCount + numMargins); i++)
{
margins[i][0] = new Random().nextInt(layoutWidth - 40) + 20;
margins[i][1] = new Random().nextInt(layoutHeight - 40) + 20;
}
}
private void createTextSizes(int numTextSizes)
{
for(int i = viewCount; i < (viewCount + numTextSizes); i++)
{
textSizes[i] = new Random().nextInt(maxSize - minSize) + minSize;
}
}
private void createColors(int numColors)
{
for(int i = viewCount; i < (viewCount + numColors); i++)
{
randomColors[i] = colors[new Random().nextInt(colors.length - 1)];
}
}
private boolean inRange(int position, int other)
{
int range = 60;
return !(position - other < range && other - position < range);
}
private void eliminateSameRandoms()
{
int numRandoms = viewCount;
int i = 0;
while(i < numRandoms)
{
for(int j = 0; j < numRandoms; j++)
{
Log.d("i: " , String.valueOf(i));
Log.d("j: " , String.valueOf(j));
if(j != (numRandoms - i))
{
while (numbers[j].equals(numbers[numRandoms - (i + 1)]))
{
numbers[j] = new Random().nextInt(maxValue);
}
while (randomColors[j].equals(randomColors[numRandoms - (i + 1)]))
{
randomColors[j] = colors[new Random().nextInt(colors.length)];
}
while (textSizes[j].equals(textSizes[numRandoms - (i + 1)]))
{
textSizes[j] = new Random().nextInt(maxSize - minSize) + minSize;
}
while(inRange(margins[j][0], margins[numRandoms - (i + 1)][0]))
{
margins[j][0] = new Random().nextInt(layoutWidth - 40) + 20;
}
while(inRange(margins[j][1], margins[numRandoms - (i + 1)][1]))
{
margins[j][1] = new Random().nextInt(layoutHeight - 40) + 20;
}
}
}
i++;
}
}
}
There is only a RelativeLayout in my XML layout which has the id = layout
I tried to use
((ViewGroup)tv.getParent()).removeView(tv);
before
layout.addView(tv);
at various positions in my code but none of them worked.
I've looked this and this but couldn't figure out the solution.
Where and how should I use removeView() ?