I have a function who gets a list of products from a webpage, and I want to add a row in a tableLayout for each element of the list.
public void getProductsOfCategory() throws IOException{
new Thread(){
public void run(){
//background code...
try {
Bundle extras = getIntent().getExtras();
String categoryName = extras.getString("categoryName");
HttpGet httpget = new HttpGet("http://romal.hopto.org/foodadvisor/users/getProductsOfCategory.json?category="+categoryName);
HttpResponse httpresp = httpClient.execute(httpget);
ByteArrayOutputStream baos = new ByteArrayOutputStream();
httpresp.getEntity().writeTo(baos);
final String content = new String(baos.toByteArray());
CategoryActivity.this.runOnUiThread(new Runnable(){
public void run(){
//foreground code (UI)
//update user interface, for example, showing messages
try {
JSONObject jObject = new JSONObject(content);
JSONArray productsList = jObject.getJSONArray("response");
for(int i=0; i<productsList.length();i++){
JSONObject product = productsList.getJSONObject(i);
JSONObject productData = product.getJSONObject("Product");
String productDescription = productData.getString("description");
}
} catch (JSONException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
});
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}.start();
}
In my layout xml file I have defined the table layout like this:
<TableLayout
android:id="#+id/tableOfProducts"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<TextView
android:id="#+id/productDescription"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="TextView"
android:paddingBottom="7dp"
android:paddingLeft="14dp"
android:paddingRight="14dp"
android:paddingTop="7dp"
android:textSize="20dp" />
</TableLayout>
I imagine I have to add some extra code in the for loop, adding a new row and a new textview for each element, and setting the content of the text view with the string that has the description of the product.
How can I do this?
Check this out, this is the general way of creating table rows dynamically. Modify it accordingly
XML file
<TableLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/main_table"
android:layout_height="wrap_content"
android:layout_width="match_parent">
</TableLayout>
JAVA PART
TableLayout t1;
TableLayout tl = (TableLayout) findViewById(R.id.main_table);
Create table row header to hold the column headings
TableRow tr_head = new TableRow(this);
tr_head.setId(10);
tr_head.setBackgroundColor(Color.GRAY); // part1
tr_head.setLayoutParams(new LayoutParams(
LayoutParams.MATCH_PARENT,
LayoutParams.WRAP_CONTENT));
I'm adding two data sections to the table row
TextView label_hello = new TextView(this);
label_hello.setId(20);
label_hello.setText("HELLO");
label_hello.setTextColor(Color.WHITE); // part2
label_hello.setPadding(5, 5, 5, 5);
tr_head.addView(label_hello);// add the column to the table row here
TextView label_android = new TextView(this); // part3
label_android.setId(21);// define id that must be unique
label_android.setText("ANDROID..!!"); // set the text for the header
label_android.setTextColor(Color.WHITE); // set the color
label_android.setPadding(5, 5, 5, 5); // set the padding (if required)
tr_head.addView(label_android); // add the column to the table row here
After adding the columns to the table row its time to add the table row the the main table layout that we fetched at the start
tl.addView(tr_head, new TableLayout.LayoutParams(
LayoutParams.FILL_PARENT, //part4
LayoutParams.MATCH_CONTENT));
EDIT : YOU CAN DO THE FOLLOWING IN YOUR CODE
TextView[] textArray = new TextView[productsList.length()];
TableRow[] tr_head = new TableRow[productsList.length()];
for(int i=0; i<productsList.length();i++){
JSONObject product = productsList.getJSONObject(i);
JSONObject productData = product.getJSONObject("Product");
String productDescription = productData.getString("description");
//Create the tablerows
tr_head[i] = new TableRow(this);
tr_head[i].setId(i+1);
tr_head[i].setBackgroundColor(Color.GRAY);
tr_head[i].setLayoutParams(new LayoutParams(
LayoutParams.MATCH_PARENT,
LayoutParams.WRAP_CONTENT));
// Here create the TextView dynamically
textArray[i] = new TextView(this);
textArray[i].setId(i+111);
textArray[i].setText(productDescription);
textArray[i].setTextColor(Color.WHITE);
textArray[i].setPadding(5, 5, 5, 5);
tr_head[i].addView(textArray[i]);
// Add each table row to table layout
tl.addView(tr_head[i], new TableLayout.LayoutParams(
LayoutParams.MATCH_PARENT,
LayoutParams.WRAP_CONTENT));
} // end of for loop
Creating the TextView and TableRow array are not necessary. You can just include part1, part2, part3 (if you need more than 1 field) and part4 inside your for loop.
Look, i think you have to modify your xml to adding rows to your tableview:
First, the inflater:
LayoutInflater inflater = mContext.getLayoutInflater();
or in this way:
LayoutInflater inflater = (LayoutInflater) this.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
//Here you can set up the layoutparameters from your tableview and the rowview.
//Maybe you don't have to modify nothing from the parameters of your tableview so
//you can dismiss it.
TableLayout.LayoutParams tableParams = new TableLayout.LayoutParams(TableLayout.LayoutParams.WRAP_CONTENT, TableLayout.LayoutParams.WRAP_CONTENT);
TableRow.LayoutParams rowParams = new TableRow.LayoutParams(TableRow.LayoutParams.WRAP_CONTENT, TableRow.LayoutParams.WRAP_CONTENT);
//Here were we take the tablelayout from your xml
TableLayout tableLayout = (TableLayout)inflater.inflate(R.layout.tableOfProducts, null);
//Like a told you before, maybe you don't need set the parameters of the tablelayout
//so you can comment next line.
tableLayout.setLayoutParams(this.tableParams);
TableRow tableRow = new TableRow(context);
tableRow.setLayoutParams(this.tableParams);
//Here you have to create and modify the new textview.
TextView textView = new TextView(context);
textView.setLayoutParams(this.rowParams);
tableRow.addView(textView);
tableLayout.addView(tableRow);
If you need more help, tell me, if it is helpful, rating me!!! ;) Un saludo Gallega! O como se dice en gallego: una aperta!
for this, you have to create one xml file for row, then you have to modify your layout.xml file like
<ScrollView>
<LinearLayout orientation=vertical id="+id/rowHolder">
</LinearLayout
</scrollview>
Then in for loop, inflate the row layout and add it runtime to rowHolder object.
I'm new myself to Android, and after years with Python/Gtk, I'm lost if I can't think in terms of Model/View/Presenter.
one useful approach I managed to apply, it puts me back into that optics, and even if it's not relative to a Table, I'm quite sure it can be extended to that (I guess this page would be a good start, for me too).
start by declaring the two objects in your fragment (or activity):
List<String> stringList; // think of it as the model.
ArrayAdapter<String> listAdapter; // and this would be the presenter
define the model in the fragment constructor:
stringList = new ArrayList<>();
next, when the onCreateView of my fragment is invoked, I do this (edit correspondingly if you're using Activity, not Fragment):
View rootView = inflater.inflate(R.layout.fragment_taxonomy, container, false);
ListView mainListView = rootView.findViewById(R.id.taxonomy_results);
// Create ArrayAdapter using the string list. think of it as the presenter.
// see how it's being handled a model and a view.
listAdapter = new ArrayAdapter<>(
rootView.getContext(), R.layout.textrow, stringList);
// Set the ArrayAdapter as the ListView's adapter.
mainListView.setAdapter( listAdapter );
textrow.xml is an extra layout which is being reused every time I add an element to the stringList model.
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/rowTextView"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:padding="10dp"
android:textSize="16sp" >
</TextView>
in the rest of the code, I only "talk" to listAdapter, and I only need its two add and clear methods, to add elements, or for clearing the list.
There are many ways to do this. First, for minimizing your code, create an XML file that initializes the TableRow and its attribute (TextView should be also included). Then, in your target XML file that is linked to the activity, you have to create only the TableLayout.
In the main, create LayoutInflater that will link the items to gather. Then, create as much as you can of the number of TableRow. In the end, each TableRow that has a unique variable should be linked using addView() to the TableLayout that you have created in the XML.
For more, see here. https://github.com/AreejTurky/Dynamic-TableRow-Generation
My android app requires me to create some LinearLayouts according to data i got through the run time, so i don't know it's number and I have to put it into a for loop to create it, and as a result the name assigned to the layouts or the elements inside it will be overridden with each iterate through the for loop, and that's my code:
List<LinearLayout> inner_ver = new ArrayList<LinearLayout>();
for(int i = 0 ; i < size_from_run_time ; i++){
LinearLayout temp_inner_ver = new LinearLayout(this);
temp_inner_ver.setLayoutParams(temp_lay);
temp_inner_ver.setOrientation(LinearLayout.VERTICAL);
temp_inner_ver.setWeightSum(2);
temp_inner_ver.setPadding(7, 7, 7, 7);
inner_ver.add(temp_inner_ver);
}
for(int j = 0 ; j < inner_ver.size() ; j++){
LinearLayout icon1 = new LinearLayout(this);
inner_ver.get(j).addView(icon1);
icon1.setLayoutParams(lp_icon);
icon1.setBackgroundResource(R.drawable.ac_overlay);
icon1.setOrientation(LinearLayout.HORIZONTAL);
icon1.setTag(NORMAL);
// icon1
TextView text1 = new TextView(this);
icon1.addView(text1);
text1.setLayoutParams(text_name);
text1.setText("something");
text1.setTextSize(12);
text1.setTextColor(Color.WHITE);
ImageButton rgp1 = new ImageButton(this);
icon1.addView(rgp1);
rgp1.setLayoutParams(lp_ineer_ver);
rgp1.setImageResource(R.drawable.grp);
rgp1.setBackgroundColor(Color.TRANSPARENT);
Button rgp_value1 = new Button(this);
icon1.addView(rgp_value1);
rgp_value1.setLayoutParams(lp_ineer_ver);
rgp_value1.setText("something");
rgp_value1.setTextSize(12);
rgp_value1.setBackgroundColor(Color.TRANSPARENT);
rgp_value1.setTextColor(Color.WHITE);
ImageButton cool1 = new ImageButton(this);
icon1.addView(cool1);
cool1.setLayoutParams(lp_ineer_ver);
cool1.setImageResource(Color.TRANSPARENT);
cool1.setBackgroundColor(Color.TRANSPARENT);
TextView cool_value1 = new TextView(this);
icon1.addView(cool_value1);
cool_value1.setLayoutParams(text_cool);
cool_value1.setText("something");
cool_value1.setTextSize(12);
ver_rooms.addView(inner_ver.get(j)); // ver_rooms is a LinearLayout defined through the xml
}
So, what if i want to add an OnClickListener for the created items (e.g rgb1, rgb_value1, cool1), as I may have like 10 of inner_ver and all of them for sure contains all of these elements with the same name.
You would probably create an array or ArrayList of 10 inner_ver.Here I have assumed, innerVerList is an Array that holds List of LinearLayout.
for (LinearLayout l: list){
for(int i=0; i<l.getChildCount(); ++i){
l.getChildAt(i).addOnClickListner(/*name of onClick listener here*/ );
}
}
But I still don't get when will you need so many LinearLayouts. Though I hope it helps!
Happy coding!
I want to add a LinearLayout wrapped around a TextView and Button programmatically. I want it to take a String array and then using the length of the string array, add that many TextViews each with their own button.
So first:
String [] s = { .... the values ....}
int sL = s.length;
TextView t1 = new TextView (this);
// then somehow create t2, t3... etc. matching the length of the String array.
Is this the best way to do this or is there another way to do this? For some context, it's a quiz app and I've created a list of categories inside resources as values and I'm trying to programmatically get my app to create as many TextViews as there are categories then set each TextView to each category then get each button to take the user to that category of questions.
You are starting it right, just do a for loop and add textviews to your linearlayout.
// You linearlayout in which you want your textview
LinearLayout linearLayout = (LinearLayout) findViewById(R.id.mylayout);
linearLayout.setBackgroundColor(Color.TRANSPARENT);
String [] s = { .... the values ....}
int sL = s.length;
TextView textView = null;
// For later use if you'd like
ArrayList<TextView> tViews = new ArrayList<TextView>();
for (int i = 0; i < sL; i++)
{
textView = new TextView(this);
textView.setText(s[i]);
linearLayout.addView(textView);
tViews.add(textView);
}
There is nothing wrong with this way of doing it. If you want to use these textview later on (set text for them or something) store them in an Array of some kind. Edited code
You can do the following:
for(int i=0;i<s.length;i++){
TextView t=new TextView(this);
t.setText(s[i]);
yourLinearLayout.addView(t);
}
But I really think that using a ListView would be better for performance ;)
Well i made an activity where i am creating some TextViews based on the size of a string array! But despite the fact that my string array has 4 items on it, which i tested it with debugging, the textviews that are created is only 1. If anyone has an idea about it please tell me :)
setContentView(R.layout.program);
String[] daily_lessons = getResources().getStringArray(R.array.firstGradeLessons);
final TextView[] tv = new TextView[daily_lessons.length];
final LinearLayout layout = (LinearLayout) findViewById(R.id.linear1);
fasa = (TextView) findViewById(R.id.textView1);
fasa.setText(String.valueOf(daily_lessons.length));
for (int i=0; i<daily_lessons.length; i++){
tv[i] = new TextView(this);
tv[i].setText(daily_lessons[i]);
tv[i].setTextSize(20);
tv[i].setLayoutParams(new LinearLayout.LayoutParams((int)LayoutParams.FILL_PARENT,(int) LayoutParams.WRAP_CONTENT));
tv[i].setGravity(Gravity.CENTER);
layout.addView(tv[i]);
}
If you still need an answer to this question here is what I would do.
setContentView(R.layout.program);
String[] daily_lessons = getResources().getStringArray(R.array.firstGradeLessons);
LinearLayout layout = (LinearLayout) findViewById(R.id.linear1);
fasa = (TextView) findViewById(R.id.textView1);
fasa.setText(String.valueOf(daily_lessons.length));
TextView tmpView = null;
for (int i=0; i<daily_lessons.length; i++){
tmpView = new TextView(this);
tmpView.setText(daily_lessons[i]);
tmpView.setTextSize(20);
layout.addView(tmpView , new LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.WRAP_CONTENT);
}
I use this type of code alot for my dynamically genenerated content (obtain content from prepopulated database).
The TextView seems to be created but might now be visible on the GUI may be stacked over each other etc.
1.Use the layout.setOrientation(ORIENTAIION.VERTICAL) on the parent linear layout's.
2.Use the childCount() on layout to make it sure on the fact that the all 4 text views have been added to the snippet.
3.Also make sure your are not using removeALLView() etc methods for your case study to the problem case.
In my application, i have a tableLayout with many editTexts in it. When i click "save"button, i want to access all the values entered in editTexts. I have assigned IDs in runtime while creating the table. Now how can i access the values from editTexts when "save" button is clicked...? I have used something like below to assign IDs,
for(int i=0;i< no_of_rows ;i++)
for(int j=0;j<5;j++)
{
...............
assignment.setId(i+j);
.............
}
Could anyone suggest a solution..?
Other nice solution is to cycle through all childrens of some Layout, so you don't need to set any special IDs. Just try:
LinearLayout layout = (LinearLayout) findViewById(R.id.layout);
child_count = layout.getChildCount();
for (int i=0; i<child_count; i++)
{
EditText text = (EditText) layout.getChildAt(i);
// do work with text
}
With some other code, you can do this for any other layout hierarchy.
How about something like:
ArrayList<String> strings = new ArrayList<String>();
for(int i=0;i< no_of_rows ;i++)
for(int j=0;j<5;j++)
{
EditText text = (EditText)ActivityName.this.findViewById(i+j);
strings.add(text.getText().toString());
}
}
This would give you all of the values from all of the texts in one big array. If that's not what you want, let me know and I'll see if I can adjust the code.