Building table layout dynamically at run time from XML - android

New to android, I would like to have a view like below with actual values.
My code to dummy values is as below:
<?xml version="1.0" encoding="utf-8"?>
<TableLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginTop="10dp">
<TableRow
android:background="#607D8B"
android:padding="5dp">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="Title" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="Due On" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="" />
</TableRow>
<TableRow
android:background="#ECEFF1"
android:padding="5dp">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="Access to Knowledge" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="12 Feb 2016" />
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="Renew" />
</TableRow>
<TableRow
android:background="#ECEFF1"
android:padding="5dp">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="Achivement" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="16 Feb 2016" />
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="Renew" />
</TableRow>
<TableRow
android:background="#ECEFF1"
android:padding="5dp">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="God of small things" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="22 Feb 2016" />
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="Renew" />
</TableRow>
<Button
android:text="Renew all" />
</TableLayout>
I am getting the values from XML from webservices and parsing it to show in my table view.
I am using DocumentBuilderFactory to parse my XML. Here my XML file is in String str.
builder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
InputSource src = new InputSource();
src.setCharacterStream(new StringReader(str));
Document doc = builder.parse(src);
String title = `doc.getElementsByTagName("title").item(0).getTextContent();`
Normally I use
TitleTxt.setText("Title: " + title);
PublisherTxt.setText("Publisher: " + publisher)
to show the results in my view.
I have multiple questions:
Q1 what modifications are needed in layout file to show - actual values and not the dummy values?
Q2 how to get the array values in XML parsing to show in my layout file?
Q3 how to show the XML parsed results in my table view - dynamically at runtime?
These are related queries, so had to put in the same question. Some of it may sound simple, but being new to Android, I am not able to figure out. Also tried to find a sample code to do it but could not find. Not sure if I am using the right keywords to search for what I am looking for.
Any links to sample code or which exact keywords to look for to search my issue solution or suggestions will also be appreciated.
Thanks in advance.

In order to add new Views to another at runtime, you can use the View.add method. So, in order to make the above table "dynamic", you can alter your layout file to just contain the TableLayout. And later, at runtime you programmatically add TableRows to the TableLayout.
Basically, there are two options how to add a TableRow then.
First, you can construct your TableRow, e.g.:
TextView tvTitle = new TextView(...);
TextView tvDueOn = new TextView(...);
Button btnRenew = new TextView(...);
TableRow tr = new TableRow(...);
tr.add(tvTitle);
tr.add(tvDueOn);
tr.add(btnRenew);
TableLayout lytTable = (TableLayout)findViewById(...);
lytTable.add(tr);
This is just a minimal version, but with adding the views weight, layout_width and layout_height, you can achieve this.
Second, you can design your TableRow in a layout XML file, which you can then load and add to the TableLayout at runtime using LayoutInflater.
lytTableRow.xml
<TableRow
android:id="+#id/lytTableRow"
android:background="#607D8B"
android:padding="5dp">
<TextView
android:id="+#id/tvTitle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1" />
<TextView
android:id="+#id/tvDueOn"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1" />
<Button
android:id="+#id/btnRenew"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="" />
</TableRow>
code in Activity
TableLayout lytTable = (TableLayout)findViewById(R.id.lytTable);
View tableRow = getLayoutInflater().inflate(R.layout.lytTableRow, null);
TextView tvTitle = (TextView)tableRow.findViewById(R.id.tvTitle);
TextView tvDueOn = (TextView)tableRow.findViewById(R.id.tvDueOn);
Button btnRenew = (Button)tableRow.findViewById(R.id.btnRenew);
tvTitle.setText(...);
Both code-parts can be put into a loop for instance, in order to add your multiple rows - but pay attention to set tags/ids to your views using view.setTag in order to be able to distinguish them later in the Button click listener for instance.
Concerning the data, depending on what kind of XML parser you use, you can loop through every item in the data and add them to your TableLayout using one of the options shown above. According to your question, you use a DOM parser. You can loop through the items using a NodeList retrieved from doc.getElementsByTagName("parentnodename") where parentnodename is the element name which contains "title", "dueon" etc.

Related

Need help getting my Android TableLayout to work properly

I am attempting to display data from the on-board SQLite database within a table in the Android UI, but it isn't working as it should. Here is what I have:
activity_main.xml
<TableLayout
android:id="#+id/data_table"
android:stretchColumns="3"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TableRow>
<TextView android:layout_column="1" android:text="id" android:layout_width="0dp" android:layout_weight="1" />
<TextView android:layout_column="2" android:text="firstname" android:layout_width="0dp" android:layout_weight="1" />
<TextView android:layout_column="3" android:text="lastname" android:layout_width="0dp" android:layout_weight="1" />
</TableRow>
</TableLayout>
MainActivity.java
List<People> listOfPeople = databaseHelper.getAllPeople();
TableLayout myTableLayout = (TableLayout) findViewById(R.id.data_table);
for(People person : listOfPeople){
TableRow newTableRow = new TableRow(this);
TableRow.LayoutParams rowParams = new TableRow.LayoutParams();
newTableRow.setLayoutParams(rowParams);
TextView idTV = new TextView(this);
idTV.setLayoutParams(new TableRow.LayoutParams(1));
idTV.setText(person.getId());
TextView firstnameTV = new TextView(this);
firstnameTV.setLayoutParams(new TableRow.LayoutParams(2));
firstnameTV.setText(person.getFirstname());
TextView lastnameTV = new TextView(this);
lastnameTV.setLayoutParams(new TableRow.LayoutParams(3));
lastnameTV.setText(person.getLastname());
newTableRow.addView(idTV);
newTableRow.addView(firstnameTV);
newTableRow.addView(lastnameTV);
myTableLayout.addView(newTableRow);
}
The table and data is displayed, but the data within the rows I built from the database are all smooshed together and unreadable. If I were to compare this to web development, it looks like all the data are in one cell of the table row.
I am very new at Android development (former JSP developer), and what I have here, I have tried to piece together from Google searches. I need to use a TableLayout so a grid layout (or any other layout) will not do.
EDIT:
I added some background color to my "cells" and discovered they are in different cells. The issue, apparently, is that they are not distributing themselves correctly as I am not sure how to add "layout_width" and "layout_weight" to the cells within Java. At least, I guess that is what the issue is.
Just change your xml to this:
<TableLayout
android:id="#+id/data_table" android:stretchColumns="1"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TableRow>
<TextView android:layout_column="1" android:layout_weight="1" android:text="id" />
<TextView android:layout_column="2" android:layout_weight="1" android:text="firstname" />
<TextView android:layout_column="3" android:layout_weight="1" android:text="lastname" />
</TableRow>
Make sure to also set the layout_weight to 1, for all the TextViews added by java code.

How to programmatically add content to custom XML layout?

I'm making a custom XML layout to display a cocktail recipe. Here is my XML:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_width="fill_parent"
android:layout_height="fill_parent">
<TextView android:id="#+id/drinkname" android:layout_height="wrap_content"
android:textSize="30sp" android:text="#string/drink_name"
android:layout_width="wrap_content" android:layout_alignParentTop="true"
android:layout_centerHorizontal="true" />
<TextView android:layout_width="fill_parent"
android:layout_height="2dp" android:background="#FFFFFFFF"
android:layout_below="#id/drinkname" />
<TextView android:layout_height="wrap_content" android:id="#+id/ingredient_label"
android:text="Ingredients: " android:layout_width="wrap_content"
android:layout_below="#+id/drinkname" android:layout_marginLeft="10dp"
android:layout_marginTop="16dp" />
<TableLayout android:layout_height="wrap_content"
android:id="#+id/ingredient_table" android:layout_width="wrap_content"
android:layout_alignTop="#+id/ingredient_label"
android:layout_alignLeft="#+id/drinkname"
android:layout_alignParentRight="true">
<TableRow android:id="#+id/tableRow1" android:layout_width="wrap_content"
android:layout_height="wrap_content">
<TextView android:text="• 2 oz. Gin (Boodles)"android:id="#+id/textView1"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</TableRow>
<TableRow android:id="#+id/tableRow2" android:layout_width="wrap_content"
android:layout_height="wrap_content">
<TextView android:text="• 2 oz. Vodka (Stolichnaya)"
android:id="#+id/textView2" android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</TableRow>
<TableRow android:id="#+id/tableRow3" android:layout_width="wrap_content"
android:layout_height="wrap_content">
<TextView android:text="• 1/2 oz. Vermouth, dry" android:id="#+id/textView3"
android:layout_width="wrap_content" android:layout_height="wrap_content" />
</TableRow>
<TableRow android:id="#+id/tableRow4" android:layout_width="wrap_content"
android:layout_height="wrap_content">
<TextView android:text="• 3 pieces Olive" android:id="#+id/textView4"
android:layout_width="wrap_content" android:layout_height="wrap_content" />
</TableRow>
</TableLayout>
<TextView android:id="#+id/instruction_label"
android:layout_height="wrap_content" android:layout_width="wrap_content"
android:layout_below="#id/ingredient_table" android:layout_alignLeft="#id/ingredient_label"
android:text="Instructions: " android:layout_marginTop="25dp" />
<TextView android:id="#+id/instructions"
android:layout_height="wrap_content" android:layout_width="wrap_content"
android:layout_alignTop="#id/instruction_label"
android:layout_alignLeft="#id/drinkname"
android:layout_alignParentRight="true" android:text="#string/drink_instructions" />
<TextView android:id="#+id/glass_label" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_below="#id/instructions"
android:layout_alignLeft="#id/ingredient_label" android:text="Glass:"
android:layout_marginTop="25dp" />
<TextView android:id="#+id/glass_type"
android:layout_toRightOf="#id/glass_label" android:text="#string/drink_glass"
android:layout_height="wrap_content" android:layout_width="wrap_content"
android:layout_alignTop="#id/glass_label" android:layout_alignLeft="#+id/drinkname" />
As you can see all the content displayed is written into the layout itself or is taken from a string resource. My question is: what would I have to do to keep the layout I created below, but be able to fill in the content programmatically?
You would have to do something like this...
(TextView) this.findViewById(R.id.drinkname).setText("Water");
Use findView to get a reference to a particular view on the activity. Pass it the Resource identifier you gave in the XML (the id property). Cast it to the correct View type, and then set it's properties.
The resource id's are created automatically from the id attribute in XML, and added to the R class inside R.id..
As an example from the application I'm currently writing, I usually define the views I'm going to be modifying as class level fields near the beginning of the class like so:
TextView tvGameDate;
TextView tvGameTime;
TextView tvHomeTeam;
TextView tvAwayTeam;
TextView tvHomePitcher;
Then near the start of onCreate I will populate them all with the references to the actial views like this:
tvGameDate = (TextView) this.findViewById(R.id.tvGameDate);
tvGameTime = (TextView) this.findViewById(R.id.tvGameTime);
tvHomeTeam = (TextView) this.findViewById(R.id.tvHomeTeam);
tvAwayTeam = (TextView) this.findViewById(R.id.tvAwayTeam);
tvHomePitcher = (TextView) this.findViewById(R.id.tvHomePitcher);
Then I can just refer to the fields I defined whenever I need to access them like this:
tvHomeTeam.setText(attributes.getNamedItem("home_long").getNodeValue());
tvHomePitcher.setText(" (" + attributes.getNamedItem("home_pitcher").getNodeValue() + ")");
In your XML it looks like you may actually need to dynamically create additional text views on the fly based on the recipe. You can do this like so (where llIngredients maps to some LinearLayout in your XML):
TextView tv = new TextView(context);
tv.setTextColor(Color.BLACK);
tv.setLayoutParams(new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT));
tv.setText("Some text for the new view");
llIngredients.addView(tv);
Not sure I follow you. I'm guessing this resource represents an activity. You can get a reference to your text view, lets say glass_type by saying -
TextView glassTypeTxtView = findViewById(R.id.glass_type) and set its content dynamically by saying glassTypeTxtView.setText("new text").
Please correct me if I misunderstood your question completely.

How to program relativeLayouts in code

I need to create a dinamic table which will be fit with rows of data. The rows I want will have an specific form, like this:
So, to get it, I used relativeLayouts. The problem is that I first tried it with an .xml to see what parameters will have the differents views that it forms, and I get it, but now I cant replicate it in the code.
Here is my code:
TableLayout linkRoutesTable = (TableLayout) findViewById(R.id.layoutLinkRoutes);
//ROW:
TableRow linkRouteRow = new TableRow(this);
linkRouteRow.setLayoutParams(new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT));
linkRouteRow.setId(i)
//RELATIVELAYOUT:
float px0 = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 1, r.getDisplayMetrics());
RelativeLayout relativeLayout = new RelativeLayout(this);
relativeLayout.setLayoutParams(new RelativeLayout.LayoutParams(0, (int)px0)));
//CONTENT:
// BUTTON: ...
// NUMBER:...
// ADDRESS:...
// NAME: ...
relativeLayout.addView(number);
relativeLayout.addView(name);
relativeLayout.addView(address);
relativeLayout.addView(button);
linkRouteRow.addView(relativeLayout);
linkRouteTable.addView(linkRouteRow);
linkRoutesTable.refreshDrawableState();
It doesn't show anything...
The .xml show ok, here it is:
<TableLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_gravity="center" android:orientation="vertical">
<TableRow>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="0dp"
android:layout_weight="1"
android:id="#+id/layoutLinkRoutes" >
<Button android:text="Button" android:layout_width="wrap_content" android:layout_height="wrap_content" android:id="#+id/button1" android:layout_alignParentTop="true" android:layout_alignParentRight="true"></Button>
<TextView android:textStyle="bold" android:textSize="45dp" android:text="1" android:id="#+id/textView1" android:layout_width="wrap_content" android:layout_height="wrap_content" android:textAppearance="?android:attr/textAppearanceLarge" android:layout_marginLeft="22dp"></TextView>
<TextView android:text="TextView" android:id="#+id/textView3" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignBottom="#+id/button1" android:layout_toRightOf="#+id/textView1" android:layout_marginLeft="16dp"></TextView>
<TextView android:text="TextView" android:id="#+id/textView2" android:layout_width="wrap_content" android:layout_height="wrap_content" android:textAppearance="?android:attr/textAppearanceLarge" android:layout_alignParentTop="true" android:layout_alignLeft="#+id/textView3"></TextView>
</RelativeLayout>
</TableRow>
What Am I doing wrong in the code? I need some help, I tried everything.
If I dont use the relativeLayouts and the rows, it shows something but bad... so the problem is the rows and the relativelayout
Really thanks...
You don't have to define the layout in code to fill a table dynamically. You can infalte a layout which you define in xml like a normal layout.
So you define your table row layout one time in a xml file and infalte it multiple times into your table layout.
Check this answer.

How to set view's layout column in code (view is inside tablerow)?

I have a tablelayout in xml. I am also adding some rows to it in code. How can i set some view's column_layout in code?
In xml i have:
android:layout_column="3"
How to achieve the same in code (e.g. for TextView)?
TextView tv = new TextView(this);
tv.setLayoutParams(new TableRow.LayoutParams(3));
I'm not entirely sure I understand the questions, however MyTracks for Android provides some nice example code using a table layout. It can be found here.
Thanks for the comment. I think this is what you are looking for:
< TableLayout xmlns:
android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:stretchColumns="3">
<TableRow>
<TextView
android:layout_column="1"
android:text="Open..."
android:padding="3dip" />
<TextView
android:text="Ctrl-O"
android:gravity="right"
android:padding="3dip" />
<TextView
android:text="String"
android:gravity="right"
android:padding="3dip" />
</TableRow> ...`

Indent bullet list in TextView

I have a TextView which I fill with text from a string resources in strings.xml. The string resource contains < li > elements to create a bullet list inside the TextView. My problem is that I want to control the indention of lines in the bullet list that span over more than one line. Default the text isn't indented past the bullet so it looks kind of ugly. Is it possible to do this with style parameters or to create bullets in some other way?
Thanks in advance.
edit:
Is it really answered? I don't have any problems producing the bullet list, as described in those links but I'm having problems getting the layout correct. The indentation is like this:
text that go beyond the width
of the line.
And I want the "of the line" to at least start indented as far as the text after the bullet. That's what I try to achieve.
I'm suprised that there seems to be noone with this problem. I mean, bullet list can't be that uncommon in about-dialogs, FAQ etc and a bullet doesn't have to contain too much text to span more than one row and run into this problem.
Anyway, I got to solve it like this for now:
<?xml version="1.0" encoding="utf-8"?>
<ScrollView
android:id="#+id/ScrollViewTipsLayout"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
xmlns:android="http://schemas.android.com/apk/res/android">
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/TipsLayout"
android:layout_width="fill_parent"
android:layout_height="wrap_content">
<TableLayout
android:layout_height="wrap_content"
android:id="#+id/TableLayout01"
android:layout_width="wrap_content"
>
<TableRow>
<TextView android:id="#+id/tvIngress"
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:text="#+string/tv_picking_content_ingress"
android:layout_span="2"
android:singleLine="false"
android:layout_weight="1"
/>
</TableRow>
<TableRow>
<TextView android:id="#+id/tvCleaningDot1"
android:layout_height="wrap_content"
android:text="•"
android:singleLine="false"
/>
<TextView android:id="#+id/tvCleaningFirst"
android:layout_height="wrap_content"
android:text="#+string/tv_picking_content_first"
android:layout_width="0dp"
android:layout_weight="1"
android:gravity="left"
android:singleLine="false"
/>
</TableRow>
<TextView android:id="#+id/tvCleaningDot2"
android:layout_height="wrap_content"
android:text="•"
android:singleLine="false"
/>
<TextView android:id="#+id/tvCleaningSecond"
android:layout_height="wrap_content"
android:text="#+string/tv_picking_content_second"
android:layout_width="0dp"
android:layout_weight="1"
android:gravity="left"
android:singleLine="false"
/>
</TableRow>
</TableLayout>
</RelativeLayout>
I use it to present static text in a bullet list so I don't bother to create the bullet + text dynamically in code. If anyone have any suggestion how to accomplish the same thing in a better way, please enlight me.
Btw, if going with the solution suggested in second link above:
android:text="<ol><li>item 1\n</li><li>item 2\n</li></ol>
The second, third etc. row in a bullet that span over more than one row won't get same indention as first line, which is quite ugly.
Thank you #Bjorn
You can also do something like bellow.
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal" >
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:drawableLeft="#drawable/point"
android:textAppearance="?android:attr/textAppearanceSmall"
/>
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Your Text Here"
android:textAppearance="?android:attr/textAppearanceSmall"
android:textSize="14sp" />
</LinearLayout>
The way I solved this problem was by using a RelativeLayout and marginLeft. The marginLeft will put a blank margin between it and the previous item.
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:scrollbarTrackVertical="#drawable/scrollbar_vertical_track"
android:scrollbarThumbVertical="#drawable/scrollbar_vertical_thumb"
android:scrollbarSize="12dip">
<RelativeLayout
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:padding="10sp">
<TextView
android:id="#+id/body_text3"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:lineSpacingExtra="3sp"
android:text="Main paragraph of text, before the bulleted list"
android:textSize="15sp" />
<TextView
android:id="#+id/type1"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:lineSpacingExtra="3sp"
android:text="• First bullet"
android:textSize="15sp"
android:layout_below="#+id/body_text3"
android:layout_marginLeft="25dp" />
<TextView
android:id="#+id/type2"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:lineSpacingExtra="3sp"
android:text="• Second bullet"
android:textSize="15sp"
android:layout_below="#+id/type1"
android:layout_marginLeft="25dp" />
</RelativeLayout>
</ScrollView>
Just trying to point out the key answer of the question:
to create an bullet list, use TableLayout with two columns for each row. One column for TextView of a bullet and the other one for the text
to make text TextView fill the rest empty TableRow and indented at new line, set the weight to 1. You can set the bullet weight to zero or just simply not set the bullet weight and let it empty
based on my experience, changing width parameter do not affect the text and the bullet. So you can leave it empty or set it to anything you want.
Example:
<TableLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<TableRow
android:id="#+id/tableRow1"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<TextView
android:id="#+id/bullet"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="#string/bullet"/>
<TextView
android:id="#+id/TextView01"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="this is the text of a bullet list"/>
</TableRow>
</TableLayout>

Categories

Resources