The table I'm looking for has a number of rows, each of which has several columns which need to have their size automatically generated so that they display at the maximum width required to display them, and one of which needs to expand/contract to fill the remaining space.
I've tried to accomplish this by flagging the expanding/contracting column as shrinkable and stretchable. But this doesn't seem to work - when the table is wider than the available space, the column is not being shrunk, and instead the table is cut off on the right hand side, with several columns not visible.
Any pointers as to where I could be going wrong with this?
Recently I had to face a similar requirement for an app and I finally could get it working. In my case I needed to create one TableLayout and add TableRows dynamically depending on the screen's width. The Views added to the TableRow were TextViews with the layout_weight property set, so I had to play around with the number of items shown per row, and finally could tune up the desired layout.
I'll paste my code and explain what I'm doing at each step:
// The following code block is to dynamically get the width of the screen.
// The width param will be reachable within the `params.width` property
final Display display = getWindowManager().getDefaultDisplay();
final Point size = new Point();
display.getSize(size);
final WindowManager.LayoutParams params = getWindow().getAttributes();
// So now I have to take the TableLayout and add TableRows dynamically. I'll be adding
// TextViews to the row with the texts present at myItems
TableLayout myTableLayout = (TableLayout) findViewById(R.id.table_layout);
TableRow currentRow = new TableRow(this);
int currentWidth = 0;
for (final String item : myItems) {
// Define the TextView
final TextView tv = new TextView(this);
tv.setBackground(getResources().getDrawable(R.drawable.rounded_edges));
tv.setGravity(Gravity.CENTER);
tv.setText(item);
...
// This one line is very important, as you're defining the layout params.
// Make sure that you add the 1f parameter as it represents the weight
// Each TextView will have the same weight so they will have the same width
// within the row
tv.setLayoutParams(new TableRow.LayoutParams(TableRow.LayoutParams.MATCH_PARENT, TableRow.LayoutParams.WRAP_CONTENT, 1f));
...
// Now you check if this cell still fits the TableRow
// I use the 90% because the TableLayout won't ever be 100% of the screen width
if (currentWidth + tv.getWidth() < ((int) params.width * 0.9)) {
// It fits!
currentRow.addView(tv);
currentWidth = currentWidth + tv.getWidth();
}
else {
// It doesn't fit. Just add the current row to the TableLayout and go on.
myTableLayout.add(currentRow);
currentRow = new TableRow(this);
currentRow.addView(tv);
currentWidth = tv.getWidth();
}
}
// It might happen that once I've ended processing the texts, there's still
// a row pending to add, so if it has any child I add it
if (currentRow.getChildCount() > 0)
myTableLayout.add(currentRow);
You can try using the layout weight for the cells. Something like shown below
private static int COLUMN_WEIGHT_1 = 3;
private static int COLUMN_WEIGHT_2 = 1;
private static int COLUMN_WEIGHT_3 = 2;
// this column will stretch to fill the space
private static int COLUMN_WEIGHT_4 = 0;
private void populatePriceTable(){
TableLayout prices = (TableLayout)findViewById(R.id.pricetable);
prices.setStretchAllColumns(true);
prices.bringToFront();
TableRow tr = new TableRow(this);
TextView c1 = new TextView(this);
c1.setText("A cell");
TextView c2 = new TextView(this);
c2.setText("A large cell");
c2.setGravity(Gravity.CENTER_HORIZONTAL);
TextView c3 = new TextView(this);
c3.setText("Another large cell");
TextView c4 = new TextView(this);
c4.setGravity(Gravity.RIGHT);
c4.setText("Filler");
c1.setLayoutParams( new TableRow.LayoutParams( 0 , android.view.ViewGroup.LayoutParams.WRAP_CONTENT, COLUMN_WEIGHT_1) );
c2.setLayoutParams( new TableRow.LayoutParams( 0 , android.view.ViewGroup.LayoutParams.WRAP_CONTENT, COLUMN_WEIGHT_2) );
c3.setLayoutParams( new TableRow.LayoutParams( 0 , android.view.ViewGroup.LayoutParams.WRAP_CONTENT, COLUMN_WEIGHT_3) );
c4.setLayoutParams( new TableRow.LayoutParams( 0 , android.view.ViewGroup.LayoutParams.WRAP_CONTENT, COLUMN_WEIGHT_4) );
tr.addView(c1);
tr.addView(c2);
tr.addView(c3);
tr.addView(c4);
tr.setLayoutParams(new TableRow.LayoutParams(android.view.ViewGroup.LayoutParams.MATCH_PARENT, android.view.ViewGroup.LayoutParams.WRAP_CONTENT));
prices.addView(tr);
}
You can just have a ListView and have a seperate xml layout file which is actually a Table layout.
so as in listview you can handle as much rows you want and table layout will make it elastic.
Write Seperate XML layout for row like this....and use wrap content/fill parent attribute according to text size
<?xml version="1.0" encoding="utf-8"?>
<TableRow xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginBottom="3dp"
android:layout_marginTop="3dp"
android:background="#FFFFFF"
android:id="#+id/row_calender">
<TextView
android:id="#+id/tv_ac_sn"
android:layout_width="35dp"
android:layout_height="fill_parent"
android:background="#drawable/border"
android:gravity="center"
android:padding="5dp"
android:textColor="#000000" />
<TextView
android:id="#+id/tv_ac_day"
android:layout_width="85dp"
android:layout_height="fill_parent"
android:background="#drawable/border"
android:gravity="center"
android:padding="5dp"
android:textColor="#000000" />
<TextView
android:id="#+id/tv_ac_date"
android:layout_width="85dp"
android:layout_height="fill_parent"
android:background="#drawable/border"
android:gravity="center"
android:padding="5dp"
android:textColor="#000000" />
<TextView
android:id="#+id/tv_ac_event"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:background="#drawable/border"
android:gravity="center"
android:padding="5dp"`
android:textColor="#000000" />
</TableRow>
Related
Problem: I'm having difficulty getting an EditText field to fit within a table cell dimensions.
What I've tried: I have tried a number of suggestions, like below in my code, stated here on StackOverflow but nearly all are static and not dynamic examples. I looked at a couple videos which were about the same.
What I'm trying to do: I'm trying to give the user an option to add a row of data to a table and fill in the fields. The following code works out well except I cannot seem to find the correct way of stating the LayoutParams to fit the EditText within the cell boundaries.
for(int r=1; r<5;r++) {
EditText editText = new EditText(this);
editText.setBackgroundColor(Color.WHITE);
editText.setTextSize(12);
editText.setSingleLine();
editText.setLayoutParams(new TableRow.LayoutParams(TableRow.LayoutParams.WRAP_CONTENT,TableRow.LayoutParams.WRAP_CONTENT));
row.addView(editText);
}
<TableLayout
android:id="#+id/table_authors"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical"
android:background="#color/colorDkGray"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toBottomOf="#id/btn_add_author"
android:layout_marginTop="15dp"
android:layout_marginEnd="5dp"
android:layout_marginStart="5dp"/>
The code to setup table in the EditNote activity:
tableLayoutAuthors = findViewById(R.id.table_authors);
tableLayoutAuthors.addView(setupAuthorsTableRow("+", "Organization/First", "Middle Name", "Last Name","Suffix", true));
btnAddAuthor.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
tableLayoutAuthors.addView(setupAuthorsTableRow("-","", "", "", "", false));
}
});
You need to make few adjustments:
In the xml TableLayout add android:stretchColumns="*" which means that stretch all columns.
<TableLayout
android:id="#+id/table_authors"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="5dp"
android:layout_marginTop="15dp"
android:layout_marginEnd="5dp"
android:layout_marginBottom="716dp"
android:orientation="vertical"
android:stretchColumns="*"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
You need to set editText width to 0. Because with WRAP_CONTENT it respects the content width it has to wrap & not the cell boundaries.
This is how sample code would look like:
TableLayout tableLayoutAuthors = findViewById(R.id.table_authors);
TableRow row = new TableRow(this);
for (int r = 1; r < 5; r++) {
EditText editText = new EditText(this);
editText.setBackgroundColor(Color.WHITE);
editText.setTextSize(12);
editText.setText("test");
editText.setSingleLine();
editText.setLayoutParams(new TableRow.LayoutParams(0, TableRow.LayoutParams.WRAP_CONTENT));
row.addView(editText);
}
tableLayoutAuthors .addView(row);
With the help of Mayur Gajra, I was able to figure out how to fix my issue. Posted below is what fixed my issue:
Adding this line to the XML:
android:stretchColumns="*"
Changing to creating an instance of TableRow.LayoutParams and setting the margins and setting the padding for the editText:
for(int r=1; r<5;r++) {
EditText editText = new EditText(this);
// Change:
TableRow.LayoutParams trLayoutParams = new TableRow.LayoutParams();
trLayoutParams.setMargins(3,3,3,3);
editText.setLayoutParams(trLayoutParams);
editText.setBackgroundColor(Color.WHITE);
editText.setTextSize(12);
editText.setGravity(Gravity.CENTER);
editText.setSingleLine();
// Change:
editText.setPadding(8, 8, 8, 8);
row.addView(editText);
row.setClickable(true);
}
I want that the buttons had identical sizes and table was fully filled the buttons. But the buttons have a different size, what do I wrong in?
My xml:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:background="#drawable/background"
android:orientation="horizontal" >
<LinearLayout
</LinearLayout>
<TableLayout
android:id="#+id/mainTableL"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginBottom="40dp"
android:layout_marginRight="40dp"
android:layout_marginTop="40dp" >
</TableLayout>
</LinearLayout>
My code:
layoutParams = new TableRow.LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT, 1.0f);
mainTableLayout = (TableLayout) findViewById(R.id.mainTableL);
tableRow = new TableRow[VALUE_ROWS];
btn = new Button[VALUE_ROWS*VALUE_COLUMNS];
for (int indexRow = 0; indexRow < VALUE_ROWS; indexRow++){
tableRow[indexRow] = new TableRow(this);
tableRow[indexRow].setLayoutParams(new TableRow.LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT, 1.0f));
for (int indexColumn = 0; indexColumn < VALUE_COLUMNS; indexColumn++){
btn[countBtn] = new Button(this);
btn[countBtn].setLayoutParams(layoutParams);
btn[countBtn].setId(countBtn);
btn[countBtn].setBackgroundResource(R.drawable.fon);
tableRow[indexRow].addView(btn[countBtn],layoutParams);
countBtn++;
}
mainTableLayout.addView(tableRow[indexRow], layoutParams);
}
I am sorry for my pure english.
Thank you
I'm not sure if changing this will help you, but this definitely should be fixed. For table rows you should set TableLayout.LayoutParams instead of TableRow.LayoutParams:
tableRow[indexRow].setLayoutParams(new TableLayout.LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT, 1.0f));
and later when you add a row, don't specify layoutParams:
mainTableLayout.addView(tableRow[indexRow]);
Also note that specifying size for rows doesn't have any effect, their width is set to MATCH_PARENT and the height - to WRAP_CONTENT (see the doc). And similar with buttons, TableRow sets their width to WRAP_CONTENT and the height - to MATCH_PARENT regardless of what you specify in the layout params.
I have a TableLayout inside a HorizontalScrollView. When I add a single row of images, the images are side by side, no extra padding.
But when I add another row, and the images scale down, the TableLayout creates extra padding horizontally around each cell, but not vertically.
Here is my code:
TableLayout grid = (TableLayout) deckBuilder.findViewById(R.id.grid);
for (int j = 0; j < 3; ++j) {
TableRow testRow = new TableRow(this);
\\Each row has the same weight
testRow.setLayoutParams(new TableLayout.LayoutParams(TableLayout.LayoutParams.WRAP_CONTENT, TableLayout.LayoutParams.MATCH_PARENT, 1f));
for (int i = 0; i < 20; ++i) {
ImageView testImage = new ImageView(this);
testImage.setImageResource(R.test_image);
testRow.addView(testImage);
}
grid.addView(testRow);
}
And here is my xml:
<HorizontalScrollView
android:id="#+id/horizontalscroll"
android:layout_width="wrap_content"
android:layout_height="1dip"
android:scrollbars="none"
android:overScrollMode="never">
<TableLayout
android:id="#+id/grid"
android:layout_width="wrap_content"
android:layout_height="match_parent" >
</TableLayout>
</HorizontalScrollView>
Edit:
Sorry mis-read the code.
Solution:
set the width/height of your image views to wrap_content. You do this via the
LayoutParams object:
http://developer.android.com/reference/android/view/ViewGroup.LayoutParams.html
See this question for an example:
Show ImageView programmatically
//ImageView Setup
ImageView imageView = new ImageView(this);
//setting image resource
imageView.setImageResource(R.drawable.play);
//setting image position
imageView.setLayoutParams(new LayoutParams(
LayoutParams.MATCH_PARENT,
LayoutParams.WRAP_CONTENT));
Look at the docs here:
http://developer.android.com/reference/android/widget/ImageView.html
Specifically look at scaleType:
http://developer.android.com/reference/android/widget/ImageView.ScaleType.html
I think one of the options there should resolve this (maybe...fitXY?)
I am a bit confused about this. I have an app where user draws rectangular text objects. I added some textviews in a relative layout in my xml (lets say that I have a maximum of 3 text objects). The objects can be moved and resized. I added this code for each textView
TextView tv=(TextView) findViewById(R.id.text1);
RelativeLayout.LayoutParams lp = new RelativeLayout.LayoutParams(LayoutParams.FILL_PARENT,LayoutParams.FILL_PARENT);
System.out.println(texts.get(i).Sx+ " , "+texts.get(i).Sy+ " , "+ texts.get(i).Lx+ " , "+texts.get(i).Ly);
if(texts.get(i).Sx<=texts.get(i).Lx){
if(texts.get(i).Sy<=texts.get(i).Ly){
lp.setMargins((int)texts.get(i).Sx, (int)texts.get(i).Sy, (int)texts.get(i).Lx, (int)texts.get(i).Ly);
} else{
lp.setMargins((int)texts.get(i).Sx, (int)texts.get(i).Ly, (int)texts.get(i).Lx, (int)texts.get(i).Sy);
}
} else{
if(texts.get(i).Sy<=texts.get(i).Ly){
lp.setMargins((int)texts.get(i).Lx, (int)texts.get(i).Sy, (int)texts.get(i).Sx, (int)texts.get(i).Ly);
} else{
lp.setMargins((int)texts.get(i).Lx, (int)texts.get(i).Ly, (int)texts.get(i).Sx, (int)texts.get(i).Sy);
}
}
tv.setLayoutParams(lp);
tv.setWidth((int)(texts.get(i).width));
tv.setHeight((int)(texts.get(i).height));
tv.setTextSize(texts.get(i).textSize);
tv.setText(text.text);
tv.setTextColor(Color.WHITE);
tv.requestLayout();
Sx, Sy are the starting coos of the object in pixels and Lx, Ly the ending coos.
in the xml I added this:
<RelativeLayout
android:layout_height="fill_parent"
android:layout_width="fill_parent"
android:id="#+id/texts" >
<TextView
android:layout_height="fill_parent"
android:layout_width="fill_parent"
android:id="#+id/text1" />
<TextView
android:layout_height="fill_parent"
android:layout_width="fill_parent"
android:id="#+id/text2" />
<TextView
android:layout_height="fill_parent"
android:layout_width="fill_parent"
android:id="#+id/text3" />
</RelativeLayout>
This seems to work as for in placing the text in the right place. But the width and height of the textview does not seem to be right. Is this a problem of setting the margins in pixels? Some enlightenment would be very useful right now
LayoutParams are used to align your view dynamically. You can add rule to your params like below, above, bottom, top, align, margin and all(same like you do through xml) then finally you can set this layout params to your view. E.g :
// Set the params eg. for a button.
RelativeLayout.LayoutParams button_params = new RelativeLayout.LayoutParams(RelativeLayout
.LayoutParams.WRAP_CONTENT, RelativeLayout.LayoutParams.WRAP_CONTENT);
button_params.addRule(RelativeLayout.LEFT_OF,
any_view.getId());
button_params.addRule(RelativeLayout.ALIGN_PARENT_BOTTOM,
RelativeLayout.TRUE);
button_params.bottomMargin = screen_height / 15;
button_params.rightMargin = 20;
button.setLayoutParams(button_params);
You first set width/height to FILL_PARENT, then you overwrite it with px ?
try something like this
View temp = this.findViewById(recent);
RelativeLayout.LayoutParams relativeParams = (LayoutParams) temp.getLayoutParams();
relativeParams.setMargins(0, 0, 0, 50); // llp.setMargins(left, top, right, bottom);
relativeParams.width = 123;
relativeParams.height = 123;
temp.setLayoutParams(relativeParams);
I want to put one image on the beginning of each row in my application . The problem is that it shrinks the image too much . I want to make it occupy the whole space .
main.xml :
<?xml version="1.0" encoding="utf-8"?>
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent" android:layout_height="fill_parent"
android:scrollbars="vertical"
>
<TableLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:id="#+id/tableView"
android:layout_height="fill_parent"
android:layout_weight=".90"
android:stretchColumns="1"
></TableLayout>
</ScrollView>
This is how I add the image :
TableLayout tableView = (TableLayout) findViewById(R.id.tableView);
TableRow row = new TableRow(this);
ImageView im;
Bitmap bmp;
im = new ImageView(this);
bmp=getbmp(s);
im.setImageBitmap(bmp);
row.addView(im, new TableRow.LayoutParams(70, 30));
tableView.addView(row, new TableLayout.LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT));
If I change the parameters from TableRow.LayoutParams(70, 30)); the image stays the same , only the row gets bigger/smaller. Also , the image could get smaller if I make those parameters small enough but that is not what I want to do . I don't need necessarily the whole picture , a cropped zoomed in one that fills that space would be nice too . This is an example image from the website . If I put the image like this : row.addView(im); the image gets too big , and there is no more space for the text .
May be it's helpful to you
TableLayout tableView = (TableLayout) findViewById(R.id.tableView);
TableRow row = (TableRow) inflater.inflate(R.layout.tablerow, tableView, false);
ImageView imgDis = (ImageView) row.findViewById(R.id.spinnerEntryContactPhoto);
imgDis.setPadding(5, 5, 5, 5);
imgDis.setAdjustViewBounds(true);
// set row height width
TableRow.LayoutParams params = new TableRow.LayoutParams(TableRow.LayoutParams.FILL_PARENT, 50);
params.topMargin = 0;
params.bottomMargin = 0;
params.leftMargin = 0;
params.rightMargin = 0;
// If you want to set margin of row
tableView.addView(row, params);
tablerow.xml
<?xml version="1.0" encoding="utf-8"?>
<TableRow xmlns:android="http://schemas.android.com/apk/res/android">
<ImageView android:id="#+id/spinnerEntryContactPhoto"
android:layout_gravity="center_vertical"
android:layout_width="70dip"
android:layout_height="30dip"/>
</TableRow>