android: two issues using Tablerow+TextView in Tablelayout - android

I am using Tablerow+TextView to make a simple view for blog posts and their replies. In each TableRow I put a TextView in. Now I have two issues:
The text which is longer than the screen won't automatically wrap up to be multi-line. Is it by design of TableRow? I've already set tr_content.setSingleLine(false); [update] This has been addressed, I think I should change Fill_parent to be Wrap_content in textView.tr_author_time.setLayoutParams(new LayoutParams(
LayoutParams.**WRAP_CONTENT**,
LayoutParams.WRAP_CONTENT));
The Table won't scroll like ListView. My rows are more than the screen size. I expect the table could be scrolled down for viewing just like ListView. Is that possible?
Here is my code:
TableLayout tl = (TableLayout) findViewById(R.id.article_content_table);
TextView tr_title = new TextView(this);
TextView tr_author_time = new TextView(this);
TextView tr_content = new TextView(this);
TableRow tr = new TableRow(this);
for(int i = 0; i < BlogPost.size(); i++){
try{
// add the author, time
tr = new TableRow(this);
/////////////////add author+time row
BlogPost article = mBlogPost.get(i);
tr_author_time = new TextView(this);
tr_author_time.setText(article.author+"("+
article.post_time+")");
tr_author_time.setTextColor(getResources().getColor(R.color.black));
tr_author_time.setGravity(0x03);
tr_author_time.setLayoutParams(new LayoutParams(
LayoutParams.FILL_PARENT,
LayoutParams.WRAP_CONTENT));
tr.addView(tr_author_time);
tl.addView(tr,new TableLayout.LayoutParams(
LayoutParams.FILL_PARENT,
LayoutParams.WRAP_CONTENT));
////////////////////// then add content row
tr = new TableRow(this);
tr_content = new TextView(this);
tr_content.setText(article.content);
tr_content.setSingleLine(false);
tr_content.setGravity(0x03);
tr_content.setLayoutParams(new LayoutParams(
LayoutParams.FILL_PARENT,
LayoutParams.WRAP_CONTENT));
tr.addView(tr_content);
tr.setBackgroundResource(R.color.white);
tl.addView(tr,new TableLayout.LayoutParams(
LayoutParams.FILL_PARENT,
LayoutParams.WRAP_CONTENT));
}

A more appropriate thing to do for wrapping items would have been to add android:shrinkColumns="*" or android:shrinkColumns="1" to the TableLayout, this would probably have fixed the wrapping issue.
For Details

This isn't really a complete answer, but it really seems like you're doing this the hard way.
Instead of constructing your TableRows manually, you should set them up in xml like this:
tablerow.xml:
<TableRow xmlns:android="http://schemas.android.com/apk/res/android">
<TextView android:id="#+id/content"
android:singleLine="false"
android:textAppearance="#style/someappearance" />
</TableRow>
Prior to your loop, get a reference to a LayoutInflater:
LayoutInflater inflater = getLayoutInflater();
Then, inside your loop, create an instance of tablerow using the LayoutInflater:
TableRow row = (TableRow)inflater.inflate(R.layout.tablerow, tl, false);
TextView content = (TextView)row.findViewById(R.id.content);
content.setText("this is the content");
tl.addView(row);
This will allow you to set your layout, appearance, layout params in xml making it much easier to read and debug.
For the scrolling problem, you'll need to add your TableLayout to a ScrollView. Something like this in your xml:
<ScrollView>
<TableLayout android:id="#+id/arcitle_content_table" />
</ScrollView>

To wrap text in table rows:
By default, TableLayout rows fit the width of their content, no matter it goes over the screen bounds. To get the wider-than-screen text cells to wrap to multi-line, use android:shrinkColumns attribute on TableLayout.
<TableLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:shrinkColumns="*" />
android:shrinkColumns is zero-based index of the columns to shrink. It removes unnecessary extra space from a column and shrinks it :
android:shrinkColumns="*" shrinks all columns
android:shrinkColumns="0" shrinks first column
android:shrinkColumns="1,2" shrinks the second and third columns
android:stretchColumns does the opposite. It stretches a column to the maximum available width.
Both "shrink" and "stretch" consider all rows of the table to compute space.
To scroll down a TableLayout:
If your TableLayout is higher than the screen, move it in a ScrollView.

Related

Android - How to design a view based on mockup

I am pretty new in Android, but I am an experienced developer.
I am trying to create a table that pretty much looks like this. The content is not important if you don't understand. I have pretty much solved it in the backend. I have retrieved the list and I have created TextViews for each of the columns.
I find it very difficult to design such a page in Android.
I have tried creating a dynamic TableLayout. I tried using a layout file first as a template, and add to it dynamically but nothing was displayed. I have also tried to do everything programatically, but I haven't gotten that to work either.
I would like the view to be Scrollable vertically, but before adding more features I wanted the view to work first.
I can show sample of the code.
My layout.xml file
<TableLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="#dimen/activity_vertical_margin"
android:paddingLeft="#dimen/activity_horizontal_margin"
android:paddingRight="#dimen/activity_horizontal_margin"
android:paddingTop="#dimen/activity_vertical_margin"
android:stretchColumns="0,1"
tools:context=".TeamReportDetailActivity"
android:id="#+id/reportDetailTableLayout">
</TableLayout>
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.layout_team_report_detail); //my layout.xml
//some code for getting the data from database
putInTableLayout(theData);
}
private void putInTableLayout(ReportDetail rd) {
TableLayout tl = (TableLayout) findViewById(R.id.reportDetailTableLayout);
int totalAttGained = 0;
for(int i = 0; i < mAllReports.size(); i++) {
ReportDTO report = mAllReports.get(i);
// Create a TableRow and give it an ID
TableRow tr = new TableRow(this);
tr.setLayoutParams(new LayoutParams(
LayoutParams.FILL_PARENT,
LayoutParams.WRAP_CONTENT));
tr.setId(1500+i);
if(report.role.equalsIgnoreCase(GOALKEEPER)) {
tr.setBackgroundColor(Color.BLUE);
} else if(report.role.equalsIgnoreCase(DEFENDER)) {
tr.setBackgroundColor(Color.GREEN);
} else if(report.role.equalsIgnoreCase(MIDFIELDER)) {
tr.setBackgroundColor(Color.GREEN);
} else if(report.role.equalsIgnoreCase(ATTACKER)) {
tr.setBackgroundColor(Color.RED);
}
TextView lblRole = new TextView(this);
lblRole.setId(200+i);
lblRole.setText(report.role);
lblRole.setTextColor(Color.WHITE);
lblRole.setLayoutParams(new LayoutParams(
LayoutParams.FILL_PARENT,
LayoutParams.WRAP_CONTENT));
tr.addView(lblRole);
//I add all these textviews and then finally I add it to the TableLayout
// Add the TableRow to the TableLayout
tl.addView(tr, new TableLayout.LayoutParams(
LayoutParams.FILL_PARENT,
LayoutParams.WRAP_CONTENT));
This code doesn't display anything. I would really appreciate help in designing a view that will display this table. Also, if anyone can suggest a good resource for learning how to design views in Android, that would be helpful.
Instead of a TableLayout you should use a more basic layout (possibly LinearLayout) with a ListView embedded within that layout. Once you have a ListView you can use an ArrayAdapter to populate the sub-views of that ListView. Take a look at the List View tutorial for more info.
Make sure you are using TableRow.LayoutParams for your TextView. In fact, you should just remove all the lines with LayoutParams and use the default, which is going to be match_parent width and wrap_content height for TableRow, and wrap_content width and wrap_content height for TextView.
To enable scrolling, wrap the whole TableLayout in a ScrollView in your xml, with match_parent height for the ScrollView and wrap_content height for the TableLayout, and match_parent width for both. As a side note, you'll need to add android:stretchColumns="*" to your TableLayout so it takes up the whole width.
ScrollView is good if you expect your table to have a page or two of data. Beyond that, you'll want to consider using a ListView. ListView recycles the visible views, swapping in new content as you scroll, so performance is better. The down side of ListView is that you will have to specify the widths of the columns explicitly if you want them to line up, while TableLayout will do that math for you.

Center checkbox programmatically?

I'm got a stretched table and I want my checkbox to appear central also within the table row. On the textView I've called:
myTextView.setGravity(Gravity.CENTER);
And I've also tried setting it as a table parameter:
This is my XML that sets up the table:
<TableLayout
android:id="#+id/info"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_below="#+id/linearLayout1"
android:layout_margin="6dp"
android:stretchColumns="0,1,2,3,4" >
<TableRow
android:id="#+id/tableRow1"
android:layout_width="wrap_content"
android:layout_height="fill_parent"
android:background="#drawable/roundedheader" >
And this is the code I'm calling as I create each row:
//set table margin
TableLayout.LayoutParams tableRowParams= new TableLayout.LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT);
int leftMargin=0,rightMargin=0,bottomMargin=0;
int topMargin=5;
tableRowParams.setMargins(leftMargin, topMargin, rightMargin, bottomMargin);
tableRowParams.gravity = Gravity.CENTER;
row.setLayoutParams(tableRowParams);
// add the TableRow to the TableLayout
table.addView(row);
However the same command doesn't have the desired effect on the checkbox. Does any know what the difference is and what I need to do. The checkbox isn't within any other layout its just in the table row.
I recommend you before start working with TableLayout to check these links:
http://developer.android.com/reference/android/widget/TableLayout.html
http://developer.android.com/reference/android/widget/TableRow.html
http://developer.android.com/reference/android/widget/TableRow.LayoutParams.html
Also there is bunch of examples how to work with TableLayout in API Demos from Android SDK.
Assuming your layout android:stretchColumns="0,1,2,3,4" you will have at least 5 columns, but from the code snippet I can't assume how many views are added to row. You will need to specify TableRow.LayoutParams android:layout_span if there are less view elements then columns and you want to use that free space. So assuming that you have only one CheckBox in a row and only 5 columns you will need to do next:
TableRow.LayoutParams rowParams = new TableRow.LayoutParams();
rowParams.gravity = Gravity.CENTER;
rowParams.span = 5;
checkBox.setLayoutParams(rowParams);
Also I recommend you to use xml layouts instead of creating them from the code. If you can't stick with xml layouts then at least create them using xml editor, so you will have good start point for creating them from the code.

Android: Tablerow multiline textview clipping vertically

I am dynamically adding rows with two columns to a table. One of the columns holds text that will spread across multiple lines. I've added the weight on the layout parameters for the textview so it no longer clipps outside of the screen, but it seems to be restricted to two and a half lines showing in the table, regardless of how long the multiline text is. The table is just defined in xml and everything else is done programmatically.
TableRow.LayoutParams rowParams = new TableRow.LayoutParams(TableRow.LayoutParams.FILL_PARENT, TableRow.LayoutParams.WRAP_CONTENT);
TableRow.LayoutParams paramsStar = new TableRow.LayoutParams(TableRow.LayoutParams.WRAP_CONTENT, TableRow.LayoutParams.WRAP_CONTENT);
paramsStar.setMargins(0,0,40,0);
TableRow.LayoutParams paramsText = new TableRow.LayoutParams(TableRow.LayoutParams.WRAP_CONTENT, TableRow.LayoutParams.FILL_PARENT, (float)1.0);
TableRow tr = new TableRow(this);
tr.setLayoutParams(rowParams);
TextView viewStar = new TextView(this);
viewStar.setTextSize((float) 30.0);
viewStar.setText("*");
viewStar.setLayoutParams(paramsStar);
viewStar.setTypeface(Typeface.DEFAULT_BOLD, 2);
TextView viewText = new TextView(this);
viewText.setText("Long multiline text piece"); //<--- Here the long text goes
viewText.setLayoutParams(paramsText);
tr.addView(viewStar);
tr.addView(viewText);
table.addView(tr, rowParams);
How do i fix this vertical clipping?
Screenshot of the problem below:
Here is the link showing the problem
I've found the root of the problem. The first column values textsize made the multiline text clip. If i reduce the textsize, the problem disappears.
I cant explain why though.
Another answer I'll drop in here: Android measures table row height in a very non-intuitive way. If you have 2 TextView(s), one for each column of a TableRow, you need to ensure that whatever top and bottom padding you've set for the first TextView is set identically for the 2nd TextView or you will get strange things like content clipping and weird positioning of the 2nd TextView.

TableLayout (TableRow?) not sizing child Views as expected when adding them dynamically

Context: I have a TableLayout (created using XML), which has one TableRow, which has one TextView. The code:
<ScrollView
xmlns:android="http://schemas.android.com/apk/res/android"
android:fillViewport="true"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
>
<TableLayout
android:id="#+id/mytable"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:stretchColumns="1"
>
<TableRow>
<TextView
android:id="#+id/add_alarm"
android:layout_weight="1"
android:layout_width="0dp"
android:layout_height="fill_parent"
android:gravity="center"
android:text="New\nItem"
android:textSize="30sp"
/>
</TableRow>
</TableLayout>
</ScrollView>
In my Activity's onCreate() method, I am trying to add another View to the TableRow dynamically. Here is the code:
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
LayoutInflater inflater = LayoutInflater.from(this);
View mainLayout = inflater.inflate(R.layout.main, null);
TableLayout tl = (TableLayout) mainLayout.findViewById(R.id.mytable);
TableRow tr = (TableRow) tl.getChildAt(0);
Log.d(TAG, "tr class = " + tr.getClass().getName() + " | width = " + tr.getWidth() + "\n");
final RelativeLayout rl = (RelativeLayout) inflater.inflate(R.layout.alarm_widget, null);
LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams(0, LinearLayout.LayoutParams.WRAP_CONTENT, 1);
tr.addView(rl, lp);
tl.invalidate();
setContentView(mainLayout);
}
Question: This code is not having the intended effect of displaying both the Views (the one in the XML layout already & the other added dynamically) in a columns of equal width.
With the code given above, the dynamically added View has a width of '0' and is therefore invisible.
If I change the code to tr.addView(rl) (i.e. without reference to LayoutParams), the dynamically added view is visible, but the columns are not equal in width.
How can I achieve this?
Edit: I changed the code based on the comments to the following. It still doesn't work as expected:
TableLayout.LayoutParams lp = new TableLayout.LayoutParams(TableLayout.LayoutParams.MATCH_PARENT,
TableLayout.LayoutParams.WRAP_CONTENT, 1f);
tr.addView(rl, lp);
The problem is this behavior defined for TableRow:
The children of a TableRow do not need to specify the layout_width and layout_height attributes in the XML file. TableRow always enforces those values to be respectively MATCH_PARENT and WRAP_CONTENT.
Rather than add your text views directly to the TableRow, have the TableRow hold a horizontal LinearLayout and add the second view to that holder.
(Also, using LinearLayout.LayoutParams for something that's going into a TableRow is wrong. You should have been using TableRow.LayoutParams. But that wouldn't be the way to get equal-width TextViews. Use a LinearLayout holder.)
I think it's not a good idea to dynamically add an item to a TableRow - it defeats the purpose of using a table. Imagine if you add an item to the first row of the table, but not on the second, meaning the first row has more elements. It wouldn't look much like a table.
But if you insist,
From developer guide:
The children of a TableRow do not need to specify the layout_width and layout_height attributes in the XML file. TableRow always enforces those values to be respectively MATCH_PARENT and WRAP_CONTENT.
You may need to start looking on the layout_weight of each element. Try adding layout_weight=1 on the row's static elements, and then setting your dynamic RelativeLayout's weight to 1 before adding it to the row.
rl.setLayoutParams(new LinearLayout.LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.WRAP_CONTENT, 1f));
The last parameter is weight.
Set height like this to the layout containing the ScrollView.
It solved my own problem where tablelayout does not show last lines.
android:layout_height="0dp"

What is the equivalent of "colspan" in an Android TableLayout?

I'm using a TableLayout in Android. Right now I have one TableRow with two items in it, and, below that, a TableRow with one item it it. It renders like this:
-----------------------------
| Cell 1 | Cell 2 |
-----------------------------
| Cell 3 |
---------------
What I want to do is make Cell 3 stretch across both upper cells, so it looks like this:
-----------------------------
| Cell 1 | Cell 2 |
-----------------------------
| Cell 3 |
-----------------------------
In HTML I'd use a COLSPAN.... how do I make this work in Android?
It seems that there is an attribute doing that :
layout_span
UPDATE:
This attribute must be applied to the children of the TableRow. NOT to the TableRow itself.
Just to complete the answer, the layout_span attribute must be added to the child, not to TableRow.
This snippet shows the third row of my tableLayout, which spans for 2 columns.
<TableLayout>
<TableRow
android:layout_width="wrap_content"
android:layout_height="wrap_content" >
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_span="2"
android:text="#string/create" />
</TableRow>
</TableLayout>
And this is how you do it programmatically
//theChild in this case is the child of TableRow
TableRow.LayoutParams params = (TableRow.LayoutParams) theChild.getLayoutParams();
params.span = 2; //amount of columns you will span
theChild.setLayoutParams(params);
You have to use layout_weight to fill the entire row otherwise it still fills left or right column of table layout.
<TableRow
android:id="#+id/tableRow1"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<Button
android:id="#+id/button1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_span="2"
android:layout_weight="1"
android:text="ClickMe" />
</TableRow>
Maybe this will help someone. I tried the solution with layout_span but this not working for me. So I solved the problem with this trick. Just use LinearLayout in place of TableRow where you need colspan, that's all.
use android:layout_span in child element of TableRow element
I've had some problem with rowspan, in case of TableRow, Textview and so on, generated with code. Even if Onimush answer seems to be good, it don't works with generated UI.
Here is a piece of code which.... don't work:
TableRow the_ligne_unidade = new TableRow(this);
the_ligne_unidade.setBackgroundColor(the_grey);
TextView my_unidade = new TextView(this);
my_unidade.setText(tsap_unidade_nom);
my_unidade.setTextSize(20);
my_unidade.setTypeface(null, Typeface.BOLD);
my_unidade.setVisibility(View.VISIBLE);
TableRow.LayoutParams the_param;
the_param = (TableRow.LayoutParams)my_unidade.getLayoutParams();
the_param.span = 3;
my_unidade.setLayoutParams(the_param);
// Put the TextView in the TableRow
the_ligne_unidade.addView(my_unidade);
The code seems to be OK but, when you reach the init of "the_params" it returns NULL.
On the other end, this code works like a charm:
TableRow the_ligne_unidade = new TableRow(this);
the_ligne_unidade.setBackgroundColor(the_grey);
TextView my_unidade = new TextView(this);
my_unidade.setText(tsap_unidade_nom);
my_unidade.setTextSize(20);
my_unidade.setTypeface(null, Typeface.BOLD);
my_unidade.setVisibility(View.VISIBLE);
// Put the TextView in the TableRow
the_ligne_unidade.addView(my_unidade);
// And now, we change the SPAN
TableRow.LayoutParams the_param;
the_param = (TableRow.LayoutParams)my_unidade.getLayoutParams();
the_param.span = 3;
my_unidade.setLayoutParams(the_param);
The only difference is that I push the Textview inside the TableRow before setting the span. And in this case, it works.
Hope this will help someone!
Actually It is pretty straight forward. This is my solution programmatically
TableLayout tableLayout = binding.tableLayout;
TableRow row = new TableRow(this);
TableRow.LayoutParams layoutParams = new TableRow.LayoutParams(TableRow.LayoutParams.WRAP_CONTENT);
layoutParams.span = 4; // define no. of column span will row do
row.setLayoutParams(layoutParams);
TextView noDataTextView = new TextView(this);
noDataTextView.setText("No Data");
noDataTextView.setGravity(Gravity.CENTER);
noDataTextView.setLayoutParams(layoutParams); //This line will span your row
row.addView(noDataTextView);
tableLayout.addView(row, 1);
I think you need to wrap a layout around another one.
Have one Layout list vertically, inside have another one (or in this case, two) list horizontally.
I'm still finding it hard to nicely split interface to 50-50 portion in Android.

Categories

Resources