Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to use the center of a View as a reference point inside a RelativeLayout

I've been using a bit of a hack to stretch a view inside a parent RelativeLayout so that it starts at top-left and ends an bottom-center. While RelativeLayout does let you position something at the center of itself, it doesn't however seem to let you stretch something to that same point.

My solution was simple, position something in that center, and give it 1px dimensions so its the actual center of the parent RelativeLayout. Don't get me wrong, this works and I've had no issues whatsoever with it, but if there's a better practice that this I'd like to know about it.

As for a graphical representation of what I'm talking about, let me add a few images illustrating.

                                                enter image description here

This first image has a text-less TextView positioned at the center of the RelativeLayout and I've given it a width of 0dp. This allows me as you can see in the next image to place anything, relative to that center. My point being that it strikes me as odd that you can't do that without the need of adding the extra view at the center, for I can see properties such as Layout to left of or Layout to right of but no Layout to center of.

                                                 enter image description here

So the scennario may be a bit more in the lines of, "it's not broken yet but I'm afraid it will pop at any minute". Then on the other hand if this is the correct way of doing it and I help someone learning a new thing, that also works for me.

Why do I ask questions that don't get answered!? I'm so setting a bounty here..

The most sensible thing suggested yet (to my judgement) is that I replace my LinearLayout with a View which I would assume takes a little less memory, even if it's marginally less. So I'm thanking @yorkw for it. I'm surprised that nobody's asked this before.

Just to clarify since there seems to be a misunderstanding as to what I'm actually after. I don't want something to take half of the parent width/height. I was asking for a way to use it as a reference point (that's what I said in the title) so I can do stuff like, position an image to the left of the center without adding a linear layout that takes half and the gravity left or whatever.

Update

Since API 14 we have Space available which is a lightweight View subclass that may be more suitable for this kind of hack.

like image 616
Juan Cortés Avatar asked May 25 '12 08:05

Juan Cortés


People also ask

Which XML attribute can be used to put a view in front of other views?

bringToFront()” method will let you a perfect indicator view :) Also, there is another option to use a parent-children relationship views.

How do I center a view in XML?

You can apply a centering to any View, including a Layout, by using the XML attribute android:layout_gravity". You probably want to give it the value "center".

Which Layout attribute specifies the specifies the position of the child views?

RelativeLayout lets child views specify their position relative to the parent view or to each other (specified by ID). So you can align two elements by right border, or make one below another, centered in the screen, centered left, and so on.


2 Answers

I like your present solution, but if you want to avoid the funky invisible thin centering widget, you can accomplish that as follows:

  • Calculate containerWidth as the pixel width of your containing RelativeLayout-derived class (call this MyRelativeLayout)
  • Create an instance of MyRelativeLayout.LayoutParams called leftHalfWidgetLayoutParams
  • Set leftHalfWidgetLayoutParams.width = containerWidth / 2, either using the constructor argument when it is created above, or after the fact. After the fact is necessary if you want to adjust it later (e.g., in an override of onSizeChanged() in MyRelativeLayout).
  • Each time you set or change leftHalfWidgetLayoutParams.width, invoke leftHalfWidget.setLayoutParams(leftHalfWidgetLayoutParams).
  • Call requestLayout() if required to redraw MyRelativeLayout each time the width changes

If the widgets to the right of center are overly large, it might be necessary to set their layout width values explicitly, too, to stop them from encroaching into the left half of the container.

Now I realize that this loses some of the "magic" of having RelativeLayout do everything automatically, and that's where your approach is actually nicer. But RelativeLayout is still going to enforce the relative positions of your widgets as well as it can, given the added constraint of the width that will have been added to the layout parameters of your leftHalfWidget, so you wouldn't be overriding or abandoning its overall contribution in that regard.

I can't think of a way to meet your requirements inside a RelativeLayout without explicitly setting the width value on the layout parameters in the manner described above. It's an alternative approach to yours, but not necessarily a better one.

I would point out that if your left-half widget is always going to take up the left half of the container, then I can't see why a horizontal LinearLayout (instead of a RelativeLayout) at the top level (with a weight of 0.5 for your left-size widget with an equally-weighted right side RelativeLayout for the remaining right half), would not be a good solution. The "relative" stuff would, in that case, only be going on within that right half anyway, so why use RelativeLayout at the top level when LinearLayout could do the job more concisely? But perhaps you want to use RelativeLayout on the left side to deal with vertical relationships, and you therefore might actually have more than one control within that left side.

like image 51
Carl Avatar answered Sep 24 '22 19:09

Carl


To achieve what you are doing, I use a LinearLayout, layout_width=0dip and layout_weight=50. But it is not optimal as it nests another layout inside the linear layout. I'd be curious to see if another better solution is available.

like image 31
Vincent Mimoun-Prat Avatar answered Sep 25 '22 19:09

Vincent Mimoun-Prat