{"id":2653,"date":"2016-05-01T09:11:16","date_gmt":"2016-05-01T09:11:16","guid":{"rendered":"http:\/\/truelogic.org\/wordpress\/?p=2653"},"modified":"2016-05-01T09:11:16","modified_gmt":"2016-05-01T09:11:16","slug":"showing-dynamic-data-in-a-tablelayout-in-android","status":"publish","type":"post","link":"https:\/\/truelogic.org\/wordpress\/2016\/05\/01\/showing-dynamic-data-in-a-tablelayout-in-android\/","title":{"rendered":"Showing dynamic data in a TableLayout in Android"},"content":{"rendered":"            <script type=\"text\/javascript\" src=\"https:\/\/truelogic.org\/wordpress\/wp-content\/plugins\/wordpress-code-snippet\/scripts\/shBrushXml.js\"><\/script>\n            <script type=\"text\/javascript\" src=\"https:\/\/truelogic.org\/wordpress\/wp-content\/plugins\/wordpress-code-snippet\/scripts\/shBrushJava.js\"><\/script>\n<h4>OVERVIEW<\/h4>\n<p>Showing tabular data is a standard requirement in a lot of applications. The best way is to use a TableLayout, which will automatically arrange the inner Views into columns across multiple TableRows. If you have complex requirements in which some rows may have different layouts, then its best not to use the TableLayout as it doesnt handle varying column counts very well.<\/p>\n<p>In the sample application, we have a table which shows invoices. We have created classes for generating the invoice listing. In a real world case, this data would come from database. Here we populate the list with dummy data.<\/p>\n<p>The TableLayout is wrapped in a ScrollView so that we can scroll the table up and down when the rows overflow the screen height.<\/p>\n<h4>FILES<\/h4>\n<p>MainActivity.java &#8211; the main Layout class<\/p>\n<p>activity_main.xml &#8211; the main layout xml<\/p>\n<p>dimens.xml\u00a0 &#8211; define font sizes<\/p>\n<p>InvoiceData.java &#8211; Data structure for an invoice<\/p>\n<p>Invoices.java &#8211; Class to generate invoice list<\/p>\n<p>&nbsp;<\/p>\n<h4>SOURCE LISTING<\/h4>\n<p><strong>AndroidManifest.xml<\/strong><br \/>\n<pre class=\"brush: xml\">&lt;?xml version=&quot;1.0&quot; encoding=&quot;utf-8&quot;?&gt;\r\n&lt;manifest xmlns:android=&quot;http:\/\/schemas.android.com\/apk\/res\/android&quot;\r\n    package=&quot;table.test.com.dynamictable&quot;&gt;\r\n\r\n    &lt;application\r\n        android:allowBackup=&quot;true&quot;\r\n        android:icon=&quot;@mipmap\/ic_launcher&quot;\r\n        android:label=&quot;@string\/app_name&quot;\r\n        android:supportsRtl=&quot;true&quot;\r\n        android:theme=&quot;@style\/AppTheme&quot;&gt;\r\n        &lt;activity android:name=&quot;.MainActivity&quot;&gt;\r\n            &lt;intent-filter&gt;\r\n                &lt;action android:name=&quot;android.intent.action.MAIN&quot; \/&gt;\r\n\r\n                &lt;category android:name=&quot;android.intent.category.LAUNCHER&quot; \/&gt;\r\n            &lt;\/intent-filter&gt;\r\n        &lt;\/activity&gt;\r\n    &lt;\/application&gt;\r\n\r\n&lt;\/manifest&gt;\r\n<\/pre><\/p>\n<p><strong>dimens.xml<\/strong><br \/>\n<pre class=\"brush: xml\">&lt;resources&gt;\r\n    &lt;!-- Default screen margins, per the Android Design guidelines. --&gt;\r\n    &lt;dimen name=&quot;activity_horizontal_margin&quot;&gt;16dp&lt;\/dimen&gt;\r\n    &lt;dimen name=&quot;activity_vertical_margin&quot;&gt;16dp&lt;\/dimen&gt;\r\n    &lt;dimen name=&quot;font_size_verysmall&quot;&gt;10sp&lt;\/dimen&gt;\r\n    &lt;dimen name=&quot;font_size_small&quot;&gt;12sp&lt;\/dimen&gt;\r\n    &lt;dimen name=&quot;font_size_medium&quot;&gt;20sp&lt;\/dimen&gt;\r\n&lt;\/resources&gt;\r\n<\/pre><\/p>\n<p><strong>activity_main.xml<\/strong><br \/>\n<pre class=\"brush: xml\">&lt;?xml version=&quot;1.0&quot; encoding=&quot;utf-8&quot;?&gt;\r\n&lt;LinearLayout xmlns:android=&quot;http:\/\/schemas.android.com\/apk\/res\/android&quot;\r\n    xmlns:tools=&quot;http:\/\/schemas.android.com\/tools&quot;\r\n    android:layout_width=&quot;match_parent&quot;\r\n    android:layout_height=&quot;match_parent&quot;\r\n    android:paddingBottom=&quot;@dimen\/activity_vertical_margin&quot;\r\n    android:paddingLeft=&quot;@dimen\/activity_horizontal_margin&quot;\r\n    android:paddingRight=&quot;@dimen\/activity_horizontal_margin&quot;\r\n    android:paddingTop=&quot;@dimen\/activity_vertical_margin&quot;\r\n    android:orientation=&quot;vertical&quot;\r\n    android:id=&quot;@+id\/invoices_layout&quot;\r\n    tools:context=&quot;table.test.com.dynamictable.MainActivity&quot;&gt;\r\n\r\n\r\n    &lt;ScrollView\r\n        android:layout_width=&quot;match_parent&quot;\r\n        android:layout_height=&quot;match_parent&quot; &gt;\r\n\r\n        &lt;TableLayout\r\n            android:id=&quot;@+id\/tableInvoices&quot;\r\n            android:layout_width=&quot;match_parent&quot;\r\n            android:layout_height=&quot;match_parent&quot;\r\n            android:padding=&quot;0dp&quot;\r\n            android:stretchColumns=&quot;*&quot;\r\n            &gt;\r\n        &lt;\/TableLayout&gt;\r\n\r\n    &lt;\/ScrollView&gt;\r\n\r\n&lt;\/LinearLayout&gt;\r\n<\/pre><\/p>\n<p><strong>InvoiceData.java<\/strong><br \/>\n<pre class=\"brush: java\">package table.test.com.dynamictable;\r\n\r\nimport java.math.BigDecimal;\r\nimport java.util.Date;\r\n\r\n\/\/\r\n\/\/ Data structure for invoices\r\n\/\/\r\n\r\npublic class InvoiceData {\r\n\r\n        public int id;\r\n        public int invoiceNumber;\r\n        public Date invoiceDate;\r\n        public String customerName;\r\n        public String customerAddress;\r\n        public BigDecimal invoiceAmount;\r\n        public BigDecimal amountDue;\r\n\r\n\r\n}\r\n<\/pre><\/p>\n<p><strong>Invoices.java<\/strong><br \/>\n<pre class=\"brush: java\">package table.test.com.dynamictable;\r\n\r\nimport java.math.BigDecimal;\r\nimport java.util.Date;\r\n\r\n\/**\r\n * Created by amit on 1\/5\/16.\r\n *\/\r\npublic class Invoices {\r\n\r\n    public InvoiceData[] getInvoices() {\r\n        InvoiceData[] data = new InvoiceData[20];\r\n\r\n        for(int i = 0; i &lt; 20; i ++) {\r\n            InvoiceData row = new InvoiceData();\r\n            row.id = (i+1);\r\n            row.invoiceNumber = row.id;\r\n            row.amountDue = BigDecimal.valueOf(20.00 * i);\r\n            row.invoiceAmount = BigDecimal.valueOf(120.00 * (i+1));\r\n            row.invoiceDate = new Date();\r\n            row.customerName =  &quot;Thomas John Beckett&quot;;\r\n            row.customerAddress = &quot;1112, Hash Avenue, NYC&quot;;\r\n\r\n            data[i] = row;\r\n        }\r\n        return data;\r\n\r\n    }\r\n}\r\n<\/pre><\/p>\n<p><strong>MainActivity.java<\/strong><br \/>\n<pre class=\"brush: java\">package table.test.com.dynamictable;\r\n\r\nimport android.app.ProgressDialog;\r\nimport android.graphics.Color;\r\nimport android.os.AsyncTask;\r\nimport android.support.v7.app.AppCompatActivity;\r\nimport android.os.Bundle;\r\nimport android.util.TypedValue;\r\nimport android.view.Gravity;\r\nimport android.view.View;\r\nimport android.widget.FrameLayout;\r\nimport android.widget.LinearLayout;\r\nimport android.widget.TableLayout;\r\nimport android.widget.TableRow;\r\nimport android.widget.TextView;\r\n\r\nimport java.math.BigDecimal;\r\nimport java.text.DecimalFormat;\r\nimport java.text.SimpleDateFormat;\r\n\r\npublic class MainActivity extends AppCompatActivity {\r\n\r\n    private TableLayout mTableLayout;\r\n    ProgressDialog mProgressBar;\r\n\r\n    @Override\r\n    protected void onCreate(Bundle savedInstanceState) {\r\n        super.onCreate(savedInstanceState);\r\n        setContentView(R.layout.activity_main);\r\n\r\n        mProgressBar = new ProgressDialog(this);\r\n\r\n        \/\/ setup the table\r\n        mTableLayout = (TableLayout) findViewById(R.id.tableInvoices);\r\n   \r\n        mTableLayout.setStretchAllColumns(true);\r\n\r\n\r\n        startLoadData();\r\n    }\r\n\r\n    public void startLoadData() {\r\n\r\n        mProgressBar.setCancelable(false);\r\n        mProgressBar.setMessage(&quot;Fetching Invoices..&quot;);\r\n        mProgressBar.setProgressStyle(ProgressDialog.STYLE_SPINNER);\r\n        mProgressBar.show();\r\n        new LoadDataTask().execute(0);\r\n\r\n    }\r\n\r\n    public void loadData() {\r\n\r\n        int leftRowMargin=0;\r\n        int topRowMargin=0;\r\n        int rightRowMargin=0;\r\n        int bottomRowMargin = 0;\r\n        int textSize = 0, smallTextSize =0, mediumTextSize = 0;\r\n\r\n        textSize = (int) getResources().getDimension(R.dimen.font_size_verysmall);\r\n        smallTextSize = (int) getResources().getDimension(R.dimen.font_size_small);\r\n        mediumTextSize = (int) getResources().getDimension(R.dimen.font_size_medium);\r\n\r\n        Invoices invoices = new Invoices();\r\n        InvoiceData[] data = invoices.getInvoices();\r\n\r\n        SimpleDateFormat dateFormat = new SimpleDateFormat(&quot;dd MMM, yyyy&quot;);\r\n        DecimalFormat decimalFormat = new DecimalFormat(&quot;0.00&quot;);\r\n\r\n        int rows = data.length;\r\n        getSupportActionBar().setTitle(&quot;Invoices (&quot; + String.valueOf(rows) + &quot;)&quot;);\r\n        TextView textSpacer = null;\r\n\r\n        mTableLayout.removeAllViews();\r\n\r\n        \/\/ -1 means heading row\r\n        for(int i = -1; i &lt; rows; i ++) {\r\n            InvoiceData row = null;\r\n            if (i &gt; -1)\r\n                row = data[i];\r\n            else {\r\n                textSpacer = new TextView(this);\r\n                textSpacer.setText(&quot;&quot;);\r\n\r\n            }\r\n            \/\/ data columns\r\n            final TextView tv = new TextView(this);\r\n            tv.setLayoutParams(new TableRow.LayoutParams(TableRow.LayoutParams.WRAP_CONTENT,\r\n                    TableRow.LayoutParams.WRAP_CONTENT));\r\n\r\n            tv.setGravity(Gravity.LEFT);\r\n\r\n            tv.setPadding(5, 15, 0, 15);\r\n            if (i == -1) {\r\n                tv.setText(&quot;Inv.#&quot;);\r\n                tv.setBackgroundColor(Color.parseColor(&quot;#f0f0f0&quot;));\r\n                tv.setTextSize(TypedValue.COMPLEX_UNIT_PX, smallTextSize);\r\n            } else {\r\n                tv.setBackgroundColor(Color.parseColor(&quot;#f8f8f8&quot;));\r\n                tv.setText(String.valueOf(row.invoiceNumber));\r\n                tv.setTextSize(TypedValue.COMPLEX_UNIT_PX, textSize);\r\n            }\r\n\r\n            final TextView tv2 = new TextView(this);\r\n            if (i == -1) {\r\n                tv2.setLayoutParams(new TableRow.LayoutParams(TableRow.LayoutParams.MATCH_PARENT,\r\n                        TableRow.LayoutParams.WRAP_CONTENT));\r\n                tv2.setTextSize(TypedValue.COMPLEX_UNIT_PX, smallTextSize);\r\n            } else {\r\n                tv2.setLayoutParams(new TableRow.LayoutParams(TableRow.LayoutParams.WRAP_CONTENT,\r\n                        TableRow.LayoutParams.MATCH_PARENT));\r\n                tv2.setTextSize(TypedValue.COMPLEX_UNIT_PX, textSize);\r\n            }\r\n\r\n            tv2.setGravity(Gravity.LEFT);\r\n\r\n            tv2.setPadding(5, 15, 0, 15);\r\n            if (i == -1) {\r\n                tv2.setText(&quot;Date&quot;);\r\n                tv2.setBackgroundColor(Color.parseColor(&quot;#f7f7f7&quot;));\r\n            }else {\r\n                tv2.setBackgroundColor(Color.parseColor(&quot;#ffffff&quot;));\r\n                tv2.setTextColor(Color.parseColor(&quot;#000000&quot;));\r\n                tv2.setText(dateFormat.format(row.invoiceDate));\r\n            }\r\n\r\n\r\n            final LinearLayout layCustomer = new LinearLayout(this);\r\n            layCustomer.setOrientation(LinearLayout.VERTICAL);\r\n            layCustomer.setPadding(0, 10, 0, 10);\r\n            layCustomer.setBackgroundColor(Color.parseColor(&quot;#f8f8f8&quot;));\r\n\r\n            final TextView tv3 = new TextView(this);\r\n            if (i == -1) {\r\n                tv3.setLayoutParams(new TableRow.LayoutParams(TableRow.LayoutParams.MATCH_PARENT,\r\n                        TableRow.LayoutParams.MATCH_PARENT));\r\n                tv3.setPadding(5, 5, 0, 5);\r\n                tv3.setTextSize(TypedValue.COMPLEX_UNIT_PX, smallTextSize);\r\n            } else {\r\n                tv3.setLayoutParams(new TableRow.LayoutParams(TableRow.LayoutParams.MATCH_PARENT,\r\n                        TableRow.LayoutParams.MATCH_PARENT));\r\n                tv3.setPadding(5, 0, 0, 5);\r\n                tv3.setTextSize(TypedValue.COMPLEX_UNIT_PX, textSize);\r\n            }\r\n\r\n            tv3.setGravity(Gravity.TOP);\r\n\r\n\r\n            if (i == -1) {\r\n                tv3.setText(&quot;Customer&quot;);\r\n                tv3.setBackgroundColor(Color.parseColor(&quot;#f0f0f0&quot;));\r\n            } else {\r\n                tv3.setBackgroundColor(Color.parseColor(&quot;#f8f8f8&quot;));\r\n                tv3.setTextColor(Color.parseColor(&quot;#000000&quot;));\r\n                tv3.setTextSize(TypedValue.COMPLEX_UNIT_PX, smallTextSize);\r\n                tv3.setText(row.customerName);\r\n            }\r\n            layCustomer.addView(tv3);\r\n\r\n\r\n            if (i &gt; -1) {\r\n                final TextView tv3b = new TextView(this);\r\n                tv3b.setLayoutParams(new TableRow.LayoutParams(TableRow.LayoutParams.WRAP_CONTENT,\r\n                        TableRow.LayoutParams.WRAP_CONTENT));\r\n\r\n                tv3b.setGravity(Gravity.RIGHT);\r\n                tv3b.setTextSize(TypedValue.COMPLEX_UNIT_PX, textSize);\r\n                tv3b.setPadding(5, 1, 0, 5);\r\n                tv3b.setTextColor(Color.parseColor(&quot;#aaaaaa&quot;));\r\n                tv3b.setBackgroundColor(Color.parseColor(&quot;#f8f8f8&quot;));\r\n                tv3b.setText(row.customerAddress);\r\n                layCustomer.addView(tv3b);\r\n            }\r\n\r\n            final LinearLayout layAmounts = new LinearLayout(this);\r\n            layAmounts.setOrientation(LinearLayout.VERTICAL);\r\n            layAmounts.setGravity(Gravity.RIGHT);\r\n            layAmounts.setPadding(0, 10, 0, 10);\r\n            layAmounts.setLayoutParams(new TableRow.LayoutParams(TableRow.LayoutParams.MATCH_PARENT,\r\n                    TableRow.LayoutParams.MATCH_PARENT));\r\n\r\n\r\n\r\n            final TextView tv4 = new TextView(this);\r\n            if (i == -1) {\r\n                tv4.setLayoutParams(new TableRow.LayoutParams(TableRow.LayoutParams.MATCH_PARENT,\r\n                        TableRow.LayoutParams.MATCH_PARENT));\r\n                tv4.setPadding(5, 5, 1, 5);\r\n                layAmounts.setBackgroundColor(Color.parseColor(&quot;#f7f7f7&quot;));\r\n            } else {\r\n                tv4.setLayoutParams(new TableRow.LayoutParams(TableRow.LayoutParams.MATCH_PARENT,\r\n                        TableRow.LayoutParams.WRAP_CONTENT));\r\n                tv4.setPadding(5, 0, 1, 5);\r\n                layAmounts.setBackgroundColor(Color.parseColor(&quot;#ffffff&quot;));\r\n            }\r\n\r\n            tv4.setGravity(Gravity.RIGHT);\r\n\r\n            if (i == -1) {\r\n                tv4.setText(&quot;Inv.Amount&quot;);\r\n                tv4.setBackgroundColor(Color.parseColor(&quot;#f7f7f7&quot;));\r\n                tv4.setTextSize(TypedValue.COMPLEX_UNIT_PX, smallTextSize);\r\n            } else {\r\n                tv4.setBackgroundColor(Color.parseColor(&quot;#ffffff&quot;));\r\n                tv4.setTextColor(Color.parseColor(&quot;#000000&quot;));\r\n                tv4.setText(decimalFormat.format(row.invoiceAmount));\r\n                tv4.setTextSize(TypedValue.COMPLEX_UNIT_PX, textSize);\r\n            }\r\n\r\n            layAmounts.addView(tv4);\r\n\r\n\r\n            if (i &gt; -1) {\r\n                final TextView tv4b = new TextView(this);\r\n                tv4b.setLayoutParams(new TableRow.LayoutParams(TableRow.LayoutParams.MATCH_PARENT,\r\n                        TableRow.LayoutParams.WRAP_CONTENT));\r\n\r\n                tv4b.setGravity(Gravity.RIGHT);\r\n                tv4b.setTextSize(TypedValue.COMPLEX_UNIT_PX, textSize);\r\n                tv4b.setPadding(2, 2, 1, 5);\r\n                tv4b.setTextColor(Color.parseColor(&quot;#00afff&quot;));\r\n                tv4b.setBackgroundColor(Color.parseColor(&quot;#ffffff&quot;));\r\n\r\n                String due = &quot;&quot;;\r\n                if (row.amountDue.compareTo(new BigDecimal(0.01)) == 1) {\r\n                    due = &quot;Due:&quot; + decimalFormat.format(row.amountDue);\r\n                    due = due.trim();\r\n                }\r\n                tv4b.setText(due);\r\n                layAmounts.addView(tv4b);\r\n            }\r\n\r\n\r\n            \/\/ add table row\r\n            final TableRow tr = new TableRow(this);\r\n            tr.setId(i + 1);\r\n            TableLayout.LayoutParams trParams = new TableLayout.LayoutParams(TableLayout.LayoutParams.MATCH_PARENT,\r\n                    TableLayout.LayoutParams.WRAP_CONTENT);\r\n            trParams.setMargins(leftRowMargin, topRowMargin, rightRowMargin, bottomRowMargin);\r\n            tr.setPadding(0,0,0,0);\r\n            tr.setLayoutParams(trParams);\r\n\r\n\r\n\r\n            tr.addView(tv);\r\n            tr.addView(tv2);\r\n            tr.addView(layCustomer);\r\n            tr.addView(layAmounts);\r\n\r\n            if (i &gt; -1) {\r\n\r\n                tr.setOnClickListener(new View.OnClickListener() {\r\n                    public void onClick(View v) {\r\n                        TableRow tr = (TableRow) v;\r\n                        \/\/do whatever action is needed\r\n\r\n                    }\r\n                });\r\n\r\n\r\n            }\r\n            mTableLayout.addView(tr, trParams);\r\n\r\n            if (i &gt; -1) {\r\n\r\n                \/\/ add separator row\r\n                final TableRow trSep = new TableRow(this);\r\n                TableLayout.LayoutParams trParamsSep = new TableLayout.LayoutParams(TableLayout.LayoutParams.MATCH_PARENT,\r\n                        TableLayout.LayoutParams.WRAP_CONTENT);\r\n                trParamsSep.setMargins(leftRowMargin, topRowMargin, rightRowMargin, bottomRowMargin);\r\n\r\n                trSep.setLayoutParams(trParamsSep);\r\n                TextView tvSep = new TextView(this);\r\n                TableRow.LayoutParams tvSepLay = new TableRow.LayoutParams(TableRow.LayoutParams.MATCH_PARENT,\r\n                        TableRow.LayoutParams.WRAP_CONTENT);\r\n                tvSepLay.span = 4;\r\n                tvSep.setLayoutParams(tvSepLay);\r\n                tvSep.setBackgroundColor(Color.parseColor(&quot;#d9d9d9&quot;));\r\n                tvSep.setHeight(1);\r\n\r\n                trSep.addView(tvSep);\r\n                mTableLayout.addView(trSep, trParamsSep);\r\n            }\r\n\r\n\r\n        }\r\n    }\r\n\r\n    \/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\r\n\r\n    \/\/\r\n    \/\/ The params are dummy and not used\r\n    \/\/\r\n    class LoadDataTask extends AsyncTask&lt;Integer, Integer, String&gt; {\r\n        @Override\r\n        protected String doInBackground(Integer... params) {\r\n\r\n            try {\r\n                Thread.sleep(2000);\r\n\r\n            } catch (InterruptedException e) {\r\n                e.printStackTrace();\r\n            }\r\n\r\n            return &quot;Task Completed.&quot;;\r\n        }\r\n        @Override\r\n        protected void onPostExecute(String result) {\r\n            mProgressBar.hide();\r\n            loadData();\r\n        }\r\n        @Override\r\n        protected void onPreExecute() {\r\n        }\r\n        @Override\r\n        protected void onProgressUpdate(Integer... values) {\r\n\r\n        }\r\n    }\r\n\r\n}\r\n<\/pre><\/p>\n<p>&nbsp;<\/p>\n<p>&nbsp;<\/p>\n<h4>SCREENSHOT<\/h4>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"alignleft size-full wp-image-2656\" src=\"https:\/\/truelogic.org\/wordpress\/wp-content\/uploads\/2016\/05\/Screenshot_2016-05-01-13-53-31.png\" alt=\"Screenshot_2016-05-01-13-53-31\" width=\"480\" height=\"854\" srcset=\"https:\/\/truelogic.org\/wordpress\/wp-content\/uploads\/2016\/05\/Screenshot_2016-05-01-13-53-31.png 480w, https:\/\/truelogic.org\/wordpress\/wp-content\/uploads\/2016\/05\/Screenshot_2016-05-01-13-53-31-300x534.png 300w\" sizes=\"auto, (max-width: 480px) 100vw, 480px\" \/><\/p>\n<p>&nbsp;<\/p>\n<p>&nbsp;<\/p>\n<p>&nbsp;<\/p>\n<p>&nbsp;<\/p>\n<p>&nbsp;<\/p>\n<p>&nbsp;<\/p>\n<p>&nbsp;<\/p>\n<p>&nbsp;<\/p>\n<p>&nbsp;<\/p>\n<p>&nbsp;<\/p>\n<p>&nbsp;<\/p>\n<p>&nbsp;<\/p>\n<p>&nbsp;<\/p>\n<p>&nbsp;<\/p>\n<p>&nbsp;<\/p>\n<p>&nbsp;<\/p>\n<p>&nbsp;<\/p>\n<p>&nbsp;<\/p>\n<p>&nbsp;<\/p>\n<p>&nbsp;<\/p>\n<p>&nbsp;<\/p>\n<p>&nbsp;<\/p>\n<p>&nbsp;<\/p>\n<h4>EXPLANATION<\/h4>\n<p>The core logic of generating the table is in the loadData() function. A single loop iterates through the invoice data and creates columns and rows to fill up the table. The first row is for the heading, so the loop runs from -1 instead of zero. The UI display of the header columns is slightly different than the data columns, which is why there is a check before creating the View for each column.<\/p>\n<p>For the Customer column we are using a LinearLayout comprising of two TextViews &#8211; one for the customer name and the second for the customer address. An alternative way would have been to do just use a single TextView and assign it both the name and addresses, separate by a newline character &#8220;\\r\\n&#8221;. In this case, however, we wanted the address to look different than the name, so its better to use a different View for the address.<\/p>\n<p>For each TableRow that is created, we add a click listener, so that you can detect when a column within a row has been tapped.<\/p>\n<p>We use another TableRow to act as a separator between two data TableRows. Note the use of the <em>span<\/em> property. We set it to the number of columns in the data TableRow as there is only one column being added to the separator TableRow.<\/p>\n<p>&nbsp;<\/p>\n<p>&nbsp;<\/p>\n<p>&nbsp;<\/p>\n","protected":false},"excerpt":{"rendered":"<div class=\"mh-excerpt\"><p>OVERVIEW Showing tabular data is a standard requirement in a lot of applications. The best way is to use a TableLayout, which will automatically arrange <a class=\"mh-excerpt-more\" href=\"https:\/\/truelogic.org\/wordpress\/2016\/05\/01\/showing-dynamic-data-in-a-tablelayout-in-android\/\" title=\"Showing dynamic data in a TableLayout in Android\">[&#8230;]<\/a><\/p>\n<\/div>","protected":false},"author":1,"featured_media":2659,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[295],"tags":[],"class_list":["post-2653","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-android-dev"],"_links":{"self":[{"href":"https:\/\/truelogic.org\/wordpress\/wp-json\/wp\/v2\/posts\/2653","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/truelogic.org\/wordpress\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/truelogic.org\/wordpress\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/truelogic.org\/wordpress\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/truelogic.org\/wordpress\/wp-json\/wp\/v2\/comments?post=2653"}],"version-history":[{"count":5,"href":"https:\/\/truelogic.org\/wordpress\/wp-json\/wp\/v2\/posts\/2653\/revisions"}],"predecessor-version":[{"id":3416,"href":"https:\/\/truelogic.org\/wordpress\/wp-json\/wp\/v2\/posts\/2653\/revisions\/3416"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/truelogic.org\/wordpress\/wp-json\/wp\/v2\/media\/2659"}],"wp:attachment":[{"href":"https:\/\/truelogic.org\/wordpress\/wp-json\/wp\/v2\/media?parent=2653"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/truelogic.org\/wordpress\/wp-json\/wp\/v2\/categories?post=2653"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/truelogic.org\/wordpress\/wp-json\/wp\/v2\/tags?post=2653"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}