Every single ViewGroup
(e.g. LinearLayout
, RelativeLayout
, CoordinatorLayout
, etc.) needs to store information about its children's properties. About the way its children are being laid out in the ViewGroup
. This information is stored in objects of a wrapper class ViewGroup.LayoutParams
.
To include parameters specific to a particular layout type, ViewGroups
use subclasses of ViewGroup.LayoutParams
class.
E.g. for
LinearLayout
it's LinearLayout.LayoutParams
RelativeLayout
it's RelativeLayout.LayoutParams
CoordinatorLayout
it's CoordinatorLayout.LayoutParams
Most of ViewGroups
reutilize the ability to set margins
for their children, so they do not subclass ViewGroup.LayoutParams
directly, but they subclass ViewGroup.MarginLayoutParams
instead (which itself is a subclass of ViewGroup.LayoutParams
).
LayoutParams
in xml
LayoutParams
objects are created based on the inflated layout xml
file.
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<TextView
android:layout_width="wrap_content"
android:layout_height="50dp"
android:layout_gravity="right"
android:gravity="bottom"
android:text="Example text"
android:textColor="@android:color/holo_green_dark"/>
<ImageView
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:background="@android:color/holo_green_dark"
android:scaleType="centerInside"
android:src="@drawable/example"/>
</LinearLayout>
All parameters that begin with layout_
specify how the enclosing layout should work. When the layout is inflated, those parameters are wrapped in a proper LayoutParams
object, that later will be used by the Layout
to properly position a particular View
within the ViewGroup
. Other attributes of a View
are directly View
-related and are processed by the View
itself.
For TextView
:
layout_width
, layout_height
and layout_gravity
will be stored in a LinearLayout.LayoutParams
object and used by the LinearLayout
gravity
, text
and textColor
will be used by the TextView
itselfFor ImageView
:
layout_width
, layout_height
and layout_weight
will be stored in a LinearLayout.LayoutParams
object and used by the LinearLayout
background
, scaleType
and src
will be used by the ImageView
itselfGetting LayoutParams
object
getLayoutParams
is a View's
method that allows to retrieve a current LayoutParams
object.
Because the LayoutParams
object is directly related to the enclosing ViewGroup
, this method will return a non-null value only when View
is attached to the ViewGroup
. You need to bare in mind that this object might not be present at all times. Especially you should not depend on having it inside View's
constructor.
public class ExampleView extends View {
public ExampleView(Context context) {
super(context);
setupView(context);
}
public ExampleView(Context context, AttributeSet attrs) {
super(context, attrs);
setupView(context);
}
public ExampleView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
setupView(context);
}
private void setupView(Context context) {
if (getLayoutParams().height == 50){ // DO NOT DO THIS!
// This might produce NullPointerException
doSomething();
}
}
//...
}
If you want to depend on having LayoutParams
object, you should use onAttachedToWindow
method instead.
public class ExampleView extends View {
public ExampleView(Context context) {
super(context);
}
public ExampleView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public ExampleView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
@Override
protected void onAttachedToWindow() {
super.onAttachedToWindow();
if (getLayoutParams().height == 50) { // getLayoutParams() will NOT return null here
doSomething();
}
}
//...
}
Casting LayoutParams
object
You might need to use features that are specific to a particular ViewGroup
(e.g. you might want to programmatically change rules of a RelativeLayout
). For that purpose you will need to know how to properly cast the ViewGroup.LayoutParams
object.
This might be a bit confusing when getting a LayoutParams
object for a child View
that actually is another ViewGroup
.
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/outer_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<FrameLayout
android:id="@+id/inner_layout"
android:layout_width="match_parent"
android:layout_height="50dp"
android:layout_gravity="right"/>
</LinearLayout>
IMPORTANT: The type of LayoutParams
object is directly related to the type of the ENCLOSING ViewGroup
.
Incorrect casting:
FrameLayout innerLayout = (FrameLayout)findViewById(R.id.inner_layout);
FrameLayout.LayoutParams par = (FrameLayout.LayoutParams) innerLayout.getLayoutParams();
// INCORRECT! This will produce ClassCastException
Correct casting:
FrameLayout innerLayout = (FrameLayout)findViewById(R.id.inner_layout);
LinearLayout.LayoutParams par = (LinearLayout.LayoutParams) innerLayout.getLayoutParams();
// CORRECT! the enclosing layout is a LinearLayout