First off I am new to android development and some seemingly easy tasks are frustrating me to no end. This is a follow on question to what was answered here: Changing the checkbox size in Android 2.0
The gist of it is that for some reason there is this extra space that keeps showing up next to my checkboxes (See Below).
Now I have tried to set the width to 1 and it doesn't get any shorter than what is shown. I have tried to set the width bigger and I can make the size bigger, but no shorter.
Please take a look at the code below and let me know what you see.
TableLayout table = (TableLayout) findViewById(R.id.timeEntriesTable);
for (int i = 0; i < timeEntries.getLength(); i++)
{
Element element = (Element) timeEntries.item(i);
TableRow tr = new TableRow(this);
tr.setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT));
CheckBox box = new CheckBox(this);
box.setButtonDrawable(getResources().getDrawable(R.drawable.checkbox_off_background));
box.setPadding(0,0,0,0);
box.setWidth(1);
box.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
CheckBox box = (CheckBox) v;
if (box.isChecked())
{
box.setButtonDrawable(getResources().getDrawable(R.drawable.checkbox_on_background));
}
else
{
box.setButtonDrawable(getResources().getDrawable(R.drawable.checkbox_off_background));
}
}
});
TextView dateBox = new TextView(this);
String dateText = element.getAttribute("date");
dateBox.setText(dateText);
dateBox.setTextColor(Color.BLACK);
TextView customerBox = new TextView(this);
String customerName = element.getAttribute("customer");
customerBox.setText(customerName);
customerBox.setTextColor(Color.BLACK);
TextView hoursBox = new TextView(this);
String hours = element.getAttribute("hours");
hoursBox.setText(hours);
hoursBox.setTextColor(Color.BLACK);
TextView test = new TextView(this);
test.setTextColor(Color.RED);
test.setText("Test");
tr.addView(box);
tr.addView(dateBox);
tr.addView(customerBox);
tr.addView(hoursBox);
table.addView(tr, new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT));
}
Thank you in advance!
That looks suspiciously like the "Time Entries" header is in its own table cell in a header row and the column of checkboxes below it is matching the same width. (See how the right edge of the text lines up perfectly with the date below it?) Since the checkbox's layout_gravity is likely defaulting to TOP|LEFT, it's being positioned in the upper left of the cell.
Try altering either the header row or the layout_gravity of the checkboxes.
So after the input of the two other answerers #adamp and #Phobos. I stumbled across what worked for me.
How to set (Text)View attributes programmatically?
By adding this:
TableRow.LayoutParams lp = new TableRow.LayoutParams();
lp.width = 15;
lp.setMargins(3, 5, 0, 0);
lp.height = 15;
tr.addView(box, lp);
I was able to tweak that cell exactly how I wanted it. It was very strange to me that it wasn't growing the column of the cell it was growing the checkbox itself. This is because in Android there are no actual cells, it uses the views and their sizes to generate the table apparently.
I have came across no tutorials or anything that has you set the LayoutParams programmatically that way. Thank you for your help troubleshooting this!
Table Layouts naturally want to make all the cells the same size. If you want one, or more, to be different sizes then that takes additional parameters.
To shrink all the extra space in your cells add this to your table object
table.setShrinkAllColumns(true);
Or to just shrink the first column where your checkbox is
table.setColumnShrinkable(int columnIndex, boolean isShrinkable)
Related
I noticed, that a TextView with the same textSize can have a different height depending on the String it is displaying.
I disscovered it when paiting a simple TableLayout which has some TableRow items with some cells, each cell is a TextView.
Those cells doesn't have top margin, and they are being painted perfectly in Android 8.0 and upper devices, but in Android 7.0 and lower versions, some of the cells are adding a top margin between them, and this is because the height of the TextView is different. I can't understand how is that happening, it's very frustrating.
In this case, it's happening in the TextView called player and only when the name is too much long and it's using ellipsize to truncate it.
The code is very simple:
public void populateGoalscorersTable(ArrayList<Player> players){
goalscorersTableLayout.removeAllViews();
for (int i=0; i<players.size() && i<30; i++){
TableRow row = new TableRow(this);
row.setLayoutParams(goalscorersRowParams);
TextView position = new TextView(this);
position.setGravity(Gravity.CENTER);
position.setLayoutParams(goalscorersPositionParams);
position.setText(""+(i+1));
position.setBackgroundResource(R.drawable.table_cell_background);
position.setMinHeight((int) getResources().getDimension(R.dimen.cell_height));
row.addView(position);
TextView player = new TextView(this);
player.setGravity(Gravity.LEFT | Gravity.CENTER_VERTICAL);
player.setLayoutParams(goalscorersPlayerParams);
player.setText(players.get(i).getName());
player.setBackgroundResource(R.drawable.table_cell_background);
player.setMaxLines(1);
player.setEllipsize(TextUtils.TruncateAt.END);
player.setPadding((int) getResources().getDimension(R.dimen.spacing_small),0,(int) getResources().getDimension(R.dimen.spacing_small),0);
player.setMinHeight((int) getResources().getDimension(R.dimen.cell_height));
row.addView(player);
TextView team = new TextView(this);
team.setGravity(Gravity.LEFT | Gravity.CENTER_VERTICAL);
team.setLayoutParams(goalscorersTeamParams);
team.setText(players.get(i).getTeam().getName());
team.setBackgroundResource(R.drawable.table_cell_background);
team.setMaxLines(1);
team.setEllipsize(TextUtils.TruncateAt.END);
team.setPadding((int) getResources().getDimension(R.dimen.spacing_small),0, (int) getResources().getDimension(R.dimen.spacing_small),0);
team.setMinHeight((int) getResources().getDimension(R.dimen.cell_height));
row.addView(team);
TextView goals = new TextView(this);
goals.setGravity(Gravity.CENTER);
goals.setLayoutParams(goalscorersPositionParams);
goals.setText(""+players.get(i).getLeagueGoals());
goals.setBackgroundResource(R.drawable.table_cell_background);
goals.setMinHeight((int) getResources().getDimension(R.dimen.cell_height));
row.addView(goals);
if (players.get(i).getTeam() == Manager.getInstance().getTeam()){
player.setTextColor(getResources().getColor(R.color.player_team));
player.setTypeface(null, Typeface.BOLD);
team.setTextColor(getResources().getColor(R.color.player_team));
team.setTypeface(null, Typeface.BOLD);
}
goalscorersTableLayout.addView(row);
}
}
It's not the only way to make this errorneal top margin appearing (caused by a incorrect text height), I can see it for example when i have a row whith TextView cells with only one character and others with more than one character. The TextViews with more characters get's the margin. Also i can see this error happening when some TextViews are aligned to left and others centered. Very frustrating.
How can this be avoided?
If the font is not monospaced, different text can have different sizes and needs of space for letters that venture down the line such as j or p or q.
I want to insert a few LinearLayouts, but it doesn't work like it should. It inserts just one, but it should insert more.
LinearLayout commentsContainer = (LinearLayout) findViewById(R.id.view_comment_container);
commentsContainer.setLayoutParams(new LinearLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT));
commentsContainer.setOrientation(LinearLayout.HORIZONTAL);
for (int i = 0; i < postView.commentLenght(); i++) {
Log.e("LENGTH", postView.commentLenght()+"x"+i);
LinearLayout commentContainer = new LinearLayout(PostViewActivity.this);
commentContainer.setLayoutParams(new LinearLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT));
LinearLayout userContainer = new LinearLayout(PostViewActivity.this);
userContainer.setLayoutParams(new LinearLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT));
userContainer.setOrientation(LinearLayout.VERTICAL);
commentContainer.setOrientation(LinearLayout.HORIZONTAL);
commentContainer.setPadding(25,0,0,0);
ImageView commentImage = new ImageView(PostViewActivity.this);
commentImage.setLayoutParams(new LinearLayout.LayoutParams((int) ((float) width / 6), (int) ((float) width / 6)));
commentImage.setImageBitmap(postView.getComment(i).getImage());
TextView commentText = new TextView(PostViewActivity.this);
commentText.setLayoutParams(new LinearLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT));
commentText.setText(postView.getComment(i).getText());
TextView displayUserText = new TextView(PostViewActivity.this);
displayUserText.setLayoutParams(new LinearLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT));
displayUserText.setText(postView.getComment(i).getDisplayName());
Log.d("TEXT", postView.getComment(i).getText());
Log.e("TEXT", displayUserText.getText()+"");
displayUserText.setTag(postView.getComment(i).getUsername());
displayUserText.setTextSize(12);
displayUserText.setTextColor(getResources().getColor(R.color.colorAccent));
userContainer.addView(commentImage);
userContainer.addView(displayUserText);
commentContainer.addView(userContainer);
commentContainer.addView(commentText);
commentsContainer.addView(commentContainer);
}
Another strange thing: the first Log.d is always the correct one, but the second one is always the same. What's the mistake?
This code can be greatly cleaned up by using XML resource files. As each of the comments takes the same form, the same layout can be used for each. You can fill different values into the layout as you desire. These can all be added to a ViewGroup within another layout.
Programmatically generating layouts is much more error prone and complex than using an XML layout.
Doing some reading into the Android official documentation is absolutely worth it! https://developer.android.com/guide/topics/ui/declaring-layout.html
I'm creating a TableLayout programmatically. A table row can consist of an amount + unit (cell 1), and ingredient (cell 2) and a delete button (cell 3).
The ingredients can be longer than the available width, so I used the weight attribute and set it to 1 to enable a line break:
setLayoutParams(new TableRow.LayoutParams(0, TableRow.LayoutParams.WRAP_CONTENT, 1f));
This works.
The problem is that the delete button prevents the table row to increase the height, so it is partly hidden which looks like this:
This is the important part of the code that produces one table row:
final TableRow tableRow = new TableRow(getApplicationContext());
tableRow.setTag(INGREDIENT_ENTRY);
tableRow.setLayoutParams(new TableLayout.LayoutParams(TableLayout.LayoutParams.MATCH_PARENT, TableLayout.LayoutParams.WRAP_CONTENT));
// Amount and unit
int dp6InPixel = PixelCalculator.convertDpToPixel(getApplicationContext(), 6);
TextView tvAmountAndUnitText = new TextView(getApplicationContext());
tvAmountAndUnitText.setLayoutParams(new TableRow.LayoutParams(TableRow.LayoutParams.WRAP_CONTENT, TableRow.LayoutParams.WRAP_CONTENT));
tvAmountAndUnitText.setText(strAmount + " " + strUnit);
tvAmountAndUnitText.setTextColor(ContextCompat.getColor(getApplicationContext(), R.color.black));
tvAmountAndUnitText.setTextSize(TypedValue.COMPLEX_UNIT_SP, 16f);
tvAmountAndUnitText.setGravity(Gravity.RIGHT);
tvAmountAndUnitText.setTypeface(tvAmountAndUnitText.getTypeface(), Typeface.BOLD);
tvAmountAndUnitText.setPadding(dp6InPixel, 0, dp6InPixel, 0);
tableRow.addView(tvAmountAndUnitText);
// Ingredient
TextView tvIngredientText = new TextView(getApplicationContext());
tvIngredientText.setLayoutParams(new TableRow.LayoutParams(0, TableRow.LayoutParams.WRAP_CONTENT, 1f));
tvIngredientText.setText(strIngredient);
tvIngredientText.setTextColor(ContextCompat.getColor(getApplicationContext(), R.color.black));
tvIngredientText.setTextSize(TypedValue.COMPLEX_UNIT_SP, 16f);
tableRow.addView(tvIngredientText);
// Button
int dp10InPixel = PixelCalculator.convertDpToPixel(getApplicationContext(), 10);
TextView tvIngredientDeleteButton = new TextView(getApplicationContext());
LayoutParams buttonParams = new TableRow.LayoutParams(TableRow.LayoutParams.WRAP_CONTENT, TableRow.LayoutParams.WRAP_CONTENT);
buttonParams.setMargins(dp10InPixel, 0, 0, 0);
tvIngredientDeleteButton.setLayoutParams(buttonParams);
tvIngredientDeleteButton.setTextColor(ContextCompat.getColor(getApplicationContext(), R.color.black));
tvIngredientDeleteButton.setBackgroundColor(ContextCompat.getColor(getApplicationContext(), R.color.lightred));
tvIngredientDeleteButton.setTextSize(TypedValue.COMPLEX_UNIT_SP, 20f);
tvIngredientDeleteButton.setPadding(dp6InPixel, dp6InPixel, dp6InPixel, dp6InPixel);
tvIngredientDeleteButton.setText("x");
//more code
tableRow.addView(tvIngredientDeleteButton);
ingredientTable.addView(tableRow);
When I set tvIngredientDeleteButton.setMinLines(2);, then I can see the full ingredient cell. Unfortunately all rows have a min height of 2 then which looks ugly. I need some way to recognize if the ingredient cell has a line break and set minLines for that case or any other good solution (but I will not count ingredient characters or something. I guess this can be solved with some table attributes or similar). Any ideas how to solve this problem?
TableRow is direct subclass of LinearLayout. And inorder to set how child views are positioned in it, you need to define it's gravity. Default value is TOP, and I've tried with FILL, CENTER_VERTICAL etc. So any value of setGravity() other than TOP will render TextView with full content. Please refer official document, for more detail.
So you just need to add one statement at a time of declaration of TableRow to achieve your requirement.
tableRow.setGravity(Gravity.FILL);
I want to place Check-boxes next to each other dynamically in android and when the width is over then the check boxes need to be aligned from the next line.
I have number of check-boxes which are initializing in an array. I have used the following code. It correctly place only one check-box. Other one gets placed in between. I have used the following code.
LinearLayout layout = (LinearLayout)findViewById(R.id.linearLayout_symptoms_checkboxes);
RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(LayoutParams.WRAP_CONTENT,LayoutParams.WRAP_CONTENT);;
params.setMargins(0, 10, 0, 0);
for(int i = 0; i < arraySymptoms.length; i++) {
CheckBox cb = new CheckBox(getApplicationContext());
cb.setText(arraySymptoms[i]);
cb.setId(i);
if(i==0)
{
cb.setLayoutParams(params);
layout.addView(cb);
}
else
{
params.addRule(RelativeLayout.ALIGN_RIGHT, i-1);
cb.setLayoutParams(params);
layout.addView(cb);
}
}
Please guide me through this. Your help will be greatly appreciated. Thank you in advance people :)
Just use LinearLayout with horizontal orientation instead of RelativeLayout
I tried to use below code, but the textviews do not change line after it reach the end of screen.
RelativeLayout ll = (RelativeLayout)findViewById(R.id.viewObj);
int lastid=0;
for (int i=0; i<100; i++) {
String teststr = " hello ";
TextView textView2 = new TextView(this);
textView2.setId(i+1);
textView2.setTextSize(30);
textView2.setBackgroundColor(Color.GREEN);
textView2.setTextColor(Color.RED);
textView2.setTypeface(Typeface.MONOSPACE);
textView2.setText(teststr+String.valueOf(i));
if (i>0)
{
RelativeLayout.LayoutParams lay = new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.WRAP_CONTENT, RelativeLayout.LayoutParams.WRAP_CONTENT);
lay.addRule(RelativeLayout.RIGHT_OF, lastid);
ll.addView(textView2, lay);
} else {
ll.addView(textView2);
};
lastid = textView2.getId();
}
However, I dont know how to determine when to change line. I just keep on putting new textview to the right of the last one created. Can anyone tell me the correct logic to do the task? many thanks.
Easy fix. Switch to a dynamically-created LinearLayout, and set its orientation to vertical:
lay.setOrientation(LinearLayout.VERTICAL);