LayoutParams
suggest changeEvery 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’sLinearLayout.LayoutParams
RelativeLayout
it’sRelativeLayout.LayoutParams
CoordinatorLayout
it’sCoordinatorLayout.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
andlayout_gravity
will be stored in aLinearLayout.LayoutParams
object and used by theLinearLayout
gravity
,text
andtextColor
will be used by theTextView
itself
For ImageView
:
layout_width
,layout_height
andlayout_weight
will be stored in aLinearLayout.LayoutParams
object and used by theLinearLayout
background
,scaleType
andsrc
will be used by theImageView
itself
Getting 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