Programmatically adding TextView to Grid Layout alignment not proper - android

Hi i am trying to add TextView with drawableLeft to GridLayout.
I am adding this TextView in an Loop. The TextView are getting added properly but the are not aligned properly. Each textview should take equal width in one horizontal row which is not happening.
Following is the code i am using
GridLayout gridLayout = new GridLayout(getContext());
gridLayout.setAlignmentMode(GridLayout.ALIGN_BOUNDS);
gridLayout.setColumnCount(2);
gridLayout.setRowCount(3);
TextView titleText;
for (int i = 0; facilities != null && i < facilities.size(); i++) {
titleText = new TextView(getContext());
titleText.setText(facilities.get(i));
gridLayout.addView(titleText, i);
titleText.setCompoundDrawablesWithIntrinsicBounds(rightIc, 0, 0, 0);
}

For this you have to dynamically set the column width for the views. This will finally align each view properly with equal amount of space.
GridLayout gridLayout = new GridLayout(getContext());
gridLayout.setAlignmentMode(GridLayout.ALIGN_BOUNDS);
gridLayout.setColumnCount(2);
gridLayout.setRowCount(3);
TextView titleText;
for (int i = 0; facilities != null && i < facilities.size(); i++) {
titleText = new TextView(getContext());
titleText.setText(facilities.get(i));
gridLayout.addView(titleText, i);
titleText.setCompoundDrawablesWithIntrinsicBounds(rightIc, 0, 0, 0);
GridLayout.LayoutParams param =new GridLayout.LayoutParams();
param.height = LayoutParams.WRAP_CONTENT;
param.width = LayoutParams.WRAP_CONTENT;
param.rightMargin = 5;
param.topMargin = 5;
param.setGravity(Gravity.CENTER);
param.columnSpec = GridLayout.spec(c);
param.rowSpec = GridLayout.spec(r);
titleText.setLayoutParams (param);
}

The following code sample should give each text view equal height and width, and order the TextViews left-to-right and then top-to-bottom.
The critical part is explicitly providing the GridLayout.LayoutParams, setting height/width to 0 and defining the row/column specs with weights set to 1 so that the height and width will be automatically calculated based on the weights.
Also notice I set the number of rows as a function of the number of facilities, so that if your list grows you'll have more rows.
if (facilities == null) {
// In this case there is nothing to display. You can adjust this part to your needs.
return;
}
GridLayout gridLayout = new GridLayout(getContext());
gridLayout.setAlignmentMode(GridLayout.ALIGN_BOUNDS);
gridLayout.setColumnCount(2);
gridLayout.setRowCount(facilities.size() / 2);
for (int i = 0; i < facilities.size(); i++) {
TextView titleText = new TextView(getContext());
titleText.setText(facilities.get(i));
titleText.setCompoundDrawablesWithIntrinsicBounds(rightIc, 0, 0, 0);
GridLayout.LayoutParams layoutParams = new GridLayout.LayoutParams();
layoutParams.height = 0;
layoutParams.width = 0;
int currentCol = i % 2;
int currentRow = i / 2;
// The last parameter in the specs is the weight, which gives equal size to the cells
layoutParams.columnSpec = GridLayout.spec(currentCol, 1, 1);
layoutParams.rowSpec = GridLayout.spec(currentRow, 1, 1);
// Optional, if you want the text to be centered within the cell
layoutParams.setGravity(Gravity.CENTER);
gridLayout.addView(titleText, layoutParams);
}

Basically that is the column and row count. I have re wrotten the complete logic
GridLayout gridLayout = new GridLayout(getContext());
int total = facilities.size();
int column = 2;
int row = total / column;
gridLayout.setAlignmentMode(GridLayout.ALIGN_BOUNDS);
gridLayout.setColumnCount(column);
gridLayout.setRowCount(row + 1);
TextView titleText;
for(int i =0, c = 0, r = 0; i < total; i++, c++)
{
if(c == column)
{
c = 0;
r++;
}
titleText = new TextView(getContext());
titleText.setText(facilities.get(i));
gridLayout.addView(titleText, i);
titleText.setCompoundDrawablesWithIntrinsicBounds(rightIc, 0, 0, 0);
GridLayout.LayoutParams param =new GridLayout.LayoutParams();
param.height = LayoutParams.WRAP_CONTENT;
param.width = LayoutParams.WRAP_CONTENT;
param.rightMargin = 5;
param.topMargin = 5;
param.setGravity(Gravity.CENTER);
param.columnSpec = GridLayout.spec(c);
param.rowSpec = GridLayout.spec(r);
titleText.setLayoutParams (param);
}

That's may be because of your dynamic text length is not fixed so each textview not take same space Check this
int height=getContext().getResources().getDimension(R.dimen.activity_horizontal_margin); //set size of dimen in required resolution
titleText .setLayoutParams(new LinearLayout.LayoutParams(0, height, height));

My solution:
GridLayout gl = findViewById( R.id.grid_layout );
TextView tv = new TextView( this );
tv.setText( ""+cursor.getInt( column ) ); //for example
GridLayout.LayoutParams lp = new GridLayout.LayoutParams();
lp.columnSpec = GridLayout.spec( GridLayout.UNDEFINED, 1, GridLayout.FILL ); //for stretch a child to column use GridLayout.FILL
gl.addView( tv, lp );
//DO NOT USE lp.setGravity( ... );
//FOR ALIGN TEXT USE tv.setTextAlignment( ... );

Related

Android Create multiple ImageViews in a loop ... strange behavior

I am creating multiple ImageViews dynamiclly in a loop.
Every ImageView has a different position and a different image.
Finally i add them to a FrameLayout.
FrameLayout.LayoutParams params = new FrameLayout.LayoutParams(container.getWidth() / 3, container.getHeight() / 3);
ImageView imageView;
for(int i=0; i<cloths.size(); i++) {
imageView = new ImageView(getActivity(), null);
imageView.setAdjustViewBounds(true);
Glide.with(getActivity()).load(cloths.get(i).getImage()).into(imageView);
imageView.setOnTouchListener(touchListener);
params.leftMargin = (int) cloths.get(i).getxPos(container.getWidth());
params.topMargin = (int) cloths.get(i).getyPos(container.getHeight());
params.rightMargin = 0;
params.bottomMargin = 0;
imageView.setScaleY(cloths.get(i).getScale());
imageView.setScaleX(cloths.get(i).getScale());
container.addView(imageView, params);
}
Instead of positioning all imageviews correctly, they are all laying on top of each other at on the position of the last imageview.
Any ideas how to fix it ?
What am i doing wrong ?
Assuming you know the desired position and size (getyPos() suggest you do), you can try aggregating all the sizes so the images will go one over the other. If you don't know the sizes, you can use Glide to help you find them (or just measure the views after the image arrives).
public void putImages(FrameLayout container){
FrameLayout.LayoutParams params = new FrameLayout.LayoutParams(container.getWidth() / 3, container.getHeight() / 3);
int topMargin = 0;
for(int i=0; i<cloths.size(); i++) {
ImageView imageView = new ImageView(getActivity(), null);
imageView.setAdjustViewBounds(true);
Glide.with(getActivity()).load(cloths.get(i).getImage()).into(imageView);
imageView.setOnTouchListener(touchListener);
params.leftMargin = (int) cloths.get(i).getxPos(container.getWidth());
params.topMargin = topMargin;
params.rightMargin = 0;
params.bottomMargin = 0;
topMargin += (int) cloths.get(i).getyPos(container.getHeight());
imageView.setScaleY(cloths.get(i).getScale());
imageView.setScaleX(cloths.get(i).getScale());
container.addView(imageView, params);
}
}

How to make LinearLayout height to be the highest height of it's child component?

I add two Checkboxes dynamically to a Linearlayout. Then those Linearlayouts are added one after another in a Relativelayout. The weights of the checkboxes are set so that each take 50% of the Linearlayout width. Now, if their heights do not match, the bottom of the checkbox with bigger height disappears. How to solve this? Here's a screenshot:
And the code:
LinearLayout ll;
LinearLayout.LayoutParams lp;
CheckBox ch;
int id = 1200, i, j;
for (i = 0, j = 0; i < selections.size() - 1; i += 2, j += 2) {
ll = new LinearLayout(NotificationSettings.this);
lp = new LinearLayout.LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT);
ch = new CheckBox(NotificationSettings.this);
lp.weight = 1.0f;
ch.setLayoutParams(lp);
ch.setText(selections.get(i));
ch.setChecked(isSelected);
ch.setTextColor(color);
ch.setId(j);
ll.addView(ch);
ch = new CheckBox(NotificationSettings.this);
ch.setLayoutParams(lp);
ch.setText(selections.get(i + 1));
ch.setChecked(isSelected);
ch.setTextColor(color);
ch.setId(j + 1);
ll.addView(ch);
RelativeLayout.LayoutParams p = new RelativeLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT);
if (id == 1200)
p.addRule(RelativeLayout.BELOW, addBelow);
else
p.addRule(RelativeLayout.BELOW, id);
ll.setLayoutParams(p);
ll.setId(++id);
rl.addView(ll);
}
Edit:
When both checkboxes have multiple lines:
Can you make sure that the Linear Layout's height below it is not too large that it covers the above Linear Layout?
Or try changing your Relative Layout Params' height to WRAP_CONTENT
Change
RelativeLayout.LayoutParams p = new RelativeLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT);
To
RelativeLayout.LayoutParams p = new RelativeLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);

How to set multiple textviews with ellipsize only on some of them

I have a little complicated layout I want to make in my ListView adpater.
Each item in the list is combined of 4 TextView
The first three TextView are basically one sentence, but I want the second TextView not to be ellipsized, and the first and the third I do want to be ellipsized.
The last TextView is need to be positioned to the right side.
so if the all the first three TextView can't be shown completely, the layout should be like this:
`TextView1...` `TextView2` `TextView3...` `TextView4`
My code is working in this case, but in simple case when no ellipsize is necessary, it doesn't and it looks like this:
`TextView1` `TextView2` `TextView3` `TextView4`
Here's my code:
LinearLayout layout = new LinearLayout(m_context);
layout.setGravity(Gravity.CENTER_VERTICAL);
layout.setOrientation(LinearLayout.HORIZONTAL);
layout.setLayoutParams(new ListView.LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.WRAP_CONTENT));
LinearLayout textLayout = new LinearLayout(m_context);
textLayout.setOrientation(LinearLayout.HORIZONTAL);
textLayout.setGravity(Gravity.CENTER_VERTICAL);
view.m_text1 = new TQTextView(m_context);
view.m_text1.setSingleLine();
view.m_text1.setEllipsize(TruncateAt.END);
view.m_text2 = new TQTextView(m_context);
view.m_text3 = new TQTextView(m_context);
view.m_text3.setSingleLine();
view.m_text3.setEllipsize(TruncateAt.END);
view.m_text1 = new TQTextView(m_context);
textLayout.setWeightSum(2f);
textLayout.addView(view.m_text1, new LinearLayout.LayoutParams(0, LayoutParams.WRAP_CONTENT, 1f));
textLayout.addView(view.m_text2, new LinearLayout.LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT, 0f));
textLayout.addView(view.m_text3, new LinearLayout.LayoutParams(0, LayoutParams.WRAP_CONTENT, 1f));
layout.addView(textLayout, new LinearLayout.LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.WRAP_CONTENT, 1f));
view.m_text4 = new TQTextView(m_context);
LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT, 0f);
int margin = 10;
params.leftMargin = margin;
params.gravity = Gravity.CENTER_VERTICAL|Gravity.RIGHT;
layout.addView(view.m_text4, params);
I found a solution:
I add the three TextView without special LayoutParams like this:
textLayout.addView(view.m_attackeeName);
textLayout.addView(view.m_text);
textLayout.addView(view.m_attackerName);
and I call the following function in the end of getView function (after setting the texts)
private void updateTexts(View parent, ViewHolder view, Data data){
view.m_text1.measure(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
view.m_text3.measure(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
view.m_text2.measure(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
view.m_text4.measure(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
int totalWidth = parent.getWidth() - parent.getPaddingLeft() - parent.getPaddingRight();
totalWidth = totalWidth - view.m_text4.getMeasuredWidth() - view.m_text2.getMeasuredWidth() - m_margin;
int attackerTextWidth = view.m_text1.getMeasuredWidth();
int attackeeTextWidth = view.m_text3.getMeasuredWidth();
if( attackerTextWidth + attackeeTextWidth > totalWidth )
{
int spareWidth = totalWidth / 2 - attackerTextWidth;
if( spareWidth > 0 )
{
attackeeTextWidth = totalWidth / 2 + spareWidth;
}
else
{
spareWidth = totalWidth / 2 - attackeeTextWidth;
if( spareWidth > 0 )
{
attackerTextWidth = totalWidth / 2 + spareWidth;
}
else
{
attackerTextWidth = totalWidth / 2;
attackeeTextWidth = totalWidth / 2;
}
}
}
String text = TextUtils.ellipsize(data.GetText1(), view.m_text1.getPaint(),
attackerTextWidth, TextUtils.TruncateAt.END).toString();
view.m_text1.setText(text);
text = TextUtils.ellipsize(data.GetText3(), view.m_text3.getPaint(),
attackeeTextWidth, TextUtils.TruncateAt.END).toString();
view.m_text3.setText(text);
}

Dynamic GridLayout [duplicate]

This question already has answers here:
GridLayout (not GridView) how to stretch all children evenly
(25 answers)
Closed 7 months ago.
I made an error in another class, that's why it didn't work. The code below seems to be correct
I'm trying to create a dynamic GridLayout. Inside another class, not this one, I have a method that designs rows and cols of my gridlayout. In the class below, i add some buttons to my GridLayout:
int buttons= 6;//the number of bottons i have to put in GridLayout
int buttonsForEveryRow = 3; // buttons i can put inside every single row
int buttonsForEveryRowAlreadyAddedInTheRow =0; // count the buttons added in a single rows
int columnIndex=0; //cols index to which i add the button
int rowIndex=0; //row index to which i add the button
for(int i=0; i < buttons;i++){
/*if numeroBottoniPerRigaInseriti equals numeroBottoniPerRiga i have to put the other buttons in a new row*/
if(buttonsForEveryRowAlreadyAddedInTheRow ==buttonsForEveryRow ){
rowIndex++; //here i increase the row index
buttonsForEveryRowAlreadyAddedInTheRow =0;
columnIndex=0;
}
Spec row = GridLayout.spec(rowIndex, 1);
Spec colspan = GridLayout.spec(columnIndex, 1);
GridLayout.LayoutParams gridLayoutParam = new GridLayout.LayoutParams(row, colspan);
gridLayout.addView(button_to_add,gridLayoutParam);
buttonsForEveryRowAlreadyAddedInTheRow ++;
columnIndex++;
In the following image you can see what i get: Buttons 3 and 6 are missing. I'm afraid I am not using GridLayout.spec properly.
Using below code you can add image views to grid layout dynamically with column span and row span.
gridLayout = (GridLayout) findViewById(R.id.gridview);
gridLayout.removeAllViews();
int total = 10;
int column = 3;
int row = total / column;
gridLayout.setColumnCount(column);
gridLayout.setRowCount(row + 1);
for (int i = 0, c = 0, r = 0; i < total; i++, c++) {
if (c == column) {
c = 0;
r++;
}
ImageView oImageView = new ImageView(this);
oImageView.setImageResource(R.drawable.ic_launcher);
oImageView.setLayoutParams(new LayoutParams(100, 100));
Spec rowSpan = GridLayout.spec(GridLayout.UNDEFINED, 1);
Spec colspan = GridLayout.spec(GridLayout.UNDEFINED, 1);
if (r == 0 && c == 0) {
Log.e("", "spec");
colspan = GridLayout.spec(GridLayout.UNDEFINED, 2);
rowSpan = GridLayout.spec(GridLayout.UNDEFINED, 2);
}
GridLayout.LayoutParams gridParam = new GridLayout.LayoutParams(
rowSpan, colspan);
gridLayout.addView(oImageView, gridParam);
}

Adding an ImageView array to a RelativeLayout

I am trying to add a series of images to the current RelativeLayout at runtime below another TextView. So far, I get it to display partially correct, but not exactly right. I can't get them to move to another row. I hope someone can give me a hand and show me the correct way. The series of image will appear below this TextView(R.id.date):
TextView date = (TextView) findViewById(R.id.date);
//// image view start //////
int photos = Integer.parseInt(total_photo);
RelativeLayout mainLayout = (RelativeLayout) findViewById(R.id.relative_layout_b);
for (int i = 0; i < limit; i++){
final ImageView imageView = new ImageView (this);
imageView.setId(i);
imageView.setImageResource(R.drawable.photo_frame);
RelativeLayout.LayoutParams lp = new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.WRAP_CONTENT, RelativeLayout.LayoutParams.WRAP_CONTENT);
imageView.setPadding(10, 10, 0, 0);
imageView.setAdjustViewBounds(true);
imageView.setMaxHeight(80);
imageView.setMaxWidth(80);
lp.addRule(RelativeLayout.BELOW, R.id.date);
lp.addRule(RelativeLayout.RIGHT_OF, imageView.getId() - 1);
imageView.setLayoutParams(lp);
mainLayout.addView(imageView);
}
Right now, it only display total photo quantity - 1 (i.e.: when there is 5, it only display 4); and I would like to get each row to display 5 and will move to the next row immediately if it reach 6, 11, 16....etc. This layout is nested inside a ScrollView and in a RelativeLayout because I have quite a few views in it. So, I will have to stick with RelativeLayout for this.
If I understood what you're trying to do, see if the code below position the ImageViews like you want(I don't know how efficient it is):
private static final int ROW_ITEMS = 5; // 5 ImageViews per row
// ...
RelativeLayout mainLayout = (RelativeLayout) findViewById(R.id.relative_layout_b);
int limit = 13; // I assume that limit is the number of ImageView that you'll put in the layout
int rows = limit / ROW_ITEMS; // the number of rows that results from limit
int leftOver = limit % ROW_ITEMS; // see if we have incomplete rows
if (leftOver != 0) {
rows += 1;
}
int id = 1000; // the ids of the ImageViews 1000, 1001, 1002 etc
int belowId = R.id.date; // this id will be used to position the ImageView on another row
while (rows > 0) {
int realItemsPerRow = ROW_ITEMS;
if (leftOver != 0 & rows == 1) {
realItemsPerRow = Math.min(ROW_ITEMS, leftOver);
}
for (int i = 0; i < realItemsPerRow; i++) {
final ImageView imageView = new ImageView(this);
imageView.setId(id);
imageView.setImageResource(R.drawable.ic_launcher);
RelativeLayout.LayoutParams lp = new RelativeLayout.LayoutParams(
RelativeLayout.LayoutParams.WRAP_CONTENT,
RelativeLayout.LayoutParams.WRAP_CONTENT);
imageView.setPadding(10, 10, 0, 0);
imageView.setAdjustViewBounds(true);
imageView.setMaxHeight(80);
imageView.setMaxWidth(80);
if (i == 0) {
lp.addRule(RelativeLayout.ALIGN_PARENT_LEFT, RelativeLayout.TRUE);
} else {
lp.addRule(RelativeLayout.RIGHT_OF, imageView.getId() - 1);
}
lp.addRule(RelativeLayout.BELOW, belowId);
imageView.setLayoutParams(lp);
mainLayout.addView(imageView);
id++;
}
belowId = id - 1;
rows--;
}
Also, as kcoppock already said in his comment, it might be worth looking at the GridView for efficiency.

Categories

Resources