addRule in RelativeLayout.LayoutParams is not working - android

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);

Related

Android Row: How to make first and third views' widths equal to the widest of them, with the middle view expanding to fill the row

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

reposition textview in constraint layout dynamically

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);

Adding a margin to ImageView programmatically

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);

Android layoutparms scrollvew height

I have a tableview inside of a scrollview. I want to reserve space for a listview 2/3 of the screen. I am getting the height of the screen, and will divide that in 2/3 and set the height of the ScrollView. But even with manually x and y numbers its blowing up.
App is crashing when I set the ScrollView width and height like this:
ScrollView sv = (ScrollView)findViewById(R.id.usdScroll);
ScrollView.LayoutParams layoutParams = new ScrollView.LayoutParams( -1, 550);
sv.setLayoutParams(layoutParams);
Any ideas what I did wrong?
You can use the layout_weight attribute to specify how much of a view the specific component will use, e.g. android:layout_weight=2. So for your listView set a weight of 1 and a weight of 2 for your tableview, I think. Anyway, play with the weight setting and you can split the view in any ratio you like.
LayoutParams is used to tell their parents how they want to be laid out. So the layout param's type which you set to must match its parent class type exactly.
and here is a better solution, using layout_weight instead. Try this please
<ScrollView android:layout_weight="1" ........></ScrollView>
<ListView android:layout_weight="2" ........></ListView>

How to set fixed size and position of a RelativeLayout?

Android implemented a default layout rule, like measure, layout, etc, I didn't find out there is a method to set such a fixed size. How to get rid of that default layout behavior?
Actually, in my case, every view is supposed to be relative to its parent, and will have a specified size., how could I do?
Thx
Not sure if I correctly understood your issue, but you can specify size of certain View (e.g. RelativeLayout, LinearLayout or certain control). In Properties of your layout view (Layout width, Layout height) you do not need to use only wrap_content or fill_parent. You are also allowed to type size like 40dip.
If you created your View dinamically, then you should set LayoutParams. For example, to define your element size and margins for RelativeLayout (similar for others) you should use something like:
RelativeLayout.LayoutParams adaptLayout = new RelativeLayout.LayoutParams(element_width, element_height);
adaptLayout.setMargins(marginLeft, marginTop, marginRight, marginBottom);
mLinearLayoutForm.setLayoutParams(adaptLayout);

Categories

Resources