In a ListView getview() method, I build my layout like this :
LinearLayout layout = new LinearLayout(context);
layout.setLayoutParams(new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, 200));
layout.setWeightSum(120);
for (int i = 0; i < totalTVNumber; i++) {
LifeEvent event = getEventFromDB(cost, position);
if (event != null) {
TextView eventTV [![enter image description here][1]][1]= event.getTextView(getContext());
eventTV.setLayoutParams(new LinearLayout.LayoutParams(0, 200, getTheWeight(eventTV)));
layout.addView(eventTV);
}
}
The problem is that doing this will cause my view not to be exactly aligned vertically. Since they have the same height than the layout, I expected them to match it but some views (nearly 1 on 2) act like they have a little margin-top. Of course there is nothing like a margin-top in my code, and reading their margin onClick returns 0.
Adding layout.setGravity(Gravity.TOP); doesnt change anything, and adding eventTV.setGravity(Gravity.TOP); just put the text on the top of the TV.
Note that if I go for MATCH_PARENT intead of 200 for the event, it acts exactly as expected, but I would like the views to be a little smaller than the layout, to get a little gap between them.
In case it matters, a LinearLayout can have from 2 to 9 textviews inside, and their weight are calculated to sum to 120 (for instance 44+34+2+40). Horizontal behaviour is ok.
How can I align view on the top of my horizontal linearlayout ?
EDIT : here is a screenshot :
Related
I am designing a title row that has the item title in the middle, with a status description on the left and expiration date description on the right. The title should be centered at all times and expand width until it runs into either of the side views, at which time it should get ellipsized. I'm having trouble figuring out how to keep the title view centered while allowing for the two side views to have different sizes, while also trying to show as much of the text as possible in cases where the side views have only two or three characters, or as many as 20.
This is NOT a basic question of having the center view fill the space. The cases will outline the additional requirements I have that make it more tricky.
I tried two main approaches:
LinearLayout
I started with a horizontal LinearLayout. The first and third TextViews had widths of WRAP_CONTENT while the center title view had a width of 0dp and weight of 1, allowing it to fill the middle section of the row. The issue here was that the first and third views wouldn't have the same width with WRAP_CONTENT, so the title view would be shifted one way or the other. See here how the title is shifted to the left towards the smaller text:
After that, I assigned a weightSum of 20 to the LinearLayout, gave weights of 4 to the first and third views, a weight of 12 to the middle view, and width of 0dp for all 3. This worked better but wouldn't allow for longer text in the end views, even when there was plenty of room in the row for the view to expand:
Changing the views to use layout_weight and widths of WRAP_CONTENT didn't work either.
ConstraintLayout
I switch the row to a ConstraintLayout to try that as well.
I started this route with the end views using WRAP_CONTENT as their width and the title view using 0dp. The title view had its start linked to the end of the first view, and its end linked to the start of the last view. Of course, this would shift the title view towards whichever end text was shorter. Changing the end views to a width of 0dp yielded the same result.
From here I got closer. I linked the middle view's start and end to the parent LinearLayout so that it stretched the entire width. Then I linked the first view's end to the middle view's start, and the last view's start to the middle view's end, and set both of their widths to 0dp. By setting the middle view's width to 0dp and adding a marginStart and marginEnd of 64dp, I allowed some space for the first and last views to be shown. Still, this was like the LinearLayout solution with weights, as the gaps on each side of the middle view was of the fixed 64dp size, and didn't allow for expansion.
My last effort was so close! Changing the middle view's width to WRAP_CONTENT, and start and end both linked to the parent, allowed the end views to be of equal widths, and fully expanded. That is, UNTIL the title view became very long. With a width of WRAP_CONTENT, the middle view would push the end views off the screen with a very long text, even with a min_width set on the end views.
Changing the end views to have widths of WRAP_CONTENT didn't work either.
What I want to accomplish is most like this last try, except that I want the middle view to stop expanding and become ellipsized instead of pushing the end views out. Any other ideas to try?
The problem is if you want the first and third views equal width I don't think it is possible with just standard xml layouts as it's too late once a view has been sized, it won't be resized again without extra code.
Something like TableLayout has the extra code to resize all the rows to match, one it's sized them individually.
But you can to this yourself programmatically
e.g
public class MainActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
LinearLayout mainLayout = findViewById(R.id.content);
// Wait until mainLayout has it's size calculated
ViewTreeObserver.OnGlobalLayoutListener mGlobalLayoutListener = new ViewTreeObserver.OnGlobalLayoutListener() {
#Override
public void onGlobalLayout() {
// Don't listen anymore
mainLayout.getViewTreeObserver().removeOnGlobalLayoutListener(this);
TextView col1 = new TextView(getApplicationContext());
TextView col2 = new TextView(getApplicationContext());
TextView col3 = new TextView(getApplicationContext());
col1.setText("Much Long");
col1.setBackgroundColor(Color.CYAN);
col3.setText("Long");
col3.setBackgroundColor(Color.CYAN);
col3.setGravity(Gravity.RIGHT);
col2.setText("Really Really Really Really Really Really Really Really Really Long");
col2.setGravity(Gravity.CENTER_HORIZONTAL);
col2.setSingleLine(true);
// Set it to have Ellipsizes if too long
TextUtils.TruncateAt truncate = TextUtils.TruncateAt.END;
col2.setEllipsize(truncate);
int measureSpec = View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED); // As big as the view wants to be
// Measure all the views
col1.measure(measureSpec, measureSpec);
col2.measure(measureSpec, measureSpec);
col3.measure(measureSpec, measureSpec);
// work which side is bigger
int maxWidth = Math.max(col1.getMeasuredWidth(), col3.getMeasuredWidth());
int parentWidth = mainLayout.getWidth();
// Probably should have some checks to make sure centre width does not go negative
int centreWidth = parentWidth - (2 * maxWidth);
col1.setWidth(maxWidth);
col2.setWidth(centreWidth);
col3.setWidth(maxWidth);
mainLayout.addView(col1);
mainLayout.addView(col2);
mainLayout.addView(col3);
}
};
mainLayout.getViewTreeObserver().addOnGlobalLayoutListener(mGlobalLayoutListener);
}
}
Produces some examples
The centre of the middle column is always at the centre of the screen
I'm building an android app that does 3 variations of a similar calculation.
I have an imageview, three radiobuttons, and four textviews inside the imageview that display inputs/results. I have editext for actual input and a button to do the calculation. That is not my problem.
I can load the appropriate image by checking appropriate radiobutton As each image is slightly different I'd like to reposition the the textview with each image so they line up with the image better.
During layout design I loaded the appropriate, positioned the textviews where I want them and copied down the Horizontal and Vertical bias numbers.
Can't figure out how to change the bias to move the textview when I change the image.
I'm using constraint layout.
Thanks Steve
The ConstraintLayout.LayoutParams class has two fields: horizontalBias and verticalBias. You can therefore update the bias values for any view that is a child of a ConstraintLayout like this:
ConstraintLayout.LayoutParams params = (ConstraintLayout.LayoutParams) view.getLayoutParams();
params.verticalBias = 0.3f;
view.setLayoutParams(params);
I have this code:
final RelativeLayout headerRl=new RelativeLayout(SpeakersActivity.this);
headerRl.setBackgroundColor(Color.parseColor(almacen.getColor()));
final TextView initial=new TextView(SpeakersActivity.this);
final RelativeLayout.LayoutParams headerParams=new RelativeLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, 80);
headerParams.addRule(RelativeLayout.CENTER_VERTICAL,RelativeLayout.TRUE);
initial.setText(arrayInitials.get(i));
initial.setTextColor(getColor(R.color.white));
initial.setTextSize(16);
initial.setPadding(10,0,0,0);
runOnUiThread(new Runnable() {
#Override
public void run() {
headerRl.addView(initial,headerParams);
ll.addView(headerRl);
}
});
"ll" is a LinearLayout. I am adding the rule on a RelativeLayout.LayoutParams, I am adding the view to a RelativeLayout, which is added to a LinearLayout. But my view is not centered vertically. I tried to center it horizontally to see if it was working, but it isn't. Why is my view not centered in the RL? How to center it?
Thank you.
Depending on what result you are expecting
There are 2 ways to deal with your problem.
First one:
The issue is in the headerRl which is set by default as wrap_content, wrap_content
So, what you need is to define it's layout params with match_parent:
headerRlLayoutParams = ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT)
headerRl.setLayoutParams(headerRlLayoutParams)
The first parameter could be wrap_content, depends on what you want, but the second one should be match_parent, otherwise, it will be wrap_content by default which will position your view at the top
Create headerParams as headerParams = new RelativeLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT...
And that's it.
Match parent here causes your view to take the whole parent's width. If that's what you want, then see the second option below
Second one:
If you want your view as match_parent and take the whole view, then
your issue is:
new RelativeLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT
Which cause your text view to be match_parent in the layout. And because you didn't set view's gravity - text has default one - top/start.
And the solution is simple - Set TextView Gravity (which same as setting gravity param in the XML) - the view will stay as match_parent - taking the whole width of its parent's layout but the text will be centered vertically
initial.setGravity(Gravity.CENTER_VERTICAL);
And a small hint - You also can set in developer options "show layout bounds" to see how much space your layout takes and how views are positioned them self in the layout. This could help to debug and understand what exactly is going wrong
initial.setGravity(Gravity.CENTER_VERTICAL);
Try with
final RelativeLayout.LayoutParams headerParams=new RelativeLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, 80);
/**
* Rule that centers the child vertically with respect to the
* bounds of its RelativeLayout parent.
*/
headerParams.addRule(RelativeLayout.CENTER_VERTICAL,RelativeLayout.TRUE);
// your textview
initial.setGravity(Gravity.CENTER_VERTICAL);
I am currently learning android and I am trying to create an array of buttons for my app in the following manner:
LinearLayout answer_layout = (LinearLayout)findViewById(R.id.answer_layout);
idCount = answer_layout.getId() + 1000;
for(int i = 0 ; i<letters.length ; i++)
{
Button b = new Button(this);
b.setText(letters[i]);
b.setTypeface(null, Typeface.BOLD);
b.setBackgroundResource(R.drawable.puzzletilebg);
b.setTextSize(TypedValue.COMPLEX_UNIT_SP, 15);
b.setIncludeFontPadding(false);
b.setLayoutParams(new LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.WRAP_CONTENT));
b.setId(idCount + i);
b.setTag(Integer.valueOf(i));
bLetters[i] = b;
answer_layout.addView(b);
}
}
When i run this code, i am able to get a row of buttons depending on the length value of string. My problem is the buttons appear stretched and when the length value is more than 7, The buttons dont appear. For this problem i tried implementing the method suggested here(How do I programmatically add buttons into layout one by one in several lines?) but i didnt get any result. What parameters do i have to use to make the shape of the buttons as a perfect square and make sure they are of the same size for all screen sizes? My button background drawable size is 50x50.
If you want a perfect square change
LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.WRAP_CONTENT));
to
LinearLayout.LayoutParams(50, 50);
And ofc if your linearLayour is horizontal the buttons will dissapear
on the edge of the screen.
You can use Gridlayout instead of LinearLayout, but if you want something like the LinearLayout i recommend: FlowLayout
example:
Last edit: sorry is not AutoFitLayout is FlowLayout i edited the answer;
Solve your problem?
Instead of LinearLayout use a GridLayout
Try with
b.setWidth(50);
b.setHeight(50);
The numbers are pixels, so maybe you have to convert dp to pixels.
For the problem with button more than 7 not appear, you could try to wrap your LinearLayout answer_layout in a ScrollView or HorizontalScrollView for horizontal scroll behaviour in the xml file.
And for programmatically change the width and the height of the button, you could try this answer https://stackoverflow.com/a/11294075/1331743
from existing post.
I have a table layout where each row is built programmatically.
The structure is basically, for each row:
TextView, LinearLayout, LinearLayout, LinearLayout, Button.
Each of the LinearLayout has multiple ImageViews inside of them. I want to increase the spacing between the ImageView items as they render with their borders touching.
I tried the suggestions here - In Android, how to make space between LinearLayout children? - I create the parameters like so:
LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.FillParent, LinearLayout.LayoutParams.WrapContent);
And set it like this to an image view when adding the control:
linearLayout1.AddView(image1);
linearLayout1.AddView(image2, layoutParams);
linearLayout1.AddView(image3);
Note I am only setting it on the middle item as a left & right margin on this would be fine for what I am trying to achieve.
The problem is that even without setting any margins on the layout params i.e. just instantiating it and setting it as shown above, it adds about a 35px margin to the left causing a much larger margin than I wanted. Even calling SetMargins with 1px doesn't change the margin.
Where am I going wrong?
set width of linear layout as WrapContent like this
LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.WrapContent, LinearLayout.LayoutParams.WrapContent);