I need to add a number of rows to my Table layout and to each row I need to add two Image Buttons. Number of rows can be different each time I start the Activity - I look into a SQLite database and for each row in the database I need to add an Image Button. And there will be two Image Buttons in each row of Table layout. So far, I have this code:
db.open();
int count = db.getCount();
boolean newRow = true;
for (int i = 0; i < count; i++) {
if (newRow == true) {
newRow = false;
row = new TableRow(this);
row.setLayoutParams(new LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.WRAP_CONTENT));
}
ImageButton button = new ImageButton(this);
row.addView(button);
tableLayout.addView(row);
}
db.close();
TableRow row is defined above this block of code simply as variable for this Activity. My Table layout (tableLayout in code) is defined in XML code of the Activity layout:
<TableLayout
android:id="#+id/tableLayoutContacts"
android:layout_width="match_parent"
android:layout_height="wrap_content" >
</TableLayout>
The code crashes at the line
tableLayout.addView(row);
I wasnt able to resolve this. Any ideas? Thanks!!
I think the problem is different
It seems that Your code will have only one row and you are adding that row again and again to tableLayout as shown below.
tableLayout.addView(row);
This will lead to IllegalStateException at addViewInner Function of ViewGroup
try this
db.open();
int count = db.getCount();
boolean newRow = false;
for (int i = 0; i < count; i++) {
if (i % 2 == 0)
newRow = true;
if (newRow == true) {
newRow = false;
row = new TableRow(this);
row.setLayoutParams(new LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.WRAP_CONTENT));
tableLayout.addView(row);
}
ImageButton button = new ImageButton(this);
row.addView(button);
}
db.close();
Related
I am working on a screen that basically shows questions and answers in a grid format and I am putting them all into table rows dynamically. The problem I am having is that once I put in the first row (the header), the rest of the rows in the table do not show up. I first add the headers. This shows up.
protected void setupTableHeaders() {
TableRow tableRow = getNewTableRow();
tableRow.setTag(header);
TextView textView = new TextView(this);
GlobalVars.setupText(this,textView,32320); //Event
textView.setTextColor(R.color.black);
LayoutParams params = new LayoutParams(0,LayoutParams.WRAP_CONTENT,3.0f);
params.setMarginStart(50);
tableRow.addView(textView,params);
tableRow.addView(getNewDivider(),(new LayoutParams(0,LayoutParams.WRAP_CONTENT,.1f)));
Iterator it = mapQuestions.entrySet().iterator();
//first get all the answers
if (it.hasNext()) {
Map.Entry pair = (Map.Entry) it.next();
HolderQuestion holderQuestion = mapQuestions.get(pair.getKey());
//assume all answers sets for all questions on this screen are the same.
int i = 0;
for (HolderAnswer answer : holderQuestion.getListAnswers()) {
TextView textViewHeader = new TextView(this);
textViewHeader.setTextColor(R.color.black);
GlobalVars.setupText(this, textViewHeader, answer.getTextID());
tableRow.addView(textViewHeader, (new LayoutParams(0, LayoutParams.WRAP_CONTENT, .5f)));
if (i < holderQuestion.getListAnswers().size() - 1) {
tableRow.addView(getNewDivider(), (new LayoutParams(0, LayoutParams.WRAP_CONTENT, .1f)));
}
i++;
}
}
table1.addView(tableRow);
}
Then I add the questions and answers, which do not show up:
protected void setupRadioButtonAnswers() {
for (int i=0;i<holderQuestionMultis.size();i++) { //assume this is populated correctly
TableRow tableRow = getNewTableRow();
tableRow.setTag(answerRow);
TextView textView = new TextView(this);
textView.setTextColor(R.color.black);
GlobalVars.setupText(this,textView,holderQuestionMultis.get(i).getHolderQuestion().getTextID());
textView.setTag(textCell);
textView.setVisibility(View.VISIBLE);
LayoutParams params = new LayoutParams(0,LayoutParams.WRAP_CONTENT,3.0f);
params.leftMargin = 50;
tableRow.addView(textView,params);
tableRow.addView(getNewDivider(),(new LayoutParams(0,LayoutParams.WRAP_CONTENT,.1f)));
for (int j=0;j<holderQuestionMultis.get(i).getRadioButtons().size();j++) {
RadioButton radioButton = holderQuestionMultis.get(i).getRadioButtons().get(j);
radioButton.setVisibility(View.VISIBLE);
tableRow.addView(radioButton,(new LayoutParams(0,LayoutParams.WRAP_CONTENT,.5f)));
if (j< holderQuestionMultis.size()-1) {
tableRow.addView(getNewDivider(),(new LayoutParams(0,LayoutParams.WRAP_CONTENT,.1f)));
}
}
tableRow.setVisibility(View.VISIBLE);
table1.addView(tableRow);
}
}
And the two methods which get the radioButtons and table rows:
// table elements
protected TableRow getNewTableRow() {
TableRow tableRow = new TableRow(this);
TableLayout.LayoutParams tlparams = new TableLayout.LayoutParams(
TableLayout.LayoutParams.MATCH_PARENT,
TableLayout.LayoutParams.WRAP_CONTENT);
tableRow.setBackground(getResources().getDrawable(R.drawable.border_table_multi_grid));
tableRow.setLayoutParams(tlparams);
return tableRow;
}
protected RadioButton getRadioButton() {
RadioButton radioButton = new RadioButton(this);
radioButton.setBackground(getResources().getDrawable(R.drawable.radio_button_multigrid));
//radioButton.setButtonDrawable(R.color.transparent);
TableRow.LayoutParams params = new TableRow.LayoutParams(TableRow.LayoutParams.WRAP_CONTENT, TableRow.LayoutParams.WRAP_CONTENT);
radioButton.setLayoutParams(params);
return radioButton;
}
The tablelayout xml:
<TableLayout
android:id="#+id/table"
android:layout_width="match_parent"
android:layout_height="300dp"
android:orientation="horizontal"
android:layout_above="#+id/viewSpacer"
android:layout_below="#+id/lblSubQuestionText"
android:layout_marginBottom="15dp"
android:layout_marginRight="15dp"
android:layout_marginLeft="15dp"
android:layout_marginTop="15dp"
android:background="#drawable/border_table_multi_grid">
What am I missing? Is the first table header row covering up the other rows? Why do they not appear?
It turns out that this code:
tableRow.addView(getNewDivider(),(new LayoutParams(0,LayoutParams.WRAP_CONTENT,.1f)));
Was the culprit which consisted of adding a LinearLayout containing a view. Just adding the view alone solved the problem.
I have created a table dynamically from an array list
for (int i = 0; i < arrayList.size(); i++) {
TextView name = new TextView(this);
TextView time = new TextView(this);
TableRow row = new TableRow(this);
// Set event name and remaining time
name.setText(arrayList.get(i).name);
time.setText("...");
// Add text views to row
row.addView(time, layoutParams);
row.addView(name, layoutParams);
// Add row to table
tableLayout.addView(row, i);
}
Now if I want to edit or remove certain rows under a condition, I will have to access that row, but how?
outerloop:
for(int i = 0; i < arrayList.size(); i++ ) {
if(// row's time <= 0 ...) {
tableLayout.removeViewAt(i); // this doesn't seem to work properly
// it removes the wrong rows
}
else {
// ...
break outerloop;
}
}
For some reason tableLayout.removeViewAt(i); removes the incorrect row. Alternatively, I'd prefer to edit that row's name, but the principle applies, I just need to find a way to access the table row. Any way?
Create your table like this:
ArrayList<TableRow> rows = new ArrayList<>();
for (int i = 0; i < arrayList.size(); i++) {
TextView name = new TextView(this);
TextView time = new TextView(this);
TableRow row = new TableRow(this);
rows.add(row);
// Set event name and remaining time
name.setText(arrayList.get(i).name);
time.setText("...");
// Add text views to row
row.addView(time, layoutParams);
row.addView(name, layoutParams);
// Add row to table
tableLayout.addView(row, i);
}
When you want to remove a row now you can do that by it's index in the ArrayList:
row = rows.get(i);
table.removeView(row);
rows.remove(i);
When you want to remove multiple rows this could be a solution for you:
ArrayList<TableRow> removeRows = new ArrayList<>();
for(int i = 0; i < rows.size(); i++) {
if(....) {
removeRows.add(rows.get(i));
}
}
// now delete those rows
for(TableRow remove : removeRows) {
tableLayout.removeView(row);
rows.remove(remove);
}
I hope this works for you!
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.
I have created tabs and their content from a database. Now I need help figuring out how to get the user entered values from those controls - how to get a list of the controls on the tabs (so the data can be saved). Here is a condensed sample of how I'm populating the tabs contents:
public View createTabContent(String tag)
{
SQLiteDatabase db2 = openOrCreateDatabase(msDbFile, MODE_PRIVATE, null);
Cursor cList = db2.rawQuery("SELECT * FROM CheckList WHERE CatID=" + tag, null);
TableLayout tl = new TableLayout(FormChecklist.this);
tl.setBackgroundColor(new Color().WHITE);
while(cList.moveToNext())
{
/* Create a new row to be added. */
TableRow tr = new TableRow(FormChecklist.this);
tr.setLayoutParams(new LayoutParams(
LayoutParams.FILL_PARENT,
LayoutParams.WRAP_CONTENT));
/* Create the row-content. */
TextView lblQuestion = new TextView(FormChecklist.this);
lblQuestion.setText(cList.getString(2));
lblQuestion.setTag(tag);
/* Add control to row. */
tr.addView(lblQuestion);
CheckBox chkCompleted = new CheckBox(FormChecklist.this);
chkCompleted.setText("Completed");
chkCompleted.setLayoutParams(new LayoutParams(
LayoutParams.FILL_PARENT,
LayoutParams.WRAP_CONTENT));
chkCompleted.setTag(tag);
/* Add control to row. */
tr.addView(chkCompleted);
/* Add row to TableLayout. */
tl.addView(tr,new TableLayout.LayoutParams(
LayoutParams.FILL_PARENT,
LayoutParams.WRAP_CONTENT));
}
db2.close();
return tl;
}
No replies, but finally figured out, hopefully someone will find this info helpful.
Approach I took was modifying my createTabContent adding an ID for the TableLayout:
tl.setId(1000 + miTlCnt);
Then in my save routine I loop through controls like so:
for (int i = 1000 + miTlCnt; i > 1000; i--)
{
TableLayout tl = (TableLayout)findViewById(i);
if (tl != null)
{
for (int j = 0; j < tl.getChildCount(); j++)
{
TableRow row = (TableRow)tl.getChildAt(j);
CheckBox chkCompleted = (CheckBox)row.getChildAt(1);
}
}
}
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!