¿Por qué funcionan los parámetros de diseño en la programación de Android?

First off my background: I'm new to Java coming over from Ruby. If that helps.

I'm confused about how layout params work. I'm following a basic Hello World introduction to creating an Android App. Step 1, extend the Activity class, and the onCreate() method to access the XML layout. Ok I get that.

Then I create a layout (say a RelativeLayout) in the Main.XML. So this is making use of the RelativeLayout class which extends the ViewGroup class, ok so far. Then lets say I create a button inside this. This is where my question starts. If I look at the example I am following I see attributes being assigned to the button that belong to the RelativeLayout class (i.e: android:layout_alignParentRight="true"). These seem to be the layout params. But why does this work? The button class seems to inherit from the View class. Why can a button object accept attributes for the RelativeLayout object? Maybe my Ruby programming is confusing me..

¡Gracias!

Update: For posterity sake: thank you to Slothsberry for pointing out the XML Layouts link, which seems to describe the answer clearly in 2 sections the section on "Attributes" and on "Layout Paramters". The attributes section reads:

Every View and ViewGroup object supports their own variety of XML attributes. Some attributes are specific to a View object (for example, TextView supports the textSize attribute), but these attributes are also inherited by any View objects that may extend this class. Some are common to all View objects, because they are inherited from the root View class (like the id attribute). And, other attributes are considered "layout parameters," which are attributes that describe certain layout orientations of the View object, as defined by that object's parent ViewGroup object.

The layout parameters section though is perhaps the section that really answers this question. Where it states:

Every ViewGroup class implements a nested class that extends ViewGroup.LayoutParams. This subclass contains property types that define the size and position for each child view, as appropriate for the view group. As you can see in figure 1, the parent view group defines layout parameters for each child view (including the child view group).

They give a nice diagram as well. It seems that a beginning programmer needs to recognize that while Java classes are referenced, the XML acts more like a CSS sheet and that attributes are first computed in a nested fashion before being computed and carried over to their Java class counterparts. That's my current understanding anyways :)

preguntado el 08 de noviembre de 11 a las 18:11

No, you're right to think this is weird. I've been programming in java for over 5 year, and this is something that when I first saw it made no sense to me. I'm still not sure why it works like this. Hopefully we'll get an answer. -

4 Respuestas

Layout parameters do not strictly mirror object inheritence (as you have noticed). The reason is that there are two parts of layout: configuring a view, and parametrizing a view's parent using that view as an argument.

So parameters like android:layout_below will be ignored if the parent layout is not a RelativeLayout. It might make sense from an OOP perspective to put that parameter in the RelativeLayout object. But that is how you would do it in the java code.

In the XML code, it takes the approach that the information about the child is contained in the child. layout parameters that require a parent that is not present will be ignored when the layout is inflated. Its a nice system android uses to make the XML more readable and portable. And it is not strictly referring to the class package structure, but rather the intuitive way humans think about placing things in a layout.

respondido 08 nov., 11:23

Thank you, you clearly understood my mis-understanding and gave a great answer. I've added notes in my question for posterity sake based some further readings. Appreciate it. - Inc1982

Understanding layout 'inflation' seems to be a key to understanding as well.. some more reading I found based on your answer: androidguys.com/2008/07/09/inflation-is-a-good-thing - Inc1982

I believe that the layout properties themselves are inherited in a strict manner, similar to class inheritance. However, what Android does with them seems to vary, depending on (at least) the parent element. In general, since you build layouts from the root downward (unless you're reusing includes, which have their own properties already set), you can just ignore the inappropriate properties for your elements. I hadn't even noticed that layout_below was available all the time, since I never looked at it unless I was in a RelativeLayout - Chris Bye

All layout elements in android inherit from View, although many indirectly.

The generic View class has properties (attributes) appropriate for ANY visible layout element. for the root layout, some properties such as Layout Gravity, Layout dimensions, etc. are set by the system (in most cases I believe).

If my root layout is some linear layout, Android will allow me to have a relative layout be a child in the root. Android will let me set various layout properties on the nested element, in order to control how it renders. This works the same for Button, and any other Android layout.

If you don't care about a particular property, don't set it. They are present to allow you control over the screens of your app. Look into XML Layouts or Hola vistas to get you started on the details.

respondido 08 nov., 11:22

Thank you for adding to the discussion. While I couldn't quite grok the issue from your answer your link to XML Layouts gave me what I needed. I've updated my question above to include what how I've resolved my understanding. You can let me know if that seems right. :) - Inc1982

you are a little bit confused, that layout param doesn't own a particular XML object . If you put it in one child XML XXXView or XXXLAyout , it will understand that its Right side must be in the same place than parent right.

Then if you don't create the layout params for that child , the child would try to inherit ones of its parent's.

respondido 08 nov., 11:23

Thanks for the response. Perhaps you can help me understand from a Android/Java perspective. Objects in Android have attributes, yes? I'd assume that all attributes have an owning object, yes? When I create a button tag you are saying that not all attributes defined within the button tag belong to the button object. Is that correct? - Inc1982

it depends in the place you put it . You must think that the object itself must be in another container . Then you are obey to tell the object the relative position to his parent. Of course we are only talking about relative layout . It isn't so different from CSS programming. Furthermore , exist also another XML tags which tells the child how to order into the parent . The system is flexible for that things. - A.Quiroga

disposición

Layout is a two pass process: a measure pass and a layout pass. The measuring pass is implemented in measure(int, int) and is a top-down traversal of the view tree. Each view pushes dimension specifications down the tree during the recursion. At the end of the measure pass, every view has stored its measurements. The second pass happens in layout(int, int, int, int) and is also top-down. During this pass each parent is responsible for positioning all of its children using the sizes computed in the measure pass.

When a view's measure() method returns, its getMeasuredWidth() y getMeasuredHeight() values must be set, along with those for all of that view's descendants. A view's measured width and measured height values must respect the constraints imposed by the view's parents. This guarantees that at the end of the measure pass, all parents accept all of their children's measurements. A parent view may call measure() more than once on its children. For example, the parent may measure each child once with unspecified dimensions to find out how big they want to be, then call measure() on them again with actual numbers if the sum of all the children's unconstrained sizes is too big or too small.

The measure pass uses two classes to communicate dimensions. The View.MeasureSpec class is used by views to tell their parents how they want to be measured and positioned. The base LayoutParams class just describes how big the view wants to be for both width and height. For each dimension, it can specify one of:

  • an exact number
  • MATCH_PARENT, which means the view wants to be as big as its parent (minus padding)
  • WRAP_CONTENT, which means that the view wants to be just big enough to enclose its content (plus padding).

There are subclasses of LayoutParams for different subclasses of ViewGroup. For example, AbsoluteLayout has its own subclass of LayoutParams which adds an X and Y value.

MeasureSpecs are used to push requirements down the tree from parent to child. A MeasureSpec can be in one of three modes:

  • UNSPECIFIED: This is used by a parent to determine the desired dimension of a child view. For example, a LinearLayout may call measure() on its child with the height set to UNSPECIFIED and a width of EXACTLY 240 to find out how tall the child view wants to be given a width of 240 pixels.
  • EXACTLY: This is used by the parent to impose an exact size on the child. The child must use this size, and guarantee that all of its descendants will fit within this size.
  • AT_MOST: This is used by the parent to impose a maximum size on the child. The child must guarantee that it and all of its descendants will fit within this size.

To initiate a layout, call requestLayout(). This method is typically called by a view on itself when it believes that is can no longer fit within its current bounds.

respondido 01 mar '18, 18:03

No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas or haz tu propia pregunta.