Skip to content

Custom layout attributes

ZieIony edited this page Oct 25, 2019 · 1 revision

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.

Clone this wiki locally