Dynamic TableRow in TableLayout - android

Someone could tell me why my app crash?? When I add 1 tablerow everything goes right but when i try to add more than 1 table row my app crask
public void generaLayout(){
TableLayout tabla = new TableLayout(this);
for(int i = 0; i < 2; i++){
row[i] = new TableRow(this);
tabla.addView(row[i]);
for(int j = 0; j < contador2; j++){
row[i].addView(textArray[j]);
}
}
layout.addView(tabla);
}
public void generaTextView(int i, String cad){
textArray[i] = new TextView(this);
textArray[i].setText(cad);
}
Here is the logcat
6-14 04:13:33.814: E/SurfaceFlinger(36): ro.sf.lcd_density must be defined as a build property 06-14 04:13:34.714: E/AndroidRuntime(3733): FATAL EXCEPTION: main 06-14 04:13:34.714: E/AndroidRuntime(3733): java.lang.IllegalStateException: The specified child already has a parent. You must call removeView() on the child's parent first. 06-14 04:13:34.714: E/AndroidRuntime(3733): at android.view.ViewGroup.addView(ViewGroup.java:3131)

Ok, based off that log.
I think it is because you are adding the same TextView to different rows causing "The specified child already has a parent". E.g You are adding textArray[0] To row's 0, and 1. Row 1 it would crash as that textview is already associated with row 0.
You currently have a one dimensional TextView Array. and you are using that same array for each row.
If you want to store them, you are going to have to use a 2D array.
E.g
textArray[i][j]
Your generate would have to change to
public void generaTextView(int i, int j, String cad){
textArray[i][j] = new TextView(this);
textArray[i][j].setText(cad);
}
You would also have to change this
row[i].addView(textArray[j]);
to
row[i].addView(textArray[i][j]);

Related

create multiple runtime textview in android

I have code in eclipse for create multiple TextView in multiple rows but when run the application items don't show, please help me how to fix it.
This is my code:
public void createInputBoxes(Activity gameplay, int colnums, int rownums, TableLayout.LayoutParams lparams, TableLayout puzzlelayout) {
TextView[][] puzcels = new TextView[colnums][];
puzzlelayout.removeAllViews();
for(int c=0; c<colnums; c++)
{
puzcels[c]=new TextView[rownums];
TableRow tr = new TableRow(gameplay);
tr.setLayoutParams(lparams);
for(int r=0; r<rownums; r++)
{
puzcels[c][r] = new TextView(gameplay);
puzcels[c][r].setLayoutParams( lparams);
puzcels[c][r].setId(tvid);
puzcels[c][r].setText("?");
tvid++;
puzcels[c][r].setBackgroundColor(0xffffb90f);
tr.addView(puzcels[c][r]);
}
puzzlelayout.addView(tr,lparams);
}
}
You are using TableLayout.LayoutParams params for all of your views - TableLayout, TableRow and TextView. That won't work for those last two. You need to give them params that work for them:
Dynamically filling a Table Layout with Table Rows

Adding table rows to TableLayout from code (Remove parent error)

I am trying to add my query results to a table row inside a table layout. I keep getting java.lang.IllegalStateException: The specified child already has a parent. You must call removeView() on the child's parent first. When i call:
((ViewGroup)table.getParent()).removeView(table);
I get an null pointer error. Any help on this would be great. Here`s the full code.
runOnUiThread(new Runnable() {
public void run() {
TableLayout table = (TableLayout)findViewById(R.id.resultstable);
int count = response.getPropertyCount();
System.out.println(count);
for(int i = 0; i < count; i++)
{
resultset.add(response.getProperty(i));
}
//TextView tv = new TextView(this);
for(int j = 0; j < resultset.size(); j++)
{
//if(resultset.get(j).toString() == "resFName")
//{
tv.setText(resultset.get(j).toString());
//((ViewGroup)row.getParent()).removeView(row);
row.addView(tv);
//((ViewGroup)table.getParent()).removeView(table);
table.addView(row);
//}
}
}
});
You are adding same TextView object to the row each time. In each iteration, create a new TextView and a TableRow.
for(int j = 0; j < resultset.size(); j++)
{
//if(resultset.get(j).toString() == "resFName")
//{
TextView tv = new TextView(context);
tv.setText(resultset.get(j).toString());
//((ViewGroup)row.getParent()).removeView(row);
TableRow row = new TableRow(context);
row.addView(tv);
//((ViewGroup)table.getParent()).removeView(table);
table.addView(row);
//}
}
You are adding the same view object to the parent. So, you are getting IllegalStateException.
If you seperate child views with "id" attribute, adding will be successful. You can give different ids to the child views via hashcode method.

Android Table Layout with 5x5 dimension

I'm still new in android programming, what I'm trying to do is, I want to create 5x5 dimension TableLayout. I know this can be done by using GridView BaseAdapter suing Inflate service. But for this one i try to apply using table layout. Below is the code. I create new instance of TableLayout, and new instance of Table row. On each table row, I created instance of 5 TextView. But once I open in emulator or in my phone, there is no TableRow created, it just empty blank Table Layout. Also there is no exception was thrown.
GridView navIcon = (GridView) findViewById(R.id.content);
navIcon.setAdapter(new ImageAdapter(this));
navIcon.setOnItemClickListener(new OnItemClickListener(){
#Override
public void onItemClick(AdapterView<?> parent, View v, int position,long id) {
// TODO Auto-generated method stub
if (position==0){
try{
TableLayout calgrid = (TableLayout) findViewById(R.id.gridtable);
Context ctxt = v.getContext();
TextView[] tView = new TextView[25];
calgrid = new TableLayout(ctxt);
int dip = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,(float) 1, getResources().getDisplayMetrics());
int counter=1;
TableRow[] tr = new TableRow[5];
for(int j=0;j<5;j++){
tr[j] = new TableRow(ctxt);
for(int i=0;i<5;i++){
tView[i] = new TextView(ctxt);
tView[i].setText(String.valueOf(counter));
tView[i].setTextSize(15);
counter+=1;
tView[i].setWidth(50 * dip);
tView[i].setPadding(20*dip, 0, 0, 0);
tView[i].setTextColor(Color.rgb( 100, 200, 200));
Toast.makeText(getApplicationContext(), "tView["+i+"] value " + String.valueOf(tView[i].getText()), Toast.LENGTH_SHORT).show();
tr[j].addView(tView[i], 50, 50);
}
calgrid.addView(tr[j]);
}
}catch(Exception e){
Log.e("MainActivity", "Error in activity", e);
Toast.makeText(getApplicationContext(),e.getClass().getName() + " " + e.getMessage(),Toast.LENGTH_LONG).show();
}
}
}
});
First of all, it is a mistake to do calgrid = (TableLayout) findViewById(R.id.gridtable); and then calgrid = new TableLayout(ctxt);, which basically says find this view now assign this variable to something completely different. Remove the second statement and it will load the table from xml which is what you want.
Second, I think it would be a good idea to simplify things for yourself because there is a lot going on here. Instead of doing all this work inside an onClick listener, do it in the onCreate method itself. Also, you seem to be using the Context from the GridView, which seems odd. Perhaps if you posted your xml layout file it could help explain what you are trying to do?
There is also a problem with indices in the array of TextViews, as tView[i] will only assign items up to 5 but the array contains 25 items. Try using tView[(j*5)+i] instead. I don't think this is causing your problems but just make sure you are assigning your items correctly.
Here is an example of how to do something along the lines of what you want
setContentView(R.layout.grid);
TableLayout tl = (TableLayout) findViewById(R.id.gridtable);
for (int j = 0; j < 5; j++) {
TableRow tr = new TableRow(this);
tr.setLayoutParams(new LayoutParams(LayoutParams.FILL_PARENT,
LayoutParams.WRAP_CONTENT));
for (int i = 0; i < 5; i++) {
TextView tView = new TextView(this);
tView.setText("TEXT" + String.valueOf((j * 5) + i + 1));
tView.setLayoutParams(new LayoutParams(
LayoutParams.FILL_PARENT, LayoutParams.WRAP_CONTENT));
tr.addView(tView);
}
tl.addView(tr, new TableLayout.LayoutParams(
LayoutParams.FILL_PARENT, LayoutParams.WRAP_CONTENT));
}
and grid.xml
<?xml version="1.0" encoding="utf-8"?>
<TableLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/gridtable"
android:layout_width="fill_parent"
android:layout_height="fill_parent" >
</TableLayout>
Once you get it working in the activity itself you can try to put it inside a listener attached to a GridView. Hope this helps!

Reusing a TableRow

In order to save time when a TableLayout is populated (with repetitive data), I want to reuse TableRows. However when I try to reuse them, I get the following error:
java.lang.IllegalStateException: The specified child already has a parent. You must call removeView() on the child's parent first.
I am storing the TableRows in an ArrayList. I then store the ArrayList in a Hashtable. This is how I am populating the ArrayList and Hashtable:
ArrayList<TableRow> tableRowAl = AcmSinglton.rowHash.get(this.cfr);
// if ArrayList is null, populate the ArrayList with the TableRows
if (tableRowAl == null){
NodeList nodeList = (NodeList) xpath.evaluate(this.xpath, xmlSource, XPathConstants.NODESET);
for(int i=0; i<nodeList.getLength(); i++){
TableRow tr = new TableRow(this.activity);
tr.removeAllViews();
tr.setId(i);
TextView tv = new TextView(this.activity);
Element chapElement = (Element) nodeList.item(i);
tv.setText(chapElement.getAttribute(this.attribute));
tr.addView(tv);
rowsAl.add(tr);
}
// put the ArrayList<TableRow> into the hashtable for reuse
AcmSinglton.rowHash.put(this.cfr, rowsAl);
}else{
// Resuse the TableRows
this.rowsAl.addAll(tableRowAl);
}
When I try to add the TableRow to the tableLayout, I get the error:
ArrayList<TableRow> al = new ArrayList<TableRow>();
// get the Arraylist
al = xmlloaded.getRowsAl();
for (int x=0; x < al.size(); x++){
TableRow tableRow = new TableRow(this);
tableRow = al.get(x);
View child = tableRow.getChildAt(0);
final TextView tx = (TextView)child;
// I get the error here when I try to add the TableRow
tableView.addView(tableRow);
}
Thanks for the help.
On the second piece of code, try to clean the tableView before adding the Views again. Put something like this before the for block:
tableView.removeAllViews();

Unable to select children (textview) of tableRow programmatically

I'm trying to print the value of the TextViews which are inside TableRows, using TableLayout#getChildAt(i).getChildAt(j).
When I try to log it using the above, logcat complains, saying that it's a View object and that it doesn't have the method I'm trying to use (getText()).
The only Views in the TableRows are TextViews.
// List<TextView> textViewBoxes...
private void createViews() {
...
tblLayout = new TableLayout(this);
tblRow01 = new TableRow(this);
...
for (int i = 0; i < 99; i++) {
TextView text = new TextView(this);
text.setText("Player " + i);
textViewBoxes.add(text);
}
tblRow01.addView(textViewBoxes.get(0));
...
tblLayout.addView(tblRow01);
...
// Print the contents of the first row's first TextView
Log.d(TAG, ("row1_tv1: " +
tblLayout.getChildAt(0).getChildAt(0).getText().toString));
...
}
Have you tried something like this?
TableRow row = (TableRow)tblLayout.getChildAt(0);
TextView textView = (TextView)row.getChildAt(XXX);
// blah blah textView.getText();
You can also do it in one line, but it sometimes looks ugly:
// wtf?
((TextView)((TableRow)tblLayout.getChildAt(0)).getChildAt(XXX)).getText();
Anyway... what you are doing here is casting the View to the specific type you want. You can do that without problems, since you are completely sure that each TableLayout's child is a TableRow, and you know that TableRow's children on XXX position is a TextView.

Categories

Resources