-
Notifications
You must be signed in to change notification settings - Fork 55
Custom layout attributes
LayoutParams
classes have their own style attributes. You can spot them in layout XMLs. The following button has four inline style attributes. android:text
is used by the Button
class. The rest of the attributes (starting with layout_) is used by LayoutParams
classes - android:layout_width
and android:layout_height
by plain LayoutParams
and android:layout_margin
by MarginLayoutParams.
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="8dp"
android:text="OK" />
Adding custom layout attributes is very similar to adding custom view attributes. You also need to declare attributes, a styleable, read the attributes using obtainStyledAttributes()
and the value getters, etc. Only the place, where all of that attribute parsing and storing happens is different.
<declare-styleable name="FlowLayout">
<attr name="android:gravity" />
</declare-styleable>
<declare-styleable name="FlowLayout_Layout">
<attr name="guide_layout_fill" format="boolean" />
</declare-styleable>
By convention layout styleables are named after the owning layout with _Layout suffix. I like to also add _layout prefix to attributes' names. The rest is identical to the usual styleables.
public class FlowLayout extends FrameLayout {
public static class LayoutParams extends FrameLayout.LayoutParams {
private boolean fill = false;
public LayoutParams(Context c, AttributeSet attrs) {
super(c, attrs);
TypedArray a = c.obtainStyledAttributes(attrs, R.styleable.FlowLayout_Layout);
fill = a.getBoolean(R.styleable.FlowLayout_Layout_guide_layout_fill, false);
a.recycle();
}
}
}
LayoutParams
usually are implemented as static classes inside their owning layouts. The most interesting part of a LayoutParams
class is the XML constructor - very similar to views' XML constructors. The attrs
parameter contains values of style attributes. You can get the layout style attributes from there. Complete example code can be found here.
For the layout to use the new LayoutParams
class you have to override a couple of methods:
public class FlowLayout extends FrameLayout {
// ..
@Override
protected LayoutParams generateDefaultLayoutParams() {
return new LayoutParams(super.generateDefaultLayoutParams());
}
@Override
public LayoutParams generateLayoutParams(AttributeSet attrs) {
return new LayoutParams(getContext(), attrs);
}
@Override
protected LayoutParams generateLayoutParams(ViewGroup.LayoutParams p) {
return new LayoutParams(p);
}
}
From now on each child of this layout will get an instance of FlowLayout.LayoutParams
as their layout params.